I'm working on a small piece of i386 assembly code and encountered a segmentation fault when using the %ebx register. I would appreciate some insights into why this is happening.
I have two versions of a very simple assembly function. The function's purpose is to add two integer arguments. When I use the %ecx register, the function works correctly. However, when I switch to using the ebx register, it results in a segmentation fault. Here's the code for both versions:
Version 1 (Causes Segmentation Fault):
.globl addArgs
.text
addArgs:
movl 4(%esp), %eax
movl 8(%esp), %ebx
addl %ebx, %eax
ret
Is there something specific about the ebx register that I'm missing?
So the version below works perfectly.
Version 2 (Works Fine):
.globl addArgs
.text
addArgs:
movl 4(%esp), %eax
movl 8(%esp), %ecx
addl %ecx, %eax
ret
I am compiling my code on a 32-bit x86 system and using GCC for compilation.
In case of, here is the C code that uses the function:
#include <stdio.h>
int addArgs();
int main(){
int a = 1, b = 2;
printf("%d\n", addArgs(a, b));
return 0;
}
And this is how I compiled it :
$ gcc -march=i386 -m32 -g addArg_asm.s addArg.c -o addArg
There are rules for how routines communicate and behave, including how one passes arguments to another, how they maintain the stack, and which registers they may use freely and which they must preserve. These are called an Application Binary Interface (ABI). One ABI used on x86 architectures is the System V Application Binary Interface. Your compiler may be using this ABI or something similar.
The System V ABI specifies that
%ebp,%ebx,%edi,%esi, and%espmust be preserved by a called function—when it returns to the calling function, these registers must contain the same values they did when the routine was called. Thus, your compiler may use%ebxto hold a value that will be unchanged by calling your function. When you change%ebx, you break this requirement.The System V ABI specifies that
%ecxand%edxare scratch registers and that called routines do not have to preserve their values for the caller. Thus, your compiler will not rely on%ecxholding a value across a function call.That is seven of the eight general registers. The eighth,
%eax, is a scratch register except that it is used to return a value.