【问题标题】:Assembly Segmentation fault: 11装配分段错误:11
【发布时间】:2015-02-13 02:19:00
【问题描述】:

我正在尝试将这个 C 代码转换为汇编

#include <stdlib.h>

int sub(int x, int y) {
    return 2*x+y;
}

int main(int argc, char ** argv) {
    int a;
    a = atoi(argv[1]);
    return sub(argc,a);
}

我用gcc -S math.c把它变成了Assembly,终于明白了它的大部分作用。于是我改写成这样:

.globl _main

_sub:
    push %ebp
    mov %esp, %ebp
    mov 0x8(%ebp), %eax         # int x
    mov 0xC(%ebp), %ecx         # int y
    lea (%ecx, %eax, 2), %eax   # 2 * x + y
    pop %ebp
    ret

_main:
    push %ebp
    mov %esp, %ebp
    sub $0x4, %esp              # int a
    mov 0xC(%ebp), %eax
    push 0x4(%eax)              # char*  argv[1]
    call _atoi
    add $0x4, %esp
    push %eax                   # int y
    push 0x8(%ebp)              # int x/argc
    call _sub
    mov %ebp, %esp
    pop %ebp
    ret

我正在使用gcc -m32 -Wall math.s -o math 在 OS X 上编译它,它运行良好。但是sub $0x4, %esp 这行对我来说似乎非常不必要。所以我尝试删除它,它编译得很好。但是,当我使用 ./math 2 运行它时,它会给我一个 Segmentation fault: 11 错误。

我没有看到任何看起来依赖于该行的行。所以我想知道为什么这个程序需要该行,为什么删除它会导致该错误?谢谢!

【问题讨论】:

  • 如果您不知道代码的含义,显然您没有编写代码。想修改你的故事吗?
  • 嗯,它是由 gcc 和 C 脚本生成的,但后来我尝试从头开始重写,这就是我得到的。
  • 如果你打算把它上交,你的老师会知道你没有自己写程序,因为它闻起来像编译器生成的代码。你最好从头开始。
  • 我不是,我只是想学汇编。我更新了问题以解释我是如何获得代码的。
  • 编译器正在玩堆栈技巧,但它正在遵循这个计划。 eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64

标签: assembly segmentation-fault


【解决方案1】:

首先“sub $4, %esp”这一行与变量“a”无关!

“_atoi”函数使用 XMM 寄存器,因此某些变量必须与 16 字节边界对齐。要为堆栈上的局部变量归档它,有两种可能性:

调用 ("_atoi") 的函数本身必须确保堆栈对齐到 16 个字节。这可以使用以下代码完成:

push %ebp
mov %esp, %ebp
and $0xFFFFFFF0, %esp # <- This line here
sub $0x1230, %esp

这种方法是由 32 位 Windows 和 Linux 程序完成的,因此您的程序可以在 Windows 和 Linux 上正常运行(我在 Windows 下尝试过)!

在 MacOS X 下,第二种可能性用于 32 位程序 - 在大多数操作系统上也用于 64 位程序:

调用函数时,堆栈必须已经对齐到 16 个字节。

您的程序带有“子”行:

# Here esp is esp_original
call _main      # 4 bytes
push %ebp       # 4 bytes
sub $0x4, %esp  # 4 bytes
push 0x4(%eax)  # 4 bytes
# Here esp must be esp_original+16*N
call _atoi

如果您删除“sub”指令或将其替换为“sub $8, %esp”指令,则堆栈不再对齐。如果您还需要 8 个字节的堆栈,则必须执行“sub $20, %esp”,而不是“sub $4, %esp”,因此。

遗憾的是,这一要求使得在 MacOS X 上的汇编编程变得更加困难——尤其是对于初学者而言。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多