I have a program that is supposed to either add or subtract two hardcoded numbers based on user input 0
or not 0
. I get memory access violation error inside input
. when i try to call sum
or call diff
instead input
in line 9 it works fine and gives me expected output. loop
and next
is used to display result from stack.
.text
.global _start
_start:
xorl %esi, %esi # zerowanie licznika
call input # <---- line 9
loop: # label
movl $0, %edx # reszta z dzielenia
movl $10, %ebx # dzielnik
divl %ebx # dzielenie, wynik w eax, reszta w edx
addl $48, %edx # kod ASCII
pushl %edx # edx na stos
incl %esi # esi++
cmpl $0, %eax # porównaj wynik i 0
jz next # jeśli koniec, jump next
jmp loop # jeśli nie, następna iteracja
next: # label
cmpl $0, %esi # porównaj licznik z 0
jz exit # jeśli koniec, jump exit
decl %esi # esi--
movl $4, %eax # kod 4 = zapis
movl %esp, %ecx # znak do wypisania
movl $1, %ebx # domyślny strumień - sys_out
movl $1, %edx # długość stringa do wypisania?
int $0x80 # przerwanie
addl $4, %esp #
jmp next # kolejna iteracja
exit:
mov $1, %eax # zakończenie programu
mov $0, %ebx # kod wyjścia
int $0x80 # przerwanie
# ---------------- subprogram ----------------------
input:
movl $3, %eax # code 3 = input
movl $0, %ebx # code 0 = stdin
subl $4, %esp # move stack pointer by 4 bytes
movl %esp, %ecx # set reading position onto stack
movl $4, %edx # read 4 bytes
int $0x80 # interrupt to execute above
cmp %esp, '0' # if(input == '0') sum else diff
jz sum
jnz diff
ret
sum:
movl $37, %eax # pierwsza liczba sumy
movl $22, %ebx # druga liczba sumy
addl %ebx, %eax # suma, wynik w eax
ret
diff:
movl $37, %eax # pierwsza liczba sumy
movl $22, %ebx # druga liczba sumy
subl %ebx, %eax # roznica, wynik w eax
ret
# ------------- end -------------
How can I edit my input
function to read a character/number and compare it to 0
?
cmp %esp, '0'
is wrong, because it tries to compare the value of%esp
to the value in memory at address'0'
. At&t syntax uses reversed operands, and it needs a$
prefix for immediates. But you already know this, I guess you were just a little careless. The correct instruction iscmpb $'0', (%esp)
to compare the byte in memory at address%esp
to the ascii code of0
.Furthermore, you allocated 4 bytes from the stack, but you never free that. When you eventually hit a
ret
it will use your local variable as return address which is of course a bad thing :) A nice trick is to uselea 4(%esp), %esp
to free it without affecting the flags, so you can do this between thecmp
and thejz
. If you like less tricky stuff, you can of course just pop the input into a register and use that in the comparison, such as:PS: Learn to use a debugger. That would have pointed you directly at the instruction, and then you probably could have figured out the problem yourself.