Home > Software design >  Accessing parameters in Assembly
Accessing parameters in Assembly

Time:09-18

Overview

I am writing a program in x86 assembly (NASM) that essentially gets a dividend and divisor from the user, then calls a procedure that will do the division, returning the value in EAX for me to print. I'm using Paul Carter's asm_io.inc library for C I/O functions (http://pacman128.github.io/pcasm/). Here's what I put in my command line to get the program running: nasm -f win32 source.asm gcc source.obj driver.c asm_io.obj.

Problem

Now the problem is that when I pass two arguments to the procedure (called divide), I attempt to access the parameters via indirection (e.g. [ebp 8] for first parameter), however it yields the memory address instead. I've tried debugging it, but to no avail. Is there something that I'm doing wrong that yields the wrong result? My code:

%include "asm_io.inc"

segment .data
        prompt1 db "Enter a dividend: ", 0
        prompt2 db "Enter a divisor: ", 0        
        answer1 db " divided by ", 0
        answer2 db " equals ", 0

segment .bss
        dividend resd 1
        divisor  resd 1

segment .text
        global  _asm_main
_asm_main:
        enter   0,0
        pusha

        mov     eax, prompt1
        call    print_string
        call    read_int
        mov     [dividend], eax

        mov     eax, prompt2
        call    print_string
        call    read_int
        mov     [divisor], eax

        mov     eax, [dividend]
        call    print_int

        mov     eax, answer1
        call    print_string

        mov     eax, [divisor]
        call    print_int

        mov     eax, answer2
        call    print_string

        push    dword dividend
        push    dword divisor
        call    divide
        add     esp, 8
        
        call    print_int

        popa
        mov     eax, 0
        leave                     
        ret
divide:
        push    ebp
        mov     ebp, esp

        mov     eax, [ebp   8]
        div     dword [ebp   4]

        pop     ebp
        ret

CodePudding user response:

   push    dword dividend
   push    dword divisor

In NASM these instructions will push the address of the variable. You need to use the square brackets to get to their actual value.

    push    dword [dividend]
    push    dword [divisor]

Your divide routine forgets to zero the edx register before doing the div instruction!
Your divide routine currently divides the divisor by the return address.
The displacements are off by 4. This is the correct code:

divide:
        push    ebp
        mov     ebp, esp
        mov     eax, [ebp   12]   ; Dividend
        xor     edx, edx
        div     dword [ebp   8]   ; Divisor
        pop     ebp
        ret

You can of course choose to pass the addresses and dereference within the subroutine:

divide:
        push    ebp
        mov     ebp, esp
        mov     ecx, [ebp   8]    ; Address of Divisor
        mov     ecx, [ecx]
        mov     eax, [ebp   12]   ; Address of Dividend
        mov     eax, [eax]
        xor     edx, edx
        div     ecx
        pop     ebp
        ret

CodePudding user response:

With the push instruction, you've suddenly forgone indirection and asked it to simply push the address.  With the prior instructions (e.g. mov eax,[divisor], you did ask for indirection.

  • Related