The first three lines we see are the function prologue that was mentioned above. Meaning in the first line, the base pointer is pushed onto the stack. Then the stack pointer is made equal to the base pointer. Then the stack pointer is decremented to make room for local variables within the main function.
The next instruction movl $0x64,-0x4(%rbp) stands for move long, and it is moving the value of 0x64 in hex (100 in decimal) to a local variable 4 bytes above the current base pointer. In the source code, we can see this being the line that declares an integer variable that gets initialized to 100 int var1 = 100;.
The next three instructions (lea, mov, and call) are all for printing the hello world statement. The lea 0xeb5(%rip),%rax instruction finds and calculates the address of the string to print and stores it into rax. Then, it copies the value (the address that has been calculated that contains the string) in rax and stores it into rdi. This is because the puts function (which is about to be called) expects the address of the string (to print) in the RDI register. Then the call instruction calls puts which will print the text found at the address that was calculated.
The mov instruction is moving the value of hex 0 (decimal 0) into the eax register. The eax register usually stores the return value.
The leave instruction is equivalent to the two instructions mov %rbp, %rsp and pop %rbp. It effectively undoes the actions of the function prologue, restoring RSP and RBP to their original values. Notice how the mov instruction has the arguments switched compared to the beginning when the function prologue starts. The pop command pops it (removes it) off the stack.
The ret instruction pops the return address off the stack and jumps to it, thus giving control back to the calling function (in this case, there is none so the whole program
Bonus: Navigating Through GDB
First step is to load in GDB (by running gdb with the program name as the argument), set a break point in main, run it, and view the disassembly of main:
The commands used were:
b main - set a breakpoint in main
r - run the program
disass main - show disassembly in main
Then, setting a breakpoint after the string’s address location is calculated, and reading into the register is saved into:
The commands used:
b *[address] - set a breakpoint at that specific address
c - continue execution
x/s $rax - prints the string stored at the memory address stored in the RAX register. The x command is used to examine memory and the /s flag specifies to display the contents of memory as a string.
Other useful commands
stepi - step to the next instruction
info registers - display information about the registers and their values
$ gdb program1.elf
GNU gdb (Debian 13.1-3) 13.1
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from program1.elf...
(No debugging symbols found in program1.elf)
(gdb) b main
Breakpoint 1 at 0x113d
(gdb) r
Starting program: /home/kali/Desktop/assembly_fun/program1.elf
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, 0x000055555555513d in main ()
(gdb) disass main
Dump of assembler code for function main:
0x0000555555555139 <+0>: push %rbp
0x000055555555513a <+1>: mov %rsp,%rbp
=> 0x000055555555513d <+4>: sub $0x10,%rsp
0x0000555555555141 <+8>: movl $0x64,-0x4(%rbp)
0x0000555555555148 <+15>: lea 0xeb5(%rip),%rax # 0x555555556004
0x000055555555514f <+22>: mov %rax,%rdi
0x0000555555555152 <+25>: call 0x555555555030 [puts@plt](<mailto:puts@plt>)
0x0000555555555157 <+30>: mov $0x0,%eax
0x000055555555515c <+35>: leave
0x000055555555515d <+36>: ret
End of assembler dump.
(gdb) b *0x000055555555514f
Breakpoint 2 at 0x55555555514f
(gdb) c
Continuing.
Breakpoint 2, 0x000055555555514f in main ()
(gdb) x/s $rax
0x555555556004: "Hello world"