My environment:
- OS: Linux 4.15.0-202-generic Ubuntu SMP x86_64
- GCC: gcc (Ubuntu 4.8.5-4ubuntu8) 4.8.5
I wrote a simple assembly program, named 'helloworld.s':
.section .data
msg:
.asciz "Hello world!\n"
.section .text
.globl _start
_start:
/* call printf() to print "Hello world!" */
mov $msg, %rdi
call printf
/* call exit() function */
movq $0, %rdi
call exit
I compiled and linked it:
$ as helloworld.s
$ ld ./a.out -o helloworld -lc -dynamic-linker /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
Now the program could work well, and I got the output:
Hello world!
Then, I wanted to compile this program with GCC. I modified it, replaced the label _start with main:
.section .data
msg:
.asciz "Hello world!\n"
.section .text
.globl main /* replace _start with main */
main: /* replace _start with main */
/* call printf() to print "Hello world!" */
mov $msg, %rdi
call printf
/* call exit() function */
movq $0, %rdi
call exit
After compiling it with gcc, gcc -o helloworld helloworld.s
, I got the executable 'helloworld'. But when I ran it, I got a wrong prompt:
$ ./helloworld
Segmentation fault (core dumped)
I debugged it with gdb, the result was as following:
(gdb) b main
Breakpoint 1 at 0x40054d
(gdb) run
Breakpoint 1, 0x000000000040054d in main ()
(gdb) stepi
0x0000000000400554 in main ()
(gdb) stepi
0x0000000000400430 in printf@plt ()
(gdb) stepi
0x0000000000400436 in printf@plt ()
(gdb) stepi
0x000000000040043b in printf@plt ()
(gdb) stepi
0x0000000000400420 in ?? ()
(gdb) stepi
0x0000000000400426 in ?? ()
(gdb) stepi
_dl_runtime_resolve_xsave () at ../sysdeps/x86_64/dl-trampoline.h:71
71 ../sysdeps/x86_64/dl-trampoline.h: No such file or directory.
(gdb) stepi
74 in ../sysdeps/x86_64/dl-trampoline.h
(gdb) stepi
76 in ../sysdeps/x86_64/dl-trampoline.h
Then I wrote a simple 'helloworld.c':
#include <stdio.h>
int main() {
printf("Hello world!\n");
}
I compiled it with gcc, and disassembled it with objdump. I got the assembly code:
00000000004004fd <main>:
4004fd: 55 push %rbp
4004fe: 48 89 e5 mov %rsp,%rbp
400501: bf 94 05 40 00 mov $0x400594,%edi
400506: e8 e5 fe ff ff callq 4003f0 <puts@plt>
40050b: 5d pop %rbp
40050c: c3 retq
40050d: 0f 1f 00 nopl (%rax)
I found that there was a push %rbp
before callq
, and pop %rbp
after it, so I added these to my program:
.section .data
msg:
.asciz "Hello world!\n"
.section .text
.globl main /* replace _start with main */
main: /* replace _start with main */
/* call printf() to print "Hello world!" */
push %rbp /* add push %rbp */
mov $msg, %rdi
call printf
pop %rbp /* add pop %rbp */
/* call exit() function */
movq $0, %rdi
call exit
I compiled it with gcc once more, and then ran it; it worked well.
I was wondering if someone could help me understand the effect of push %rbp
and pop %rbp
or refer me to some link explaining. Why couldn't the program work before I added push %rbp
and pop %rbp
to it?