-1

我正在尝试在汇编(网络汇编器)中实现 atoi。我已经通过使用调试器检查寄存器值来验证我的方法是有效的。问题是应用程序在即将退出时会崩溃。我担心我的程序以某种方式破坏了堆栈。我正在链接 GCC 标准库以允许使用 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

这是堆栈转储:

例外: STATUS_ACCESS_VIOLATION 在 eip=00402005 eax=00000000 ebx=00000000 ecx=20000038 edx=61185C40 esi=612A3A7C edi=0022CD84 ebp=0022ACF8 esp=0022AC20356home,pid 程序=C:\Cygwin,\ , 线程主 cs=001B ds=0023 es=0023 fs=003B gs=0000 ss=0023 堆栈跟踪: 帧函数参数 0022ACF8 00402005 (00000000, 0022CD84, 61007120, 00000000) 堆栈跟踪结束

编辑:请注意,由于程序不再崩溃,stackdump 真的不再那么相关了,它只是显示了一个不正确的值。

4

1 回答 1

0

我不熟悉您的平台,但我希望您需要通过在调用printf().

由于printf()不知道将传递多少个参数,因此无法恢复堆栈。您的代码推送永远不会弹出的参数。因此,当您的过程返回时,它会从压入堆栈的数据中获取返回地址,这些数据不会指向有效代码。那将是您的访问违规。

于 2013-08-16T20:54:44.487 回答