Understanding assembly code: "mov dword" and "mov qword" in main.c

Below is the assembly code generated from my c program:

SECTION .text align=1 execute ; section number 1, code main: ; Function begin push rbp ; 0000 _ 55 mov rbp, rsp ; 0001 _ 48: 89. E5 mov dword [rbp-4H], edi ; 0004 _ 89. 7D, FC mov qword [rbp-10H], rsi ; 0007 _ 48: 89. 75, F0 mov eax, 1 ; 000B _ B8, 00000001 pop rbp ; 0010 _ 5D ret ; 0011 _ C3 ; main End of function SECTION .data align=1 noexecute ; section number 2, data SECTION .bss align=1 noexecute ; section number 3, bss 
asked Jan 14, 2019 at 0:34 supmethods supmethods 123 1 1 silver badge 2 2 bronze badges

1 Answer 1

Variables are aligned to some extent to help faster access to them. The alignment value is usually an implementation detail, but compilers usually follow Intel's recommendations to align/place variables next to each other.

Performance penalty of unaligned access to the stack happens when a memory reference splits a cache line. This means that one out of eight spatially consecutive unaligned quadword accesses is always penalized, similarly for one out of 4 consecutive, non-aligned double-quadword accesses, etc.

Aligning the stack may be beneficial any time there are data objects that exceed the default stack alignment of the system. For example, on 32/64bit Linux, and 64bit Windows, the default stack alignment is 16 bytes, while 32bit Windows is 4 bytes.

Assembly/Compiler Coding Rule 55. (H impact, M generality) Make sure that the stack is aligned at the largest multi-byte granular data type boundary matching the register width.

In your case on x64 the registers are 8 bytes wide and argc being an int is 4 bytes wide. Following the guideline above the variables are aligned to 8-byte boundary.

 ► 0x5555555545fe mov dword ptr [rbp - 4], edi 0x555555554601 mov qword ptr [rbp - 0x10], rsi 0x555555554605 mov eax, 0x2a 0x55555555460a pop rbp 0x55555555460b ret 

edi stores argc a 32 bit value - packed in a 64 bit boundary with the upper 32 bits of no use for you.

pwndbg> tele rbp-0x10 00:0000│ 0x7fffffffdf10 —▸ 0x7fffffffe000 ◂— 0x1 01:0008│ 0x7fffffffdf18 ◂— 0x0 02:0010│ rbp rsp 0x7fffffffdf20 —▸ 0x555555554610 (__libc_csu_init) ◂— push r15 

So the argv starts 8 bytes above argv