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:
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 ;-)
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
}
deleted
deleted
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.
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
deleted