News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

division With Remainder Example

Started by hfheatherfox07, January 06, 2013, 12:51:16 AM

Previous topic - Next topic

hfheatherfox07

Sorry I thought mod could be used to obtain remainder
Which is what I am interested in doing

http://stackoverflow.com/questions/8971627/masm-using-registers-as-expressions-between-mod-operator

My understanding is that eax has the number and edx has the remainder
Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

qWord

It seems like that you mean the fractional part of a real number, when talking about the remainder.
So the question is: do you need the that for further calculation or just for printing? In the second case, simply make a floating point calculation and then use the CRT to format the number in a string buffer:
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\msvcrt.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\msvcrt.lib

.data
MsgCaption      db "PUTER TIME",0
format          db "Your puter has run %.4G:hours since the last boot, give it a break!",0

.data?
szBuffer     db 1024 dup (?)
iTicks SDWORD ?
r8Ticks REAL8 ?
.const
r8HoursPerTicks REAL8 2.777777777777777778E-7 ; 1/3600000
; iTicksPerHour SDWORD 3600000
.code

start:

invoke GetTickCount
mov iTicks,eax
fild iTicks
fmul r8HoursPerTicks
;fidiv iTicksPerHour ; bad code
fstp r8Ticks

invoke crt_sprintf,ADDR szBuffer,ADDR format,r8Ticks ; the CRT only supports REAL8 here
    invoke MessageBox, NULL, addr szBuffer, addr MsgCaption, MB_ICONASTERISK
    invoke ExitProcess,NULL
end start
MREAL macros - when you need floating point arithmetic while assembling!

dedndave

QuoteI want the answer here to have 2 decimal reminder

the easy way is to multiply the value by 100
or - divide the divisor by 100, if it is evenly divisable
or - some combination

either way, the result is, your quotient will be 100 x the real answer
now, convert it as an integer and stick a decimal point in there  :P

hool

Quote from: dedndave on January 08, 2013, 01:55:56 AM
the easy way is to multiply the value by 100
or - divide the divisor by 100, if it is evenly divisable
or - some combination
You could refine that a bit to allow for a larger dividend .        xor     edx, edx
        mov     eax, 20         ; <- divide this (32bit)
        mov     ecx, 6          ; <- by this (24bit only)
        div     ecx             ; eax =2
        mov     eax, edx
        imul    eax, 100
        xor     edx, edx
        div     ecx             ; eax =33


.        xor     edx, edx
        mov     eax, 9         ; <- divide this (32bit)
        mov     ecx, 2          ; <- by this (24bit only)
        div     ecx             ; eax =4
        mov     eax, edx
        imul    eax, 100
        xor     edx, edx
        div     ecx             ; eax =50 (ALWAYS 2 digits)

        ; this is one way how to get rid of 0
        mov     edx, 0cccccccdh
        mov     ecx, eax
        mul     edx
        shr     edx, 3
        mov     eax, edx
        imul    eax, 10
        cmp     eax, ecx
        cmovnz  edx, ecx        ; edx =5 (or =33 in previous example) 



You can also go this way but if you run this example you are in big trouble because result of division will not fit into 32bit value. In addition, you are facing problem of separating the remainder (if that what you want)
        xor     edx, edx
        mov     eax, 0xffffffff         ; <- divide this
        mov     ecx, 6                 ; by this
        mov     ebx, 100
        mul     ebx
        div     ecx 

dedndave


qWord

you all make it so complicated ... but what else should one expect from an assembly programming forum  :lol:
MREAL macros - when you need floating point arithmetic while assembling!

dedndave


hool

Actually, here is an excellent idea:

"threshold" must be minimun 100 but can be any 24bit number

if (divisor <= threshold) {
        xor     edx, edx
        mov     eax, dividend
        mov     ecx, divisor
        div     ecx
        mov     eax, edx
        imul    eax, 100
        xor     edx, edx
        div     ecx
        ; now you need to get rid of 0
        ; If your end goal is to convert o ASCII then getiing rid of zero is best done prior to the conversion
}else{
        mov     eax, dividend
        mov     ecx, 100             
        mul     ecx
        mov     ecx, divisor
        div     ecx
        ; now you need to separate the remainder and get rid of 0.
        ; If your end goal is to convert o ascii then separating(and zero elimination) is best done after conversion, probably

dedndave

i think there is an API that will format it, actually
(2 functions used, as i remember, to convert from system time to formatted text)
but, i thought it was a good learning exercise, nonetheless

hfheatherfox07

Quote from: qWord on January 07, 2013, 11:23:11 PM
It seems like that you mean the fractional part of a real number, when talking about the remainder.
So the question is: do you need the that for further calculation or just for printing? In the second case, simply make a floating point calculation and then use the CRT to format the number in a string buffer:


Thank you that Worked Great...
Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

hfheatherfox07

Quote from: qWord on January 06, 2013, 01:55:45 AM
you must use the FPU (or SSEx) to get floating point results:
LOCAl x:REAL8

fld FP8(9.0)
fdiv FP8(2.0) ; (commonly you would multiply by 0.5)
fstp x

fnc crt_printf,"%.8G\n",x


Now I understand This !!!  :biggrin:

include \masm32\include\masm32rt.inc

division proto

.data
caption  db "Division With Remainder Example", 0
Format   db "%.9G",0
szBuffer   db 32 dup(0)
.data?
x           REAL8 ?
.code

Start:
invoke division
invoke MessageBox, 0, addr szBuffer, addr caption,  MB_ICONQUESTION
invoke ExitProcess, 0
division Proc

;LOCAl x:REAL8 ; you can use local or Global

fld FP8(44.0)
fdiv FP8(7.0)
fstp x

invoke crt_sprintf,ADDR szBuffer,ADDR Format,x

ret

division endp
end Start


Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

hfheatherfox07

Quote from: dedndave on January 08, 2013, 04:38:42 AM
this is pretty simple   :P

Nice refresh  :t
I like that  :icon_exclaim:
Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

hfheatherfox07

Quote from: hool on January 08, 2013, 03:15:15 AM
Quote from: dedndave on January 08, 2013, 01:55:56 AM
the easy way is to multiply the value by 100
or - divide the divisor by 100, if it is evenly divisable
or - some combination
You could refine that a bit to allow for a larger dividend .        xor     edx, edx
        mov     eax, 20         ; <- divide this (32bit)
        mov     ecx, 6          ; <- by this (24bit only)
        div     ecx             ; eax =2
        mov     eax, edx
        imul    eax, 100
        xor     edx, edx
        div     ecx             ; eax =33


.        xor     edx, edx
        mov     eax, 9         ; <- divide this (32bit)
        mov     ecx, 2          ; <- by this (24bit only)
        div     ecx             ; eax =4
        mov     eax, edx
        imul    eax, 100
        xor     edx, edx
        div     ecx             ; eax =50 (ALWAYS 2 digits)

        ; this is one way how to get rid of 0
        mov     edx, 0cccccccdh
        mov     ecx, eax
        mul     edx
        shr     edx, 3
        mov     eax, edx
        imul    eax, 10
        cmp     eax, ecx
        cmovnz  edx, ecx        ; edx =5 (or =33 in previous example) 



You can also go this way but if you run this example you are in big trouble because result of division will not fit into 32bit value. In addition, you are facing problem of separating the remainder (if that what you want)
        xor     edx, edx
        mov     eax, 0xffffffff         ; <- divide this
        mov     ecx, 6                 ; by this
        mov     ebx, 100
        mul     ebx
        div     ecx 




Hi,
Thank you for the reply ....
Your first algo works great only for 20 divided by 6 ?? won't work for any other numbers
include \masm32\include\masm32rt.inc
; Only works with 20 / 6
division proto

.data
caption  db "Division With Remainder Example", 0
Format   db "%d.%d",0
var1     dd 20h ; binary value Dividned
var2     dd 6h  ; binary value Divisor
buffer   db 32 dup(0)
.data?
szRemainder  dword  ?
szRealNumber dword  ?
.code

Start:
invoke division
invoke MessageBox, 0, addr buffer, addr caption,  MB_ICONQUESTION + MB_OK
invoke ExitProcess, 0
division Proc

    xor     edx, edx
    mov     eax, var1         ; <- divide this (32bit)
    mov     ecx, var2         ; <- by this (24bit only)
    div     ecx             ; eax =2
    mov     eax, edx        ; move the Quotient to edx
    imul    eax, 100        ; 2 Decimal Places ,1000 is 3 etc....
    xor     edx, edx
    div     ecx             ; eax =33
mov szRealNumber , edx
mov szRemainder,eax ; store the resulting Remainder in eax
invoke wsprintf, addr buffer, addr Format, edx, eax
ret

division endp
end Start


On the second example I get an error Here:
  cmovnz  edx, ecx        ; edx =5 (or =33 in previous example) 

Error:
division.asm(37) : error A2085: instruction or register not accepted in current CPU mode

include \masm32\include\masm32rt.inc

division proto

.data
caption  db "Division With Remainder Example", 0
Format   db "%d.%d",0
buffer   db 32 dup(0)
.data?
szRemainder  dword  ?
szRealNumber dword  ?
.code

Start:
invoke division
invoke MessageBox, 0, addr buffer, addr caption,  MB_ICONQUESTION + MB_OK
invoke ExitProcess, 0
division Proc

        xor     edx, edx
        mov     eax, 9         ; <- divide this (32bit)
        mov     ecx, 2          ; <- by this (24bit only)
        div     ecx             ; eax =4
        mov     eax, edx
        imul    eax, 100
        xor     edx, edx
        div     ecx             ; eax =50 (ALWAYS 2 digits)

        ; this is one way how to get rid of 0
        mov     edx, 0cccccccdh
        mov     ecx, eax
        mul     edx
        shr     edx, 3
        mov     eax, edx
        imul    eax, 10
        cmp     eax, ecx
        cmovnz  edx, ecx        ; edx =5 (or =33 in previous example) 

mov szRealNumber , eax
mov szRemainder,edx ; store the resulting Remainder in eax
invoke wsprintf, addr buffer, addr Format, eax, edx
ret

division endp
end Start


3rd one is not working for me either ?

include \masm32\include\masm32rt.inc

division proto

.data
caption  db "Division With Remainder Example", 0
Format   db "%d.%d",0
buffer   db 32 dup(0)
.data?
szRemainder  dword  ?
szRealNumber dword  ?
.code

Start:
invoke division
invoke MessageBox, 0, addr buffer, addr caption,  MB_ICONQUESTION + MB_OK
invoke ExitProcess, 0
division Proc
        xor     edx, edx
        mov     eax, 20         ; <- divide this
        mov     ecx, 6                 ; by this
        mov     ebx, 100
        mul     ebx
        div     ecx 

mov szRealNumber , eax
mov szRemainder,edx ; store the resulting Remainder in eax
invoke wsprintf, addr buffer, addr Format, eax, edx
ret

division endp
end Start


Am I doing something wrong?


Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

hfheatherfox07

Quote from: hool on January 08, 2013, 05:24:08 AM
Actually, here is an excellent idea:

"threshold" must be minimun 100 but can be any 24bit number

if (divisor <= threshold) {
        xor     edx, edx
        mov     eax, dividend
        mov     ecx, divisor
        div     ecx
        mov     eax, edx
        imul    eax, 100
        xor     edx, edx
        div     ecx
        ; now you need to get rid of 0
        ; If your end goal is to convert o ASCII then getiing rid of zero is best done prior to the conversion
}else{
        mov     eax, dividend
        mov     ecx, 100             
        mul     ecx
        mov     ecx, divisor
        div     ecx
        ; now you need to separate the remainder and get rid of 0.
        ; If your end goal is to convert o ascii then separating(and zero elimination) is best done after conversion, probably





include \masm32\include\masm32rt.inc

division proto

.data
caption      db "Division With Remainder Example", 0
Format       db "%d.%d",0
dividend     dd 20h ; binary value Dividned
divisor      dd 6h  ; binary value Divisor
threshold    dd 100h ; threshold
.data?
buffer       db 1024 dup(?)
szRemainder  dword  ?
szRealNumber dword  ?
.code

Start:
invoke division
invoke MessageBox, 0, addr buffer, addr caption,  MB_ICONQUESTION + MB_OK
invoke ExitProcess, 0
division Proc

; "threshold" must be minimun 100 but can be any 24bit number

.if eax<=  threshold
        xor     edx, edx
        mov     eax, dividend
        mov     ecx, divisor
        div     ecx
        mov     eax, edx
        imul    eax, 100
        xor     edx, edx
        div     ecx
        ; now you need to get rid of 0
        ; If your end goal is to convert o ASCII then getiing rid of zero is best done prior to the conversion
.else
        mov     eax, dividend
        mov     ecx, 100             
        mul     ecx
        mov     ecx, divisor
        div     ecx
        ; now you need to separate the remainder and get rid of 0.
        ; If your end goal is to convert o ascii then separating(and zero elimination) is best done after conversion, probably
.endif 

mov szRealNumber , eax
mov szRemainder,ebx ; store the resulting Remainder in eax
invoke wsprintf, addr buffer, addr Format, eax, ebx
ret

division endp
end Start


I am sorry I don't follow you here...can you use my above example and put it in ?
Thank you
Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

hool

        mov     eax, 200
        mov     ecx, 100             
        mul     ecx
        mov     ecx, 31
        div     ecx
        mov     esi, eax
        mov     edi, eax
        invoke  wsprintf, addr buffer, addr Format, esi, edi
        invoke  MessageBox, 0,addr buffer, 0, MB_ICONQUESTION+MB_OK
Now you have to explain why you see "645.645"

        mov     eax, 0xffffffff
        mov     ecx, 100             
        mul     ecx
        mov     ecx, 31
        div     ecx
        mov     esi, eax
        mov     edi, eax
        invoke  wsprintf, addr buffer, addr Format, esi, edi
        invoke  MessageBox, 0,addr buffer, 0, MB_ICONQUESTION+MB_OK
Now you have to explain why it crashes

        xor     edx, edx
        mov     eax, 200
        mov     ecx, 31
        div     ecx
        mov     esi, eax
        mov     eax, edx
        imul    eax, 100
        xor     edx, edx
        div     ecx
        mov     edi, eax
        invoke  wsprintf, buffer, Format1, esi, edi
        invoke  MessageBox, 0,addr buffer, 0, MB_ICONQUESTION+MB_OK   
Now you have to explain why you see "6.45"

And only after all that do something more complex