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.