flat assembler
Message board for the users of flat assembler.

 Index > Macroinstructions > Reciprocals macro
Author
 Thread
idle

Joined: 06 Jan 2011
Posts: 407
Location: Ukraine
idle

Code:
```; the macro generates constants to replace div by mul
; having questions, mail me to edemko@rambler.ru, or find me at www.board.flatassembler.net
; examples: rcp32 0
;           rcp32 1
;           rcp32 2
;           rcp32 10
;           rcp32 60
;           rcp32 100
;           rcp32 60*60
;           ...
macro rcp32 divisor*{
virtual at 0
local dvs
dvs = divisor

if dvs = 0 | dvs = 1
display 13, 10, 'division by ', dvs + '0', ' is easy'
err
end if

if dvs shr 32 <> 0
display 13, 10, 'divisor must be a 32bit value'
err
end if

repeat 31
if dvs = 1 shl %
display 13, 10, 'division by this power of 2 = dividend shr ', % / 10 + '0', % mod 10 + '0'
err
end if
end repeat

local dvd, quo, counter, stop_counter?
dvd = 1
quo = 0
counter = 0
stop_counter? = 0

repeat 32 + 31
dvd = dvd shl 1
quo = quo shl 1
if dvd >= dvs
dvd = dvd - dvs
quo = quo + 1
stop_counter? = 1
else
if stop_counter? = 0
counter = counter + 1
end if
end if
end repeat

display 13, 10, 'mov     eax,dividend',\
13, 10, 'mov     edx,\$'
dq quo shr 31
quo = quo shl counter shr 31 or 1
repeat 32 / 4
quo = quo shl 4
if quo and \$f'0000'0000 > \$9'0000'0000
quo = quo + \$7'0000'0000
end if
display quo shr 32 + '0'
quo = quo and \$ffff'ffff
if % = 4
display ''''
end if
end repeat
display ' ;normalized reciprocal(0.'
load quo qword from 0
repeat 18
quo = quo * 10
display quo shr 32 + '0'
quo = quo and \$ffff'ffff
end repeat
display ' * 2^', counter / 10 + '0', counter mod 10 + '0', ')',\
13, 10, 'mul     edx            ;multiply id est divide ',\
13, 10, 'shr     edx,', counter / 10 + '0', counter mod 10 + '0', '         ;compensate quotient'
end virtual
}

rcp32 10
```

I wish you code to be fast.
22 Jan 2011, 21:19
idle

Joined: 06 Jan 2011
Posts: 407
Location: Ukraine
idle
hi
this is a small revision
Tomasz, i think break if condition, and break stopping macro execution, would make a big deal

this...
Code:
```

;divisor = 0'000'000'010
mov     eax,dividend
mov     edx,\$CCCC'CCCD ;normalized reciprocal(0.099999999860301613 * 2^03)
mul     edx            ;multiply id est divide
shr     edx,03         ;compensate quotient

;divisor = 0'000'000'009
mov     eax,dividend
mov     edx,\$E38E'38E3 ;normalized reciprocal(0.111111111007630825 * 2^03)
mul     edx            ;multiply id est divide
shr     edx,03         ;compensate quotient

;divisor = 0'000'000'008
mov     eax,dividend
shr     eax,03         ;divisor is power of 2

;divisor = 0'000'000'007
mov     eax,dividend
mov     edx,\$9249'2493 ;normalized reciprocal(0.142857142724096775 * 2^02)
mul     edx            ;multiply id est divide
shr     edx,02         ;compensate quotient

;divisor = 0'000'000'006
mov     eax,dividend
mov     edx,\$AAAA'AAAB ;normalized reciprocal(0.166666666511446237 * 2^02)
mul     edx            ;multiply id est divide
shr     edx,02         ;compensate quotient

;divisor = 0'000'000'005
mov     eax,dividend
mov     edx,\$CCCC'CCCD ;normalized reciprocal(0.199999999953433871 * 2^02)
mul     edx            ;multiply id est divide
shr     edx,02         ;compensate quotient

;divisor = 0'000'000'004
mov     eax,dividend
shr     eax,02         ;divisor is power of 2

;divisor = 0'000'000'003
mov     eax,dividend
mov     edx,\$AAAA'AAAB ;normalized reciprocal(0.333333333255723118 * 2^01)
mul     edx            ;multiply id est divide
shr     edx,01         ;compensate quotient

;divisor = 0'000'000'002
mov     eax,dividend
shr     eax,01         ;divisor is power of 2

division by 1 is easy
```

...is generated by this
Code:
```; the macro generates constants to replace div by mul
; having questions, mail me to edemko@rambler.ru, or find me at www.board.flatassembler.net
; examples: rcp32 0
;           rcp32 1
;           rcp32 2
;           rcp32 10
;           rcp32 60
;           rcp32 100
;           rcp32 60*60
;           ...
macro rcp32 divisor*{
virtual at 0
local dvs
dvs = divisor

if dvs shr 32 <> 0
display 13, 10, 'divisor must be a 32bit value'
err
end if

if dvs < 2
display 13, 10, 'division by ', dvs + '0', ' is easy'
err
end if

display 13, 10, '                       ;divisor = ',\
dvs / 1'000'000'000         + '0',\
'''',\
(dvs / 0'100'000'000) mod 10 + '0',\
(dvs / 0'010'000'000) mod 10 + '0',\
(dvs / 0'001'000'000) mod 10 + '0',\
'''',\
(dvs / 0'000'100'000) mod 10 + '0',\
(dvs / 0'000'010'000) mod 10 + '0',\
(dvs / 0'000'001'000) mod 10 + '0',\
'''',\
(dvs / 0'000'000'100) mod 10 + '0',\
(dvs / 0'000'000'010) mod 10 + '0',\
dvs                  mod 10 + '0'

repeat 31
if dvs = 1 shl %
display 13, 10, 'mov     eax,dividend',\
13, 10, 'shr     eax,', % / 10 + '0', % mod 10 + '0', '         ;divisor is power of 2 '
dvs = 0
break
end if
end repeat

if dvs <> 0
local dvd, quo, counter, stop_counter?
dvd = 1
quo = 0
counter = 0
stop_counter? = 0

repeat 32 + 31
dvd = dvd shl 1
quo = quo shl 1
if dvd >= dvs
dvd = dvd - dvs
quo = quo + 1
stop_counter? = 1
else
if stop_counter? = 0
counter = counter + 1
end if
end if
end repeat

display 13, 10, 'mov     eax,dividend',\
13, 10, 'mov     edx,\$'
dq quo shr 31
quo = quo shl counter shr 31 or 1
repeat 32 / 4
quo = quo shl 4
if quo and \$f'0000'0000 > \$9'0000'0000
quo = quo + \$7'0000'0000
end if
display quo shr 32 + '0'
quo = quo and \$ffff'ffff
if % = 4
display ''''
end if
end repeat
display ' ;normalized reciprocal(0.'
load quo qword from 0
repeat 18
quo = quo * 10
display quo shr 32 + '0'
quo = quo and \$ffff'ffff
end repeat
display ' * 2^', counter / 10 + '0', counter mod 10 + '0', ')',\
13, 10, 'mul     edx            ;multiply id est divide ',\
13, 10, 'shr     edx,', counter / 10 + '0', counter mod 10 + '0', '         ;compensate quotient'
end if
end virtual
}

count equ 10
rept count var1:0{
display 13,10
rcp32 count-var1
}
```
23 Jan 2011, 06:55
idle

Joined: 06 Jan 2011
Posts: 407
Location: Ukraine
idle
this is v3:
- new hex macro
- fraction macro supports 64 bit fractions
- rounding corrected
- set LANG equ ENU to switch from RUS, that's the reason i did not put code directly

 Description: Download Filename: rcp.asm Filesize: 4.15 KB Downloaded: 152 Time(s)

31 Jan 2011, 06:30
idle

Joined: 06 Jan 2011
Posts: 407
Location: Ukraine
idle
this is v4:
- new hex macro
- rounding corrected, staying experimental
- english language only, i'm sorry, let me know and i'll write russian one
- macro supports check-code creation

main file:
Code:
```;show_hex <13,10,'\$'>, 00, 00, ';',\
;         <13,10,'\$'>, 01, 01, ';',\
;         <13,10,'\$'>, 02, 02, ';',\
;         <13,10,'\$'>, 03, 03, ';',\
;         <13,10,'\$'>, 04, 04, ';',\
;         <13,10,'\$'>, 05, 05, ';',\
;         <13,10,'\$'>, 06, 06, ';',\
;         <13,10,'\$'>, 07, 07, ';',\
;         <13,10,'\$'>, 08, 08, ';',\
;         <13,10,'\$'>, 09, 09, ';',\
;         <13,10,'\$'>, 10, 10, ';',\
;         <13,10,'\$'>, 11, 11, ';',\
;         <13,10,'\$'>, 12, 12, ';',\
;         <13,10,'\$'>, 13, 13, ';',\
;         <13,10,'\$'>, 14, 14, ';',\
;         <13,10,'\$'>, 15, 15, ';',\
;         <13,10,'\$'>, 16, 16, ';',\
;         <13,10,'\$'>, 17, 17, ';'
;
;repeat 18
;  show_hex <13,10,'\$'>, %-1, ';'
;end repeat
macro show_hex [intro, val, count, outro]{
common
local c, v, d
forward
display intro
c = count
if c > 0 & c < 17
v = val
while c > 0
c = c - 1
d = v shr (c * 4) and 1111b
display d + '0' + d/10*7
if c <> 0 & c mod 4 = 0
display ''''
end if
end while
end if
display outro
}

;show_frac <13,10,'2^-1       : '>, \$8000'0000'0000'0000, ';',\
;          <13,10,'2^-2       : '>, \$4000'0000'0000'0000, ';',\
;          <13,10,'2^-1 + 2^-2: '>, \$c000'0000'0000'0000, ';'
;
;repeat 64
;  show_frac <13,10>, 1 shl (%-1), ''
;end repeat
macro show_frac [intro, val, outro]{
common
local a, b
forward
display intro, '0.'
a = (val) and \$ffff'ffff
b = (val) shr 32
repeat 18
a = a * 10
b = b * 10 + a shr 32
display b shr 32 + '0'
a = a and \$ffff'ffff
b = b and \$ffff'ffff
if % = 18
display outro
else if % mod 3 = 0
display ''''
end if
end repeat
}

;repeat 17
;  display 13,10
;  rcp32 %-1
;end repeat
;
;repeat 17
;  display 13,10
;  rcp32 %-1, :)
;end repeat
macro rcp32 val, check{
local dvs
dvs = (val) and \$ffff'ffff
repeat 1
if dvs < 2
display 13, 10, ':) can you not divide by ', dvs + '0'
break
end if

local dvd, quo, cnt, cnt?
dvd  = 1
quo  = 0
cnt  = 0
cnt? = 1
repeat 64
dvd = dvd shl 1
quo = quo shl 1
if dvd < dvs
if cnt? = 1
cnt = cnt + 1
end if
else
cnt? = 0
dvd = dvd - dvs
quo = quo + 1
end if
end repeat

show_hex <13, 10, ';   divisor[\$1f..\$00] = \$'>  , dvs,  8, '',\
<13, 10, '; 1/divisor[\$1f..\$00] = \$0.'>, quo, 16, ''
show_frac '(', quo, ')'

repeat 31
if dvs = 1 shl %
show_hex <13, 10, 'code:   shr     eax,\$'>, %, 2, '           ; divisor is this power of two'
dvs = 0
break
end if
end repeat
if dvs = 0
break
end if

quo = quo shr (32-cnt-1)
if quo and 1 = 1
quo = quo + 10b
else
quo = quo or 10b
end if
quo = quo shr 1

show_hex <13, 10, 'code:   mov     edx,\$'>, quo, 8, '    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$', '', cnt, 2, '), and rounded',\
<13, 10, '        mul     edx               ; id est div :)'>, , 0, '',\
<13, 10, '        shr     edx,\$'>, cnt, 2, '           ; compensate quotient'

if ~ check eq
show_hex <13,10,'; use this code to check rcp32 over',\
13,10,'        call    check',\
13,10,'        jne     mail_edemko@rambler.ru_about_rounding_error',\
13,10,'        invoke  MessageBoxA,0,''rcp32 returned ok'',0,0',\
13,10,'        invoke  ExitProcess,0',\
13,10,'mail_edemko@rambler.ru_about_rounding_error:',\
13,10,'        hlt',\
13,10,'check:  mov     esi,\$'>,dvs,8,<\
13,10,'        or      ecx,-1',\
13,10,'  .loop:xor     edx,edx',\
13,10,'        mov     eax,ecx',\
13,10,'        div     esi',\
13,10,'        mov     ebx,eax',\
13,10,'        mov     eax,\$'>,'',quo,8,<\
13,10,'        mul     ecx',\
13,10,'        shr     edx,\$'>,'',cnt,2,<\
13,10,'        cmp     edx,ebx',\
13,10,'        loope   .loop',\
13,10,'        ret'>
end if
end repeat}
```

this...
Code:
```repeat 17
display 13,10
rcp32 %-1
end repeat
```

...creates this:
Code:
```

:) can you not divide by 0

:) can you not divide by 1

;   divisor[\$1f..\$00] = \$0000'0002
; 1/divisor[\$1f..\$00] = \$0.8000'0000'0000'0000(0.500'000'000'000'000'000)
code:   shr     eax,\$01           ; divisor is this power of two

;   divisor[\$1f..\$00] = \$0000'0003
; 1/divisor[\$1f..\$00] = \$0.5555'5555'5555'5555(0.333'333'333'333'333'333)
code:   mov     edx,\$AAAA'AAAB    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$01), and rounded
mul     edx               ; id est div :)
shr     edx,\$01           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'0004
; 1/divisor[\$1f..\$00] = \$0.4000'0000'0000'0000(0.250'000'000'000'000'000)
code:   shr     eax,\$02           ; divisor is this power of two

;   divisor[\$1f..\$00] = \$0000'0005
; 1/divisor[\$1f..\$00] = \$0.3333'3333'3333'3333(0.199'999'999'999'999'999)
code:   mov     edx,\$CCCC'CCCD    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$02), and rounded
mul     edx               ; id est div :)
shr     edx,\$02           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'0006
; 1/divisor[\$1f..\$00] = \$0.2AAA'AAAA'AAAA'AAAA(0.166'666'666'666'666'666)
code:   mov     edx,\$AAAA'AAAB    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$02), and rounded
mul     edx               ; id est div :)
shr     edx,\$02           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'0007
; 1/divisor[\$1f..\$00] = \$0.2492'4924'9249'2492(0.142'857'142'857'142'857)
code:   mov     edx,\$9249'2493    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$02), and rounded
mul     edx               ; id est div :)
shr     edx,\$02           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'0008
; 1/divisor[\$1f..\$00] = \$0.2000'0000'0000'0000(0.125'000'000'000'000'000)
code:   shr     eax,\$03           ; divisor is this power of two

;   divisor[\$1f..\$00] = \$0000'0009
; 1/divisor[\$1f..\$00] = \$0.1C71'C71C'71C7'1C71(0.111'111'111'111'111'111)
code:   mov     edx,\$E38E'38E4    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'000A
; 1/divisor[\$1f..\$00] = \$0.1999'9999'9999'9999(0.099'999'999'999'999'999)
code:   mov     edx,\$CCCC'CCCD    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'000B
; 1/divisor[\$1f..\$00] = \$0.1745'D174'5D17'45D1(0.090'909'090'909'090'909)
code:   mov     edx,\$BA2E'8BA3    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'000C
; 1/divisor[\$1f..\$00] = \$0.1555'5555'5555'5555(0.083'333'333'333'333'333)
code:   mov     edx,\$AAAA'AAAB    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'000D
; 1/divisor[\$1f..\$00] = \$0.13B1'3B13'B13B'13B1(0.076'923'076'923'076'923)
code:   mov     edx,\$9D89'D89E    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'000E
; 1/divisor[\$1f..\$00] = \$0.1249'2492'4924'9249(0.071'428'571'428'571'428)
code:   mov     edx,\$9249'2493    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'000F
; 1/divisor[\$1f..\$00] = \$0.1111'1111'1111'1111(0.066'666'666'666'666'666)
code:   mov     edx,\$8888'8889    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient

;   divisor[\$1f..\$00] = \$0000'0010
; 1/divisor[\$1f..\$00] = \$0.1000'0000'0000'0000(0.062'500'000'000'000'000)
code:   shr     eax,\$04           ; divisor is this power of two
```

this...
Code:
```repeat 17
display 13,10
rcp32 %-1, :)
end repeat
```

...creates this:
Code:
```

:) can you not divide by 0

:) can you not divide by 1

;   divisor[\$1f..\$00] = \$0000'0002
; 1/divisor[\$1f..\$00] = \$0.8000'0000'0000'0000(0.500'000'000'000'000'000)
code:   shr     eax,\$01           ; divisor is this power of two

;   divisor[\$1f..\$00] = \$0000'0003
; 1/divisor[\$1f..\$00] = \$0.5555'5555'5555'5555(0.333'333'333'333'333'333)
code:   mov     edx,\$AAAA'AAAB    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$01), and rounded
mul     edx               ; id est div :)
shr     edx,\$01           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'0003
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$AAAA'AAAB
mul     ecx
shr     edx,\$01
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'0004
; 1/divisor[\$1f..\$00] = \$0.4000'0000'0000'0000(0.250'000'000'000'000'000)
code:   shr     eax,\$02           ; divisor is this power of two

;   divisor[\$1f..\$00] = \$0000'0005
; 1/divisor[\$1f..\$00] = \$0.3333'3333'3333'3333(0.199'999'999'999'999'999)
code:   mov     edx,\$CCCC'CCCD    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$02), and rounded
mul     edx               ; id est div :)
shr     edx,\$02           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'0005
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$CCCC'CCCD
mul     ecx
shr     edx,\$02
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'0006
; 1/divisor[\$1f..\$00] = \$0.2AAA'AAAA'AAAA'AAAA(0.166'666'666'666'666'666)
code:   mov     edx,\$AAAA'AAAB    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$02), and rounded
mul     edx               ; id est div :)
shr     edx,\$02           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'0006
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$AAAA'AAAB
mul     ecx
shr     edx,\$02
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'0007
; 1/divisor[\$1f..\$00] = \$0.2492'4924'9249'2492(0.142'857'142'857'142'857)
code:   mov     edx,\$9249'2493    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$02), and rounded
mul     edx               ; id est div :)
shr     edx,\$02           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'0007
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$9249'2493
mul     ecx
shr     edx,\$02
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'0008
; 1/divisor[\$1f..\$00] = \$0.2000'0000'0000'0000(0.125'000'000'000'000'000)
code:   shr     eax,\$03           ; divisor is this power of two

;   divisor[\$1f..\$00] = \$0000'0009
; 1/divisor[\$1f..\$00] = \$0.1C71'C71C'71C7'1C71(0.111'111'111'111'111'111)
code:   mov     edx,\$E38E'38E4    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'0009
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$E38E'38E4
mul     ecx
shr     edx,\$03
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'000A
; 1/divisor[\$1f..\$00] = \$0.1999'9999'9999'9999(0.099'999'999'999'999'999)
code:   mov     edx,\$CCCC'CCCD    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'000A
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$CCCC'CCCD
mul     ecx
shr     edx,\$03
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'000B
; 1/divisor[\$1f..\$00] = \$0.1745'D174'5D17'45D1(0.090'909'090'909'090'909)
code:   mov     edx,\$BA2E'8BA3    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'000B
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$BA2E'8BA3
mul     ecx
shr     edx,\$03
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'000C
; 1/divisor[\$1f..\$00] = \$0.1555'5555'5555'5555(0.083'333'333'333'333'333)
code:   mov     edx,\$AAAA'AAAB    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'000C
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$AAAA'AAAB
mul     ecx
shr     edx,\$03
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'000D
; 1/divisor[\$1f..\$00] = \$0.13B1'3B13'B13B'13B1(0.076'923'076'923'076'923)
code:   mov     edx,\$9D89'D89E    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'000D
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$9D89'D89E
mul     ecx
shr     edx,\$03
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'000E
; 1/divisor[\$1f..\$00] = \$0.1249'2492'4924'9249(0.071'428'571'428'571'428)
code:   mov     edx,\$9249'2493    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'000E
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$9249'2493
mul     ecx
shr     edx,\$03
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'000F
; 1/divisor[\$1f..\$00] = \$0.1111'1111'1111'1111(0.066'666'666'666'666'666)
code:   mov     edx,\$8888'8889    ; 1/divisor[\$1f..\$00], converted to 32 bits(shr \$20-\$03), and rounded
mul     edx               ; id est div :)
shr     edx,\$03           ; compensate quotient
; use this code to check rcp32 over
call    check
jne     mail_edemko@rambler.ru_about_rounding_error
invoke  MessageBoxA,0,'rcp32 returned ok',0,0
invoke  ExitProcess,0
mail_edemko@rambler.ru_about_rounding_error:
hlt
check:  mov     esi,\$0000'000F
or      ecx,-1
.loop:xor     edx,edx
mov     eax,ecx
div     esi
mov     ebx,eax
mov     eax,\$8888'8889
mul     ecx
shr     edx,\$03
cmp     edx,ebx
loope   .loop
ret

;   divisor[\$1f..\$00] = \$0000'0010
; 1/divisor[\$1f..\$00] = \$0.1000'0000'0000'0000(0.062'500'000'000'000'000)
code:   shr     eax,\$04           ; divisor is this power of two
```
01 Feb 2011, 10:59
idle

Joined: 06 Jan 2011
Posts: 407
Location: Ukraine
idle
Code:
```2011_??_??

english
~~~~~~~
This file tells how to divide 1 by integer.
1/0 & 1/1 are easy.

First we should understand 1/123(e.g.) in decimal to use the principle in binary then.
Imagine amount of liquid(e.g. juice).
Imagine a vessel of 123 capacity(e.g. a glass).

Our task is to fill the vessel with liquid as many times as possible until liquid ends.
In other words, you drink juice *glass after a glass* until the juice is drunk.
In other words, *each glass* glass count increases, juice decreases.
In other words, *each division* quotient increases, dividend decreases.

1 is a unit, consisting of smaller ones: mili- micro- nano- etc-.
This is scaling, and we are just storing quotient of mili- micro- nano- etc- size.

Ok, let us drink that juice
quotient
-------------------
0'001/123  _       <- ones
0'010/123  0._     <- tenths
0'100/123  0.0_    <- hundredths
-------------------
1'000/123  0.00_   <- see, we are dividing mili-ones
-0'123      0.001
=0'877
-0'123      0.002
=0'754
-0'123      0.003
=0'631
-0'123      0.004
=0'508
-0'123      0.005
=0'385
-0'123      0.006
=0'262
-0'123      0.007
=0'139
-0'123      0.008
=0'016
-------------------
0'160/123  0.008_  <- hundredths
-0'123      0.0081
=0'037
-------------------
0'370/123  0.0081_ <- hundredths
-0'123      0.00811
=0'247
-0'123      0.00812
=0'124
-0'123      0.00813
=0'001
-------------------
...               _
-------------------

Binary 1/123.
It is obvious to get 0..9 in decimal quotient.
Hence binary quotient consists of 0..1 only(we either drink the juice or not .

Binary juice drunk
quotient
-----------------
001/123  _b
002/123  0._b
004/123  0.0_b
008/123  0.00_b
016/123  0.000_b
032/123  0.0000_b
064/123  0.00000_b
-----------------
128/123  0.000000_b
-123      0.0000001b
=005
-----------------
010/123  0.0000001_b
020/123  0.00000010_b
040/123  0.000000100_b
080/123  0.0000001000_b
-----------------
160/123  0.00000010000_b
-123      0.000000100001b
=037
-----------------
074/123  0.000000100001_b
-----------------
148/123  0.0000001000010_b
-123      0.00000010000101b
=025
-----------------
...                      _b
-----------------

0.00000010000101b = 2^-07 + 2^-12 + 2^-14
= 1.0000101b * 2^-07
= 10000101.b * (2^-07 * 2^-07 = 2^-14)
= 133 * 2^-14
= 133 shr 14

How many leading zeros may binary quotient contain?
(BSR dividend)[+1] the answer is.
Really, to divide by \$00ff, 1 grows  8 times into \$00100
\$ffff, 1 grows 16 times into \$10000
\$1234, 1 grows 13 times into \$02000
...and only then division(subtraction) starts.
[+1] is not required if initial divisor is the power of two:
to divide by \$0004, 1 grows          into \$00004

Procedure which returns 1/integer.
...
mov     eax,10
call    dword_rcp
...
;edx   = quotient of a .1...xxx form
;ecx   = number of consecutive zeros AFTER 0.
;ebx   = ?
;eax   = old eax = divisor
;flags = ?
dword_rcp:
divisor  equ eax
dividend equ ebx
leading  equ ecx
quotient equ edx

mov     dividend,1
sub     leading,leading
sub     quotient,quotient
.drink_juice:
inc     leading
shl     dividend,1        ;=dividend+dividend = dividend*2
jc      .1
cmp     divisor,dividend
ja      .0                ;divisor denotes units of division
.1:   sub     dividend,divisor  ;drink a glass of juice
stc
.0:   rcl     quotient,1        ;inserts either 0 or 1
jno     .drink_juice      ;the most significant bit not 1
sub     leading,32        ;number of consecutive zeros AFTER 0.
ret

restore divisor,dividend,leading,quotient

Usage sample.
...
mov     eax,\$CCCC'CCCD   ;rounded 0.1
mov     edx,65'535       ;arbitrary divisor
mul     edx              ;0.1 * divisor
shr     edx,3            ;shr edx:eax,32+3
;edx = 6'553
...
```
01 Oct 2011, 09:08
idle

Joined: 06 Jan 2011
Posts: 407
Location: Ukraine
idle
i misused the two terms
i beg your pardon if it happens again
(BSR divisor)[+1] the answer is.
mov edx,65'535 ;arbitrary dividend
mul edx ;0.1 * dividend

english & slavic(ukrainian)
03 Oct 2011, 18:35
 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

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

Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.