0

I've been reading [1] (By Daax Rynd) to get an understanding the stack and at around the 12th page, I'm a bit stumped by how the value 60 from sub rsp, 60 was arrived at.

[Note, all code and quotes are from that page and not my own]

Given the following C code:

void do_math(void)
{
    int x = 10;
    int y = 44;
    int z = 36;
    int w = 109;
    int a[4] = { 1, 2, 3, 4 };
    a[0] = x * a[0];
    a[1] = y * x;
    a[2] = a[1] * z;
    a[3] = w * a[2];
    printf("%d\n", a[3]);
}

which was compiled to the following assembly [copied verbatim from the website.]:

//
// Assembly listing of main()
//
mov qword ptr [rsp+24], r8
mov qword ptr [rsp+16], rdx
mov dword ptr [rsp+8], ecx
sub rsp, 40
call do_math
xor eax, eax
add rsp, 40
ret 0
//
// Assembly listing of do_math()
//
push rbp
mov rbp, rsp
sub rsp, 60
...

I got stuck at the sub rsp, 60. Reading the explanation on the next page:

Then the stack allocates space using sub rsp, 60h. This is our local variable storage space. If we look at our C excerpt you’ll notice that we have a total of 8 integer variables, as well as a 4 character string used as a format string for printf. That means we’re utilizing 32 bytes + 4 for character storage for a total of 36 bytes. Well that’s not good, it’s not 16-byte aligned. Let’s add 8, 44 – still not 16-byte aligned. Add another 8 and we get 52, damn it – no dice. The stack is still misaligned. Add another 8 and we have 60. 60 is a multiple of 16, so we’d have to allocate that much space on the stack to keep it aligned, thus the sub rsp, 60h. Unfortunately, the majority of that storage will be unused since it’s just for alignment purposes. Note that all the operands in these instructions are in hexadecimal.

As noted, the sub rsp, 60 is actually sub rsp, 0x60.

[0x60 = 96 decimal]

As I grasped that C code, there are 8 integers and 1 4-character string; thus, as stated, 36 bytes need to be placed in the stack.

I thought I understood the issue of 16-byte alignment; but given the above explanation, I'm not entirely sure anymore.

My understanding is that since 36 bytes are required PLUS the Return instruction pointer address that needs to be placed in the stack, there should be 36 + 8 = 44 bytes. But that isn't 16-byte aligned. So the closest 16-byte alignment would be 80 (0x50).

But instead, the author used 0x60 and I'm confused as how he got to that value (particularly the part where he added continually added 8 bytes to 36 bytes a few times, i.e. 36 +8 = 44, 44 + 8 = 52, and finally 52 + 8 = 60). Then he claims that 60 is a multiple of 16? (which it isn't, as far as I know) [but, 0x60 is a multiple of 16]

Can someone please clarify where I'm going wrong?

Thanks

[1] - https://revers.engineering/applied-re-the-stack/

2
  • The explanation from the site is both confusing and incorrect. As you have noted, since decimal 60 does not equal hexadecimal 0x60, sub rsp, 0x60 cannot be properly explained by adding numbers up to equal decimal 60. The example code and disassembly are not a good choice for learning about stack frames and stack alignment. You would be better served by using Compiler Explorer or compiling simple programs and analyzing their disassembled machine code on your own machine.
    – julian
    Jan 20, 2022 at 1:14
  • @julian Thanks! I appreciate the clarification. That's the closest I came with help to understanding that. But will take a look at the link.
    – ewokx
    Feb 14, 2022 at 4:14

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.