I decided that I need to understand this more thoroughly, so am working in parallel with two resources: one more modern and one original from @Aleph1.

In the essay, there is a basic code snippet, called example1.c, thus:

void function(int a, int b, int c) { 
    char buffer1[5];
    char buffer2[10];
void main() { 

In the illustrated disassembly of that, once complied obvs, thus:

pushl %ebp
movl %esp,%ebp
subl $20,%esp

where $20 is the size due to word size, as the 5 char buffer takes 8 bytes (2 words) and the 10 char buffer takes 12 bytes (3 words). So far so simple. This makes perfect sense to me.

While playing along on Ubuntu 12.04 - 32bit version [chosen due to the other parallel disassembly blog post] - the same disassembly comes out as:

push   %ebp
mov    %esp,%ebp
sub    $0xc,%esp

where $0xc is 12 in decimal. What is the reason for this discrepancy, assuming that I've copied the code properly. It's not really holding up my progress, but I feel that I should be able to understand why my code is subtracting by 12 bytes, and the example by 20. My best guess is that it's down to the architecture of the OS that I'm using in some way, but would like someone with more experience to validate this or tell me why.


I was comparing apples with oranges, which I've just realised. The code from Aleph1's essay where it talks about the subl $20 came from the -S (assembly) output from gcc, and is discussing the prolog whereas the code I took the sub 0xc came from within gdb and running disassemble main.

I have run gcc -S to produce example1.s - but that produces a different result again, although I suspect it's down to Johan's comment about gcc options, which happen to be gcc -g -fno-stack-protector -z execstack -S -o example1.s example1.c. Looking in the prolog, the result that I get here is subl %16 (which in dec is 22).

It has simply raised more questions! :D

Update 2

Dump of assembler code within gdb is:

 0x080483bc <+0>:   push   %ebp
 0x080483bd <+1>:   mov    %esp,%ebp
 0x080483bf <+3>:   sub    $0xc,%esp

Is that why we see $0xc (12 in decimal) because it's showing as <+3> (i.e. +3 words, 12 bytes)?

  • What are your compilation flags for the 2nd snippet? As function doesn't use either buffer, it's likely the compiler did some optimization on the code. I could see the compiler recognizing it's okay to overlap the buffers so it chose the smallest DWORD-aligned buffer to hold both (=12 bytes). – Johann Aydinbas Jan 31 '20 at 13:29
  • Good shout:-g -fno-stack-protector -z execstack -o – FiddleDeDee Jan 31 '20 at 13:53
  • I tried taking out the -o so that gcc output a.out and then gdb'd that - same sub amount of $0xc – FiddleDeDee Jan 31 '20 at 14:01
  • Try adding -O0 (letter O followed by number zero) or -Og and see if it changes something. Another trick might be adding the volatile keyword in front of your buffers. That way the compiler cannot reason about use of them and try to optimize stuff but I'm not 100% it works here. Quick edit: Apparently gdb defaults to -O0 when nothing is specified. – Johann Aydinbas Jan 31 '20 at 22:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.