gpt4 book ai didi

c - 弹出 x86 堆栈以访问函数 arg 时出现段错误

转载 作者:太空狗 更新时间:2023-10-29 16:20:58 26 4
gpt4 key购买 nike

我正在尝试链接 x86 程序集和 C。

我的 C 程序:

extern int plus_10(int);

# include <stdio.h>

int main() {
int x = plus_10(40);
printf("%d\n", x);
return 0;
}

我的汇编程序:

[bits 32]

section .text

global plus_10
plus_10:
pop edx
mov eax, 10
add eax, edx
ret

我将两者编译链接如下:

gcc -c prog.c -o prog_c.o -m32
nasm -f elf32 prog.asm -o prog_asm.o
gcc prog_c.o prog_asm.o -m32

但是,当我运行生成的文件时,出现了段错误。

但是当我更换

pop edx

mov edx, [esp+4]

程序运行良好。有人可以解释为什么会这样吗?

最佳答案

这是一个可能的汇编代码 int x = plus_10(40);

        push    40                      ; push argument
call plus_10 ; call function
retadd: add esp, 4 ; clean up stack (dummy pop)
; result of the function call is in EAX, per the calling convention

; if compiled without optimization, the caller might just store it:
mov DWORD PTR [ebp-x], eax ; store return value
; (in eax) in x

现在当您调用 plus_10 时,地址 retaddcall 指令压入堆栈。它实际上是 push+jmp,而 ret 实际上是 pop eip

因此您的堆栈在 plus_10 函数中看起来像这样:

|  ...   |
+--------+
| 40 | <- ESP+4 points here (the function argument)
+--------+
| retadd | <- ESP points here
+--------+

ESP 指向包含返回地址的内存位置。

现在,如果您使用 pop edx,返回地址将进入 edx,堆栈如下所示:

|  ...   |
+--------+
| 40 | <- ESP points here
+--------+

现在,如果您在此时执行 ret,程序实际上将跳转到地址 40,并且很可能会出现段错误或以其他一些不可预测的方式运行。

编译器生成的实际汇编代码可能不同,但这说明了问题。


顺便说一句,编写函数的一种更有效的方法是:对于这个小函数的非内联版本,这是大多数编译器在启用优化的情况下所做的。

global plus_10
plus_10:
mov eax, [esp+4] ; retval = first arg
add eax, 10 ; retval += 10
ret

这比

更小且效率更高
    mov   eax,  10
add eax, [esp+4] ; decode to a load + add.
ret

关于c - 弹出 x86 堆栈以访问函数 arg 时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56113827/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com