assembly 为什么使用%ebx寄存器会在我的汇编代码中导致分段错误

hrysbysz  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(65)

我正在处理一小段i386汇编代码,在使用%ebx寄存器时遇到了一个分段错误。
我有一个非常简单的汇编函数的两个版本。该函数的目的是添加两个整数参数。当我使用%ecx寄存器时,该函数可以正常工作。但是,当我切换到使用ebx寄存器时,它会导致分段错误。下面是两个版本的代码:
版本1(导致分段故障):

.globl addArgs
.text
addArgs:
    movl 4(%esp), %eax
    movl 8(%esp), %ebx
    addl %ebx, %eax
    ret

字符串
我是不是漏掉了什么关于ebx寄存器的东西?
所以下面的版本工作得很好。
版本2(工作正常):

.globl addArgs
.text
addArgs:
    movl 4(%esp), %eax
    movl 8(%esp), %ecx
    addl %ecx, %eax
    ret


我在32位x86系统上编译代码,并使用GCC进行编译。
下面是使用该函数的C代码:

#include <stdio.h>

int addArgs();

int main(){
    int a = 1, b = 2;
    printf("%d\n",  addArgs(a, b));
    return 0;
}


我是这样编译的:

$ gcc -march=i386 -m32 -g  addArg_asm.s addArg.c -o addArg

ifsvaxew

ifsvaxew1#

例程的通信和行为都有规则,包括如何将参数传递给另一个例程,如何维护堆栈,以及哪些寄存器可以自由使用,哪些必须保留。这些规则称为应用程序二进制接口(ABI)。在x86架构上使用的一个ABI是System V应用程序二进制接口。您的编译器可能正在使用此ABI或类似的东西。
System V ABI指定%ebp%ebx%edi%esi%esp必须由被调用函数保留-当它返回到调用函数时,这些寄存器必须包含与调用例程时相同的值。因此,你的编译器可能会使用%ebx来保存一个值,这个值在调用你的函数时不会改变。2当你改变%ebx时,你就打破了这个要求。
System V ABI指定%ecx%edx是临时寄存器,并且被调用的例程不必为调用者保留它们的值。因此,编译器将不依赖于%ecx在函数调用中保存值。
这是8个通用寄存器中的7个,第8个%eax是一个临时寄存器,只是它用来返回一个值。

相关问题