News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Stack Alignment

Started by TBRANSO1, March 01, 2019, 05:00:02 AM

Previous topic - Next topic

TBRANSO1

As I get deeper into study and using either the 32 or 64-bit platforms, I see a lot of you go through efforts to align the stack.  The MSDN discusses it for C/C++, but it forces me to ask, how do I know if my stack is unaligned?

It may be a naive assumption, but if a C/C++ or MASM program starts from a main, isn't the stack aligned when it loaded by the kernel for execution?  then how does it get unaligned? and why does it seem that a lot of your code calls for alignment?

:icon_confused:

jj2007

On entry, the stack is aligned. Any misalignment is caused by bad code:

- in 32-bit code, you can misalign stack by pushing a word instead of a dword: try push ax before invoking a MessageBox. Besides, if you use SIMD instructions like movaps with local variables, you may run into trouble, too, but it's not the stack's fault. Use a debugger and check what a movaps xmm0, somelocalOword does.

- in 64-bit code, you have more chances to misalign stack because it must be aligned to 16 bytes while the standard push reg changes the stack by 8 bytes. So, if you use push & pop always in pairs (push rax, push rdi .... pop rdi, pop rax), then the stack will never be misaligned.

That was the short answer ;-)

TBRANSO1

Quote from: jj2007 on March 01, 2019, 05:05:22 AM
On entry, the stack is aligned. Any misalignment is caused by bad code:

- in 32-bit code, you can misalign stack by pushing a word instead of a dword: try push ax before invoking a MessageBox. Besides, if you use SIMD instructions like movaps with local variables, you may run into trouble, too, but it's not the stack's fault. Use a debugger and check what a movaps xmm0, somelocalOword does.

- in 64-bit code, you have more chances to misalign stack because it must be aligned to 16 bytes while the standard push reg changes the stack by 8 bytes. So, if you use push & pop always in pairs (push rax, push rdi .... pop rdi, pop rax), then the stack will never be misaligned.

That was the short answer ;-)

That helps a bit...

How would we do this in Masm if we had to? (example from MSDN)

// Total size = 24 bytes, alignment = 8 bytes (quadword).

_declspec(align(8)) struct {
    int a;       // +0; size = 4 bytes
    double b;    // +8; size = 8 bytes
    short c;     // +16; size = 2 bytes
}

// Total size = 12 bytes, alignment = 4 bytes (doubleword).

_declspec(align(4)) struct {
    char a;       // +0; size = 1 byte
    short b;      // +2; size = 2 bytes
    char c;       // +4; size = 1 byte
    int d;        // +8; size = 4 bytes
}


nidud

#3
deleted

nidud

#4
deleted

aw27

Quote from: TBRANSO1 on March 01, 2019, 05:00:02 AM
:icon_confused:
This issue is relevant to 64-bit code. The stack is ALWAYS NOT aligned on entry to a function because it was aligned at the time of call to the function (hopefully  :badgrin:).
Now, you have a few alternatives to fix that:
1) You can do the alignment manually but takes some experience to make it right. I prefer this way, but there are easier ways.
2) You can use the masm64 SDK prologue, which will align it for you.
3) You can use alternative assemblers, like UASM and probably Nidud's ASMC (although I have no experience with this one). They will align the stack if you set some options.

TimoVJL

Examples from C++ compilers:int __cdecl main(void)
{
float __declspec(align(32)) ionea[8]={0,0,0,0,0,0,0,0};
float __declspec(align(32)) qonea[8]={0,0,0,0,0,0,0,0};
msvcmain:
00000000  4055                     push rbp
00000002  4881EC80000000           sub rsp, 80h
00000009  488D6C2440               lea rbp, [rsp+40h]
0000000E  4883E5E0                 and rbp, -20h
clangmain:
00000000  55                       push rbp
00000001  4883EC70                 sub rsp, 70h
00000005  488D6C2470               lea rbp, [rsp+70h]
0000000A  4883E4E0                 and rsp, -20h

May the source be with you

nidud

#7
deleted