Jump to content

HELP WITH THIS RECURSIVE FUNCTION... WHAT's WRONG WITH IT??

- - - - -

  • Please log in to reply
7 replies to this topic

#1
AksCode

AksCode

    Newbie

  • Members
  • Pip
  • 4 posts
Hi people. I'm new here. I hope that someone can help me because I have to send this homeword in less than 24 hours.

I'm trying to do a recursive function in Assembly in order to get the Max common divisor between two numbers. In C++ this would be easy, as I created a function before that is working, like this one:


int gcd (int x, int y)

{

if (x % y == 0)


return y;


else 


return gcd (y, x % y);


}



Fine, but I'm trying to do the same in a Assembly Procedure called "maxDiv". I will paste my entire code to see if you guys please can help me. The program runs without errors and it starts fine but when it enters to the function, the program freeze and VS tells me "project.exe has triggered a breakpoint". My code is as follow:





Include Irvine32.inc


.data


show BYTE "This program will show you the max. comun divisor between the 2 numbers of your choose ", 0

show1 BYTE "Enter the first number: ", 0

show2 BYTE "Enter the second number: ", 0

show3 BYTE "Enter the third and final number: ", 0

num1 SDWORD ?

num2 SDWORD ?

num3 SDWORD ?


.code

main PROC


mov edx, OFFSET show

call WriteString

call Crlf

mov edx, OFFSET show1

call WriteString

call ReadInt

mov num1, eax

call Crlf

mov edx, OFFSET show2

call WriteString

call ReadInt

mov num2, eax

call Crlf

mov eax, 0

call maxDiv



maxDiv PROC

show4 BYTE "The greatest common divisor from this two number is: ", 0


mov eax, num1

div num2


.IF edx == 0

mov edx, OFFSET show4

call WriteString

mov eax, num1

call WriteInt


.ElSE

mov eax, num2

mov num1, eax

mov num2, edx


call maxDiv

.ENDIF


call WaitMsg

maxDiv ENDP


main ENDP


END main





#2
Gunner

Gunner

    Learning Programmer

  • Members
  • PipPipPip
  • 45 posts

Include Irvine32.inc


.data


show    BYTE "This program will show you the max. comun divisor between the 2 numbers of your choose ", 0

show1   BYTE "Enter the first number: ", 0

show2   BYTE "Enter the second number: ", 0

show3   BYTE "Enter the third and final number: ", 0

; this should be here not in code section

show4   BYTE "The greatest common divisor from this two number is: ", 0


; unitialized data should not, cannot go in the initialized data area

.data? ; <<<< should be here

num1    SDWORD ?

num2    SDWORD ?

num3    SDWORD ?


.code

;main PROC

main: ; >>>>>> should be this


    mov     edx, OFFSET show

    call    WriteString

    call    Crlf

    mov     edx, OFFSET show1

    call    WriteString

    call    ReadInt

    mov     num1, eax

    call    Crlf

    mov     edx, OFFSET show2

    call    WriteString

    call    ReadInt

    mov     num2, eax

    call    Crlf

    mov     eax, 0

    call    maxDiv



maxDiv PROC

COMMENT $

    this should not be in the code section, although you can 

    have text in the code section, this is not the way to do it

    show4 BYTE "The greatest common divisor from this two number is: ", 0 

    $


    mov     eax, num1

    div     num2

    

    .IF edx == 0

        mov     edx, OFFSET show4

        call    WriteString

        mov     eax, num1

        call    WriteInt

    

    .ElSE

        mov     eax, num2

        mov     num1, eax

        mov     num2, edx

    

        call    maxDiv

    .ENDIF

    

        call    WaitMsg

        ret ; >>>>> This IS NEEDED

maxDiv ENDP


;main ENDP >>>> Nope, not needed


END main


#3
AksCode

AksCode

    Newbie

  • Members
  • Pip
  • 4 posts

Gunner said:


Include Irvine32.inc


.data


show    BYTE "This program will show you the max. comun divisor between the 2 numbers of your choose ", 0

show1   BYTE "Enter the first number: ", 0

show2   BYTE "Enter the second number: ", 0

show3   BYTE "Enter the third and final number: ", 0

; this should be here not in code section

show4   BYTE "The greatest common divisor from this two number is: ", 0


; unitialized data should not, cannot go in the initialized data area

.data? ; <<<< should be here

num1    SDWORD ?

num2    SDWORD ?

num3    SDWORD ?


.code

;main PROC

main: ; >>>>>> should be this


    mov     edx, OFFSET show

    call    WriteString

    call    Crlf

    mov     edx, OFFSET show1

    call    WriteString

    call    ReadInt

    mov     num1, eax

    call    Crlf

    mov     edx, OFFSET show2

    call    WriteString

    call    ReadInt

    mov     num2, eax

    call    Crlf

    mov     eax, 0

    call    maxDiv



maxDiv PROC

COMMENT $

    this should not be in the code section, although you can 

    have text in the code section, this is not the way to do it

    show4 BYTE "The greatest common divisor from this two number is: ", 0 

    $


    mov     eax, num1

    div     num2

    

    .IF edx == 0

        mov     edx, OFFSET show4

        call    WriteString

        mov     eax, num1

        call    WriteInt

    

    .ElSE

        mov     eax, num2

        mov     num1, eax

        mov     num2, edx

    

        call    maxDiv

    .ENDIF

    

        call    WaitMsg

        ret ; >>>>> This IS NEEDED

maxDiv ENDP


;main ENDP >>>> Nope, not needed


END main

Ok man, now at least there are no breakpoints so, many many thanks for your time... but now I receive an exception saying that an integer overflow. This is imposible, I'm using small numbers and even if the result of the first division is a decimal, it doesn't suppose to truncate the value?? I'm really sorry for this dumb questions but I really tried to do this by myself without ask for any help but the homework is for tonight. My thing is high level languages and i'm a complete noob using assembly. Please, you or anyone can give me a little help with the logic?? I'm trying to do exactly the same thing that I did with the C++ function that I wrote in my question. I will waiting for your answers guys.

#4
Gunner

Gunner

    Learning Programmer

  • Members
  • PipPipPip
  • 45 posts
your doing unsigned division but you are used sdwords... should be dword

this is how you use div:

    mov     edx, 0

    mov     eax, 15

    mov     ecx, 2

    div     ecx

    

    ; eax == 7

    ; edx == remainder - 1


#5
AksCode

AksCode

    Newbie

  • Members
  • Pip
  • 4 posts

Gunner said:

your doing unsigned division but you are used sdwords... should be dword

this is how you use div:

    mov     edx, 0

    mov     eax, 15

    mov     ecx, 2

    div     ecx

    

    ; eax == 7

    ; edx == remainder - 1

Many many thanks man. Now the code seems to run fine but I have another issue. I only get the right greatest common divisor when the user give 2 same numbers. But if the user give numbers like 49 and 28, the answer that I get is '21' which is only the reminder of that division. What i'm doing wrong?? As far as i'm concerned, the reminder of the div reside in edx in this case. Here a piece of my procedure:


 mov     edx, 0

    mov     eax, num1

    mov     ecx, num2

    div     ecx

    

    .IF edx == 0

        mov     edx, OFFSET show4

        call    WriteString

        mov     eax, num1

        call    WriteInt

    

    .ElSE

        mov     eax, num2

        mov     num1, eax

        mov     num2, edx

    

        call    maxDiv

    .ENDIF


We are almost there. What I can possibly be doing wrong?? I think that the proc. seems exactly as my C++ function who is as follow:



int maxDiv (int x, int y)

{

if (x % y == 0)


return y;


else 


return maxDiv (y, x % y);


}

It doesn't seems the same as my Assembly Proc for you? Please, I'm a WebMaster and I have a forum too and I hate when people ask dumb questions without read but, actually I have read enough and this is my very first app in Assembly. I will waiting for your reply and many many thanks again.

#6
AksCode

AksCode

    Newbie

  • Members
  • Pip
  • 4 posts
Ok, I FINALLY found the logic error. The error was that I was moving the value of num1 variable to eax to show it in the screen. I should return the num2, as in my C++ function I return the Y. Thank you man for been there to help. If you would like to visit my page and participate in my forums, you are welcome. News With Freedom Home. Sitio oficial de la libertad de prensa. Noticias de todo el mundo sin editar.

#7
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
No; it's not the same; not quite. It is something like that, though; it's just that all this:
.IF edx == 0

        mov     edx, OFFSET show4

        call    WriteString

        mov     eax, num1

        call    WriteInt

    

    .ElSE

        mov     eax, num2

        mov     num1, eax

        mov     num2, edx

    

        call    maxDiv

    .ENDIF
Needs to be something more like this:
.IF edx == 0

        mov eax, ecx 

        ret 

    

    .ElSE

        mov     eax, num2

        mov     num1, eax

        mov     num2, edx

    

        call    maxDiv

        

        ret 

    .ENDIF

For it to be the assembly language version of the C/C++ function.


But ... how do you define 'num1' and 'num2', though? Are they global variables?

#8
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
By the way, you could also use the CMP instruction, instead of the .IF statements, if you wanted to.

I mean, it's more assembly-like to use the CMP instruction, isn't it?




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users