News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

division

Started by A_B, February 15, 2010, 02:03:55 AM

Previous topic - Next topic

A_B

Hi,

I'm trying to get a Euclid's algorithm program to work, the problem is though, I can't even do a division.
Here is my code; why doesn't it work?

.486
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\macros\macros.asm

include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

.data?
num     dword       ?
den     dword       ?
quoti   dword       ?
;rem     dword       ?

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

.code
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    mov num, sval(input("the numerator : "))
    mov den, sval(input("the denominator : "))

    print str$(num)
    print chr$(10,13)
    print str$(den)
    print chr$(10,13)
   
    mov eax, num
    mov ebx, den

    ;print str$(eax)
    ;print chr$(10,13)
    ;print str$(ebx)
    print chr$(10,13)

    ;zero-extend the numerator (eax) into edx
    mov edx, 0

    ;preform the division
    div ebx

    ;print the quotient
    mov quoti, eax
    print str$(quoti)
    ;print the remainder
   


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
invoke ExitProcess, NULL
end start



Thanks
Alex

oex


    print chr$(10,13)


mangles eax

try


    print str$(num)
    print chr$(10,13)
    print str$(den)
    print chr$(10,13)
   
    mov eax, num
    mov ebx, den

    ;zero-extend the numerator (eax) into edx
    mov edx, 0

    ;preform the division
    div ebx

    ;print the quotient
    mov quoti, eax
    print chr$(10,13)
    print str$(quoti)
    ;print the remainder
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

A_B

wow, that was suprisingly easy to solve :D

Thanks
Alex

A_B

hallelujah, i made my first decent program in masm :p

Euclidean algorithm:
.486
.model flat, stdcall
option casemap: none

include \masm32\include\windows.inc
include \masm32\macros\macros.asm

include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
;
;   This program takes 2 positive integers as input, then computes the
;   greatest common divisor using Euclid's algorithm.
;
;       VARIABLES
;       eax - here operations take place
;       ebx - stores the numerator
;       ecx - stores the denominator
;
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

.code

_start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    ;--------------------------------------------------------
    mov ebx, sval( input("enter the first number : "))      ;|Get the 2 numbers
    mov ecx, sval( input("enter the second number : "))     ;|
    ;--------------------------------------------------------
   
    ;--------------------------------------------------------
    begin:
        mov eax, ebx            ;move the numerator to the eax register to do division
        mov edx, 0              ;zero-extend the eax register to prepare division
        div ecx                 ;divide the numberator by ecx (the denominator), yielding the quotient in eax

        mul ecx                 ;multiply the quotient by the denominator
        sub ebx, eax            ;subtract this product from the numberator, yielding the remainder in ebx

        cmp ebx, 0              ;if the remainder is 0, the gcd is the current denominator, end the program
        je finish

        mov eax, ecx            ;shuffle the values using eax as temp storage
        mov ecx, ebx            ;make the new denominator the old remainder
        mov ebx, eax            ;make the new numerator the old denominator
       
        jmp begin               ;go through the loop again

    ;--------------------------------------------------------
    finish:
    print str$(ecx)

   
    ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
invoke ExitProcess, NULL
end _start

PBrennick

Alex,

Very nice! One of the things I like about your first program is the extensive use of comments. This is a very good habit. Continue to do so, it pays dividends :p in the long run.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

oex

We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

dedndave

yes - nice commenting and nice layout, too   :U
i have seen some sloppy stuff
poke around in the 16-bit sub-forum if you want to see some "don't" examples - lol

jj2007

Very well done :U

mov edx, 0              ;zero-extend the eax register to prepare division

Have a look at cdq in opcodes.chm - cdq does the same with a single byte instead of 5, and it works for negative numbers, too.

raymond

Here's another variant with fewer instructions.

    mov ebx, sval( input("enter the first number : "))      ;|Get the 2 numbers
    mov eax, sval( input("enter the second number : "))     ;|

begin:
    xor  edx,edx     ;zero-extend the eax register to prepare division
    div  ebx         ;returns the remainder in EDX
    test edx,edx     ;if the remainder is equal to 0, the current divisor (EBX) would be the GCD
    jz   finish
    mov  eax,ebx     ;the old divisor becomes the numerator
    mov  ebx,edx     ;the remainder becomes the divisor
    jmp  begin

    finish:
    print str$(ebx)


Note: I don't recommend using "cdq" in this context for extending the eax register because you want to operate strictly on positive numbers. If your input for a number is large enough to set the most significant bit, it would then be considered as a negative number with cdq, set EDX to 0FFFFFFFFh and cause the div instruction to crash the program. :eek
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

donkey

Here's mine from a few years ago, pretty much the same as Raymond's. Interesting that you don't have to exchange them, I guess I just did it and left it, never tried with the numbers transposed.

Euclidean PROC Num1:DWORD, Num2:DWORD

mov eax,[Num1]
mov ecx,[Num2]

cmp eax,ecx
jg @F
xchg ecx,eax
@@:
xor edx,edx
div ecx
test edx,edx
jz @F
mov eax,ecx
mov ecx,edx
jmp @B

@@:
xchg eax,ecx
RET
Euclidean ENDP
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

BlackVortex

Heh, best to use "xor edx,edx" for that one, but that cdq opcode is interesting.

By the way, is there a way to zero eax in just 1 byte (under some circumstances at least) ? There's no cdqe command,lol.

dedndave

under 3 conditions

1) eax is -1:

        inc     eax

2) eax is +1

        dec     eax

3) eax is less than 80000000h (doesn't zero eax - but zeros the high word - if ax is zero, it zeros eax   :P )

        cwde

a few bytes:

        push    0
        pop     eax

or

        and     eax,0

:bg

BlackVortex

None of that is satisfactory.

Isn't there some weird 1-byte opcode to zero eax, maybe depending on a flag or something ?

dedndave

oh !
i forgot XCHG EAX,GeneralRegister

if ebx, ecx, edx, esi, edi, or ebp are 0, you can swap it into eax with 1 byte   :bg

but, alas, i think the fish you are seeking has done swam upstream

BlackVortex

Wooo, that's actually really useful. I didn't imagine xcng to be 1 byte only. Sorry for hijacking the thread, but at least some of us learned something.  :green2