通过atoi调用获得段错误

时间:2014-03-20 04:03:31

标签: c linux assembly x86 atoi

我必须使用x86进行家庭作业。我一直在接受这个段落故障,但是我不确定它为什么会发生。这是代码:

    addl    $4, %eax
    movl    (%eax), %eax
    movl    %eax, (%esp)
    call    atoi

在“call atoi”之前的$ eax等于“11”。为了证明这一点,这就是我在调用之前在gdb中获得的内容。

  x/s $eax
  0xffffd658:    "11"

我想我的一个大问题是在“call atoi”之前注册$ eax应该保留什么,以及$ eax必须为该程序保留什么才能在“call atoi”中进行段错误?

编辑:有人要求登记。

  (gdb) x/s $eax
  0xffffd658:    "11"
    (gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x2aaaaaa3 in ?? ()
(gdb) inf r
eax            0x0  0
ecx            0x2aaaaaab   715827883
edx            0x0  0
ebx            0x2c3ff4 2899956
esp            0xffffd458   0xffffd458
ebp            0x80484ef    0x80484ef
esi            0x0  0
edi            0x0  0
eip            0x2aaaaaa3   0x2aaaaaa3
eflags         0x10287  [ CF PF SF IF RF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x63 99
(gdb) 

1 个答案:

答案 0 :(得分:2)

这取决于您的atoi函数是否需要%eax或堆栈中的指针。鉴于代码段,您似乎对此犹豫不决:

movl    %eax, (%esp)
call    atoi

如果那应该是将地址推送到堆栈,你需要真正 push它(它正确地修改堆栈指针)或自己修改堆栈指针(如与sub %esp, 4或其他内容一样。

x86堆栈指针指向最后推送的条目,以便push首先递减堆栈指针,然后将值存储在新指针处。这意味着movl %eax (%esp)损坏堆栈中最后一个被推送的条目,而不是在堆栈上放置一个新值。

大多数人让CPU处理数据堆叠而不是手动执行,所以你可能正在寻找:

push %eax

但是,如果相反atoi期望其%eax中的参数而不是堆栈,为什么会将其写入堆栈?那仍然会破坏那里的一切。

所以,我要做的第一件事就是选择(推送值):

addl    $4, %eax
movl    (%eax), %eax
push    %eax
call    atoi

或(对于使用%eax),只需:

addl    $4, %eax
movl    (%eax), %eax
call    atoi