I’m trying to write a function that adds two numbers in assembly, and calling it through C. I am getting a segmentation fault when i mov eax, [ebp+8]. I know this because GDB says:
Program received signal SIGSEGV, Segmentation fault.
add () at add_two_numbers.s:12
12 mov eax, [ebp+8]
Here is my Assembly code:
.code32
.intel_syntax noprefix
.global add
.section .text
add:
push ebp
mov ebp, esp
sub esp, 4
mov eax, [ebp+8]
add eax, [ebp+12]
mov esp, ebp
pop ebp
ret
and my C Driver code:
#include <stdio.h>
int add(int, int);
int main(void)
{
int x = 4, y = 10;
int z = add(x, y);
printf("%d", z);
return 0;
}
I Compile my code using gcc -Wall -o main driver.c add_two_numbers.s
>Solution :
After reading the manual I am now really certain of my answer.
The problem is on a modern Linux, the default output of gcc is a 64 bit binary. While .code32 tells the assembler to create 32 bit code, it doesn’t change the output file format to mark it as a 32 bit .o finally so you don’t actually get the link error you would want.
32 and 64 bit code are close enough that particular code decoded correctly; but it can’t possibly work. The problem is rsp is much higher than the 4GB barrier so mov ebp, esp didn’t put the top of the stack into it, but a sheared-off pointer that points into nilspace.
The straightforward fix is to just go ahead and write 64 bit assembly.
.code
.intel_syntax noprefix
.global add
.section .text
add:
push rbp
mov rbp, rsp
sub rsp, 16 # the stack frames are 16 byte aligned so if you're going to reserve stack space, do it right!
# Arguments are in registers rdi, rsi, rdx, rcx, r8, r9
mov eax, edi
add eax, esi
mov rsp, rbp
pop rbp
ret