如何在被调用者中获取参数整数?

时间:2017-04-18 15:12:37

标签: c assembly att

我有以下代码(caller.c):

#include <stdio.h>

extern int callee(int);

int main(int argc, char *argv[]){
  callee(4);
  return 1;
}

和(callee.s):

.globl callee

callee:
  pop %eax
  add $4, %eax
  ret

我编译: gcc -m32 caller.c callee.s

并运行:

./ a.out

分段错误(核心转储)

我想知道我的错误是什么,因为我认为主要应该推动堆栈的32位数。我没有更改堆栈,因此被调用者现在应该能够从同一堆栈中弹出该数字。也许我应该在pop之前添加(添加$ 4,%esp)(如果被调用者的地址是&#34;方式&#34; /实际上已经弹出)。我也试过这个也没有成功。 callee现在应该从堆栈中获取数字并添加4。 eax寄存器应该保持callee到caller的返回值(调用约定),但是在这里我忽略了返回值。

有人可以帮助我吗?

相关问题:  calling assembly function from c

调用约定: https://en.wikipedia.org/wiki/X86_calling_conventions

1 个答案:

答案 0 :(得分:4)

(使用x86-32调用约定),函数的参数被推送到堆栈 first ,然后是返回地址。因此,您的Border defaultBorder = tf.getBorder(); ... tf.setBorder(defaultBorder); 指令会弹出返回地址,后续pop尝试返回地址0x00000004,这是未映射的内存,导致崩溃。

此外,在此约定中,被调用者应该弹出其参数。来电者会这样做。

您应该编写的代码是

ret

您可以通过编译

自行确认
callee:
    movl 4(%esp), %eax
    addl $4, %eax
    ret

使用选项unsigned int callee(unsigned int x) { return x + 4; } 并检查生成的-m32 -O2 -S -fomit-frame-pointer文件;你应该得到与上面相同的汇编代码。