flat assembler
Message board for the users of flat assembler.
Index
> Main > X86 Stack Alignment Problem |
Author |
|
Tyler 13 Mar 2011, 22:40
How do you push a byte?
[e]sp is nothing more than a pointer. You're over thinking it. What manual chapter and section are you referring to? |
|||
13 Mar 2011, 22:40 |
|
fasmnewbie 14 Mar 2011, 01:03
Tyler wrote: How do you push a byte? Hi Tyler. Thanks for the reply. 1. Here is how I see the 16-bit wide stack segment |--------|--------| |--------|--------| |--------|--------| |--------|--------| MSB<----->LSB, just for reference If I pushed two items onto it; PUSH myByte ;push a byte, becomes |--------|myByte| |--------|--------| |--------|--------| |--------|--------| |--------|--------| PUSH myWord ; push a word. what's this gonna be? is it like this |myWord|myByte| |-------- |myWord| |--------|--------| |--------|--------| or like this |--------|myByte| |myWord|myWord| |--------|--------| |--------|--------| 2. I refered to the Intel 64 and IA32 Architectures Software's Developer Manual, Volume 1, Chapter 6, Section 6.2.2 under "Stack Alignment". Intel wrote: 6.2.2 Stack Alignment The bold quote is referring to my question #3 as well, which I believe has something to do with the SP got incremented and decremented, like sub sp, 13 Thanks. |
|||
14 Mar 2011, 01:03 |
|
fasmnewbie 14 Mar 2011, 01:37
5. If we have a double-precision data (8-byte) to be pushed onto a 32-bit wide stack, is it true that the CPU requires two read cycles of memory since it has to read from two memory addresses for such data? Is this related to "stack misalignment" and affecting performance? For example;
PUSH myDouble ;8-byte double precision on 32-bit wide stack |myDouble|myDouble|myDouble|myDouble| address n |myDouble|myDouble|myDouble|myDouble| address n-1 |----------|-----------|----------|----------| |----------|-----------|----------|----------| |----------|-----------|----------|----------| Thanks in advance. |
|||
14 Mar 2011, 01:37 |
|
revo1ution 15 Mar 2011, 04:27
fasmnewbie, there is no X86 instruction to push a byte.
You must push a word, doubleword etc. - always an even number of bytes. Then if SP is word-aligned, (even address) there is no misalignment problem. |
|||
15 Mar 2011, 04:27 |
|
MazeGen 15 Mar 2011, 07:50
fasmnewbie, it is hard to learn about x86 from the manuals. Get a debugger and start stepping your code to see what's happening.
I assume you're using 32-bit version of Windows or *nix. That means your stack is 32 bits wide. At the program startup the stack is aligned to 32 bits. In the source code, PUSH 0x12 actually means PUSH 0x00000012, and PUSH 0x1234 means PUSH 0x00001234 so the stack keeps its alignment. You can explicitly declare that you want to push 16-bit constant, but it is rarely used. You can also PUSH AX that misalignes the stack. Again, there is no point in pushing 16-bit registers to 32-bit stack in everyday programming. (You can PUSH WORD [EAX], too.) Note that you can't do PUSH AL or push 8-byte operand. These instructions do not exist on x86 (in "32-bit mode"). |
|||
15 Mar 2011, 07:50 |
|
revo1ution 15 Mar 2011, 07:55
MazeGen wrote: Note that you can't do PUSH AL or push 8-byte operand. These instructions do not exist on x86 (in "32-bit mode"). They don't exist in "16-bit mode", real or protected, either. They just don't exist |
|||
15 Mar 2011, 07:55 |
|
sinsi 15 Mar 2011, 08:35
The stack itself, as far as the processor is concerned, can be misaligned with no problems, apart from the performance hit.*
Operating systems, on the other hand, prefer (and in some cases demand (i.e. x64)) that the stack is aligned to the stack word size. *except for 'pop reg16' if SP=FFFF (et al). |
|||
15 Mar 2011, 08:35 |
|
MazeGen 15 Mar 2011, 08:45
revo1ution wrote:
Push 8-byte operand exists in 64-bit mode. |
|||
15 Mar 2011, 08:45 |
|
sinsi 15 Mar 2011, 08:55
>Push 8-byte operand exists in 64-bit mode.
Yes, as an immediate value, but it is sign-extended to the stack size. You still can't push an 8-bit register, but then again why would you? |
|||
15 Mar 2011, 08:55 |
|
MazeGen 15 Mar 2011, 09:56
The in "32-bit mode" part was there to prevent nitpicking like this. Is it really so unclear? I'm trying to simplify things for fasmnewbie. Let me correct myself:
Neither PUSH AL nor PUSH <8-byte operand> exists (for nitpickers, this does not apply to 64-bit mode). |
|||
15 Mar 2011, 09:56 |
|
sinsi 15 Mar 2011, 10:18
8-bit <> 8-byte
Sorry, what an idiot reading <> comprehension |
|||
15 Mar 2011, 10:18 |
|
fasmnewbie 15 Mar 2011, 13:47
revo1ution wrote: fasmnewbie, there is no X86 instruction to push a byte. LOL. sorry for the idiocy. I gave people the wrong example. Thanks for the explanation. |
|||
15 Mar 2011, 13:47 |
|
fasmnewbie 15 Mar 2011, 14:13
MazeGen wrote: fasmnewbie, it is hard to learn about x86 from the manuals. Get a debugger and start stepping your code to see what's happening. See, your explanation is much clearer than the manuals and my own 'test' code. Yes I am on 32-bit/64-bit AMD Turion on Windows Only that not all data are double-word 'aligned'. If lets say I pushed 3 word-sized data on the 32-bit wide stack, that means memory spaces are wasted to the same amount. I see your point why there is no practical reason to push word on double-word stack. But the inefficiency is still there if smaller data are pushed. For example, what if my program is non-string chars-intensive. I mean chars would have to be pushed onto the stack anyway. Word-padding the 8-bit chars would seem wasting. Or did I get this wrong? Thanks. |
|||
15 Mar 2011, 14:13 |
|
fasmnewbie 15 Mar 2011, 14:23
Or maybe my questions are a bit 'architectural' rather than practical.
|
|||
15 Mar 2011, 14:23 |
|
MazeGen 15 Mar 2011, 14:54
fasmnewbie wrote: Only that not all data are double-word 'aligned'. If lets say I pushed 3 word-sized data on the 32-bit wide stack, that means memory spaces are wasted to the same amount. I see your point why there is no practical reason to push word on double-word stack. But the inefficiency is still there if smaller data are pushed. You're right. The thing is that PUSH is in most cases used to pass function arguments to stack. If you have 16-bit arguments, you can pass them as such but it is unusual because you would waste only few 16-bit chunks of memory. And it is unusual to misaling the stack at the function entry so in case of odd number of 16-bit arguments stack adjustment would be needed. If you have 8-bit arguments, you would additionally have to pack them somehow since you can't PUSH them directly. Well, you could do Code: SUB ESP, 1 MOV BYTE [ESP], <8-bit register/constant> Again, this would be very unusual way to pass 8-bit argument. On the other hand, it is usual to allocate stack using SUB ESP, x, for example for local (automatic) variables in function prolog. But that's another story. |
|||
15 Mar 2011, 14:54 |
|
Madis731 16 Mar 2011, 20:05
@fasmnewbie: If you're thinking about pushing "Hello World!" on the stack then quickly forget that idea
The most efficient way to use stack is to push the address of the string but not the string one-by-one (push "H" "e" "l" ... "d" "!"). Code: push dword myHelloSample ;using later in the code: mov eax,[esp] ; if you want the address to remain on stack ; or pop eax ; finally balance the stack myHelloSample db "Hello World!",0 |
|||
16 Mar 2011, 20:05 |
|
fasmnewbie 26 Mar 2011, 08:50
MazeGen wrote:
Thank you for the explanation. |
|||
26 Mar 2011, 08:50 |
|
fasmnewbie 26 Mar 2011, 08:56
Madis731 wrote: @fasmnewbie: If you're thinking about pushing "Hello World!" on the stack then quickly forget that idea LOL. I still can't get rid of that 'C++ linked-list' hangover. Thank you. |
|||
26 Mar 2011, 08:56 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.