我正在尝试在汇编中实现atoi(netwide汇编程序)。我通过使用调试器检查寄存器值来验证我的方法是有效的。问题是应用程序即将退出时会崩溃。我担心我的程序会以某种方式破坏堆栈。我正在链接GCC stdlib以允许使用printf函数。我注意到它突变了导致意外行为的寄存器(对我无法识别的值的广泛迭代),但是我通过将EAX的值存储在EBX中(未经printf修改)然后在函数调用之后恢复该值来解决这个问题。这就是为什么我能够通过单击算法确认程序现在表现得如此,并确认程序在即将终止时崩溃。 这是代码:
global _main
extern _printf
section .data
_str: db "%d", 0
section .text
_main:
mov eax, 1234
mov ebx, 10
call _itoa
_terminate:
ret
_itoa:
test eax, eax
jz _terminate
xor edx, edx
div ebx
add edx, 30h
push eax
push edx
push _str
call _printf
add esp, 8
pop eax
jmp _itoa
这是stackdump:
例外:在eip = 00402005的STATUS_ACCESS_VIOLATION eax = 00000000 ebx = 00000000 ecx = 20000038 edx = 61185C40 esi = 612A3A7C edi = 0022CD84 ebp = 0022ACF8 esp = 0022AC20 program = C:\ Cygwin \ home \ Benjamin \ nasm \ itoa.exe,pid 3556,thread main cs = 001B ds = 0023 es = 0023 fs = 003B gs = 0000 ss = 0023 堆栈跟踪: 帧功能参数 0022ACF8 00402005(00000000,0022CD84,61007120,00000000) 堆栈跟踪结束
编辑:请注意,stackdump不再那么相关,因为程序不再崩溃,只是显示不正确的值。
答案 0 :(得分:0)
我不熟悉您的平台,但我希望您在调用printf()
后弹出推送的值来恢复堆栈。
由于printf()
不知道将传递多少个参数,因此无法恢复堆栈。您的代码会推送从未弹出的参数。因此,当您的过程返回时,它将从堆栈上推送的数据中获取返回地址,这些数据不会指向有效代码。这将是您的访问违规行为。