flat assembler
Message board for the users of flat assembler.

 Index > Main > Progress Bar Counting. Goto page Previous  1, 2
Author
edfed

Joined: 20 Feb 2006
Posts: 4242
Location: 2018
edfed
JohnFound wrote:
I usually avoid divisions and in this case I would make the progress bar a
multiple of 2 i.e. 64. That way your div becomes shr 6. There are even samples out there to divide by 80 (the console width) without using div instruction.

You have to divide to the size_of_the_whole, not the length of the progress bar. See the above formulas.
You can try to use subtraction instead of division (like in Bresenham's algorithm), but it will work only on incremental progress.

besenham can work in all direction with only one algo.

you just have to define the Xinc and Yinc =1.
test for sign of deltaY and deltaX, and negate the corresponding ?inc value.

then:
start at X0,Y0
load the absolute value of maximal delta as a counter
load the half of the absolute value of maximal delta as an initial condition of the substractive division.
then, you can start to compute the state of every dot along the maximal delta direction.

the besenham algo is not a good solution for the progress bar.
it is only good for interpolation beetwen two points, for example, create audio sample beetwen two samples, create a greyscale, create any line in any 2D environment (don't mean graphic only).
the progress bar is not 2D, it is 1D only, with a simple scale from a side to another of the same D that is the progress ratio vs the process size.
03 Aug 2011, 13:36
JohnFound

Joined: 16 Jun 2003
Posts: 3502
Location: Bulgaria
JohnFound
Bresenham's algorithm is not limited to 2D - it can be used for arbitrary dimensioned space. In the case of progress bar - it is 1D.
Although I still think, in the case of progress bar, simple formula computation with integer division will give the smallest and most clean and readable result.
03 Aug 2011, 14:02
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 17716
revolution
Erm, perhaps a reality check is in order here. 'div' is a perfectly sensible and appropriate instruction to use for computing things like progress bars. Ask yourself how often are you updating the bar? Perhaps not more than 10 times per second (and probably a bit less). You might save, say, 20 clock cycles per 'div' with an alternative. But it would take you at least 10, or more, minutes to program and debug the 'div' alternative. That equates to a payback time of 285 years (with a 3GHz CPU) before alternative 'div' methods become sensible to code. Doing 10 'div's a second by other methods (i.e. magic constants etc.) is not going to be worth all the extra coding and debugging effort required to replace the 'div'.

I hope I got the maths right there.
03 Aug 2011, 14:13
edfed

Joined: 20 Feb 2006
Posts: 4242
Location: 2018
edfed
you didn't consider the diffusion of code on the web.

let say, if a code is adopted in something used by 1 000 000 people, you can divide the payback time by one million. then, two days and 12 hours approximatelly.

but as div is a good instruction, present, let use it!!!
03 Aug 2011, 14:26
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 17716
revolution
edfed wrote:
you didn't consider the diffusion of code on the web.

let say, if a code is adopted in something used by 1 000 000 people, you can divide the payback time by one million. then, two days and 12 hours approximatelly.
Show me a million people that use their CPU at 100% constantly and then I will start writing alternative 'div' codes everywhere.
03 Aug 2011, 14:28
edfed

Joined: 20 Feb 2006
Posts: 4242
Location: 2018
edfed
everywhere there are critical real time applications, there are 100% use of CPU. it don't means it saturate it, but it can just use the maximal ressource it can just to be more real time, and maybe predict a little with the extra % it takes instead of let the cpu hlt.
03 Aug 2011, 14:32
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 17716
revolution
edfed wrote:
everywhere there are critical real time applications, there are 100% use of CPU. it don't means it saturate it, but it can just use the maximal ressource it can just to be more real time, and maybe predict a little with the extra % it takes instead of let the cpu hlt.
So what you need to do now is find one million of these overworked critical systems that also have operators watching progress bars all day.

03 Aug 2011, 14:45
edfed

Joined: 20 Feb 2006
Posts: 4242
Location: 2018
edfed
lol. insert A:
03 Aug 2011, 15:05
typedef

Joined: 25 Jul 2010
Posts: 2913
Location: 0x77760000
typedef

as George Bush would say "Internets"
03 Aug 2011, 15:32
edfed

Joined: 20 Feb 2006
Posts: 4242
Location: 2018
edfed
is the 23,993,564,998MB value exact?

a progress bar can also be used as a vu-meter. and there are a lot of vu-meters on a scenic console screen.
03 Aug 2011, 16:54
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 17716
revolution
edfed wrote:
is the 23,993,564,998MB value exact?
No. The exact byte count has been rounded too the nearest megabyte. So it could be wrong by as much as 2.08389e-9%
03 Aug 2011, 17:00
edfed

Joined: 20 Feb 2006
Posts: 4242
Location: 2018
edfed
if i run my apache server, we can add several megabytes to the count.
03 Aug 2011, 17:02

Joined: 25 Sep 2003
Posts: 2140
Location: Estonia
Actually I do get the algorithm and I've made progress bars before. What I meant is if your bar is 64 units in length, then your floppy image (1457664 bytes) download will happen in 64 increments. You would have to update your progressbar ONLY! when another 22776 bytes have passed not any sooner. No need to update 10 times per second.

Code is simple:
Code:
```mov eax,SIZE_OF_FILE ; 1457664
shr eax,6 ; progress bar increments
jz  .done
mov ebx,eax
;...
@@:
hlt
cmp  ebx,[transferred]
jnc  @b
call updateProgressBar
add  ebx,eax ;ebx has the new "epoch" to run to
jmp  @b
.done:
```

...and it didn't take 20minutes.

I'm afraid of using div because I know it behaves badly when you divide by 0 and you need to check for this before division. Next probleb is that is uses edx:eax so you need to clear edx because otherwise the results don't mean anything. What if you have already used edx? You'd need to move it to another register.

So I'm not only counting clocks with div, but the problem with it is that I need to do so much more than with mul or add or other simpler ALU operations.
04 Aug 2011, 07:20

Joined: 25 Sep 2003
Posts: 2140
Location: Estonia
The C code was using some bad coding habits, like using float counter. The divisions on integers (if counter were integer) are made in wrong order which makes the output always 0 or 100%, but never between. I noticed that float was used, which is totally unnecessary.

Also 100000000 wraps around at about 42% because of the 32-bit counters. In 64-bit I was able to easily overcome that problem.

Code:
```include 'win64a.inc'
format PE64 CONSOLE 5.0

invoke  GetStdHandle,STD_OUTPUT_HANDLE
mov     [hConsole],rax
invoke  GetConsoleScreenBufferInfo,[hConsole],sbi
mov     [iPercent],100000000;

mov     [rCounter],1
.for:
mov     rax,[rCounter]
cmp     rax,[iPercent]
jg      .end_for

xor     edx,edx
mov     rbx,[iPercent]
mov     rax,[rCounter]
imul    rax,54
div     rbx

mov     [iTmpMth1],rax

cmp     [iPrevCnt],rax
je      @f
movzx   ecx,word[sbi+6]
stdcall locate,rcx,[iTmpMth1],0,0
ccall   [printf],"%c",219
mov     rax,[iTmpMth1]
mov     [iPrevCnt],rax
@@:

xor     edx,edx
mov     rbx,[iPercent]
mov     rax,[rCounter]
imul    rax,100
div     rbx
mov     [iTmpMth1],rax

cmp     [iPrevLoc],rax
je      @f

movzx   ecx,word[sbi+6]
stdcall locate,rcx,67,0,0
ccall   [printf],"%d %",[iTmpMth1]
mov     rax,[iTmpMth1]
mov     [iPrevLoc],rax
@@:
jmp     .for
.end_for:
movzx   ecx,word[sbi+6]
stdcall locate,rcx,1,1,0
invoke  Sleep,2000
invoke  ExitProcess,0

proc locate row,col,show,shape
mov     [row],rcx
mov     [col],rdx
mov     rdx,[row]
sub     rdx,1
shl     rdx,16
sub     rdx,1
invoke  SetConsoleCursorPosition,[hConsole],rdx
mov     [cci+4],r8d ;visible
mov     [cci],r9d ;size
invoke  SetConsoleCursorInfo,[hConsole],cci
ret
endp

section '.idata' import data readable writeable

library kernel,'KERNEL32.DLL',\
msvcrt,'msvcrt.dll'

import kernel,\
GetStdHandle,'GetStdHandle',\
SetConsoleCursorPosition,'SetConsoleCursorPosition',\
SetConsoleCursorInfo,'SetConsoleCursorInfo',\
GetConsoleScreenBufferInfo,'GetConsoleScreenBufferInfo',\
ExitProcess,'ExitProcess',\
Sleep,'Sleep'

import msvcrt,\
printf,'printf'

hConsole dq ?
iPercent dq ?
iPrevCnt dq ?
iPrevLoc dq ?
iTmpMth1 dq ?
rCounter dq ?
sbi:     rb 2+2+2+8+2 ;CONSOLE_SCREEN_BUFFER_INFO
cci:     rb 4+4       ;CONSOLE_CURSOR_INFO
```

Its true that my idea, dividing backwards, only goes so far. Calculating percentage still needs division:
Code:
```include 'win64a.inc'
format PE64 CONSOLE 5.0

invoke  GetStdHandle,STD_OUTPUT_HANDLE
mov     [hConsole],rax
invoke  GetConsoleScreenBufferInfo,[hConsole],sbi
mov     [iPercent],100000000;

;Precalculate bar increments:
mov     rax,[iPercent]
shr     eax,6 ;Now uses 64 (2^6) unit bar
mov     [iIncrmnt],rax
mov     [iTmpMth1],rax
mov     [iCurLoc1],3

mov     [rCounter],1
.for:
mov     rax,[rCounter]
cmp     rax,[iPercent]
jg      .end_for

mov     rax,[iTmpMth1]
cmp     [rCounter],rax
jc      @f
movzx   ecx,word[sbi+6]
stdcall locate,rcx,[iCurLoc1],0,0
ccall   [printf],"%c",219
mov     rax,[iIncrmnt]
@@:

xor     edx,edx
mov     rbx,[iPercent]
mov     rax,[rCounter]
imul    rax,100
div     rbx
mov     [iTmpMth2],rax

cmp     [iPrevLoc],rax
je      @f

movzx   ecx,word[sbi+6]
stdcall locate,rcx,73,0,0
ccall   [printf],"%d %",[iTmpMth2]
mov     rax,[iTmpMth2]
mov     [iPrevLoc],rax
@@:

jmp     .for
.end_for:
movzx   ecx,word[sbi+6]
stdcall locate,rcx,1,1,0
invoke  Sleep,2000
invoke  ExitProcess,0

proc locate row,col,show,shape
sub     ecx,1
sub     edx,1
shl     ecx,16
mov     edx,ecx
push    r8 r9
invoke  SetConsoleCursorPosition,[hConsole],rdx
pop     r9 r8
mov     [cci+4],r8d ;visible
mov     [cci],r9d ;size
invoke  SetConsoleCursorInfo,[hConsole],cci
ret
endp

section '.idata' import data readable writeable

library kernel,'KERNEL32.DLL',\
msvcrt,'msvcrt.dll'

import kernel,\
GetStdHandle,'GetStdHandle',\
SetConsoleCursorPosition,'SetConsoleCursorPosition',\
SetConsoleCursorInfo,'SetConsoleCursorInfo',\
GetConsoleScreenBufferInfo,'GetConsoleScreenBufferInfo',\
ExitProcess,'ExitProcess',\
Sleep,'Sleep'

import msvcrt,\
printf,'printf'

hConsole dq ?
iPercent dq ?
iPrevCnt dq ?
iPrevLoc dq ?
iTmpMth1 dq ?
iTmpMth2 dq ?
iIncrmnt dq ?
iCurLoc1 dq ?
rCounter dq ?
sbi:     rb 2+2+2+8+2 ;CONSOLE_SCREEN_BUFFER_INFO
cci:     rb 4+4       ;CONSOLE_CURSOR_INFO
```

_________________
My updated idol http://www.agner.org/optimize/
04 Aug 2011, 09:25
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First

 Jump to: Select a forum Official----------------AssemblyPeripheria General----------------MainTutorials and ExamplesDOSWindowsLinuxUnixMenuetOS Specific----------------MacroinstructionsOS ConstructionIDE DevelopmentProjects and IdeasNon-x86 architecturesHigh Level LanguagesProgramming Language DesignCompiler Internals Other----------------FeedbackHeapTest Area
Goto page Previous  1, 2

Forum Rules:
 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum