In IA-32e and 64 bit mode(long mode), can we have a 32-bit stack width? It means , executing POP instruction, increases RSP to 4.
logicman112,
No. In 64-bit mode opsize prefix changes operand size from 64-bit to 16-bit (?!).
No. In 64-bit mode opsize prefix changes operand size from 64-bit to 16-bit (?!).
Thanks for the reply.
The reason i asked, is the following lines from Intel manual:
6.2.5 Stack Behavior in 64-Bit Mode
PUSH/POP instructions increment/decrement the stack using a 64-bit width. When the contents of a segment register is pushed onto 64-bit stack, the pointer is auto-
matically aligned to 64 bits (as with a stack that has a 32-bit width).
What does it ("a stack that has a 32-bit width") indicate here? Does it indicate that alignment is done for 32 and 64 bits stacks?
The reason i asked, is the following lines from Intel manual:
6.2.5 Stack Behavior in 64-Bit Mode
PUSH/POP instructions increment/decrement the stack using a 64-bit width. When the contents of a segment register is pushed onto 64-bit stack, the pointer is auto-
matically aligned to 64 bits (as with a stack that has a 32-bit width).
What does it ("a stack that has a 32-bit width") indicate here? Does it indicate that alignment is done for 32 and 64 bits stacks?
if we execute:
PUSH r/m16
means if we push 16 bit register or memory data in 64 bit mode, will RSP be decremened to 8?
How we can specify 16 bit register or memory in 64 bit mode? by using prefixes?
PUSH r/m16
means if we push 16 bit register or memory data in 64 bit mode, will RSP be decremened to 8?
How we can specify 16 bit register or memory in 64 bit mode? by using prefixes?
logicman112,
"as with a stack that has a 32-bit width" refers to the fact that in legacy/compatibility 32-bit mode with 32-bit stack push sreg zero-extends selector to 32 bits before pushing it (if used without opsize prefix).
push r/m16 always decrements stack pointer by 2. And yes, it uses opsize prefix in 32/64-bit mode.
"as with a stack that has a 32-bit width" refers to the fact that in legacy/compatibility 32-bit mode with 32-bit stack push sreg zero-extends selector to 32 bits before pushing it (if used without opsize prefix).
push r/m16 always decrements stack pointer by 2. And yes, it uses opsize prefix in 32/64-bit mode.
Depends a bit, assemblers will generally push 16 bits, but compilers will often extend the 16 bit word to a dword (32 bit c compilers), generally you should avoid passing 16 bit values if you expect your functions to be called by the general programming community.
Homer,
Calling conventions have nothing to do with instructions, they only specify what and where should be put by caller/callee (and expected by callee/caller). How do you put it there is out of scope: any means will do.
Below is FASM source for simple program that doesn't push anything, yet it uses stdcall Win32 API:
Calling conventions have nothing to do with instructions, they only specify what and where should be put by caller/callee (and expected by callee/caller). How do you put it there is out of scope: any means will do.
Below is FASM source for simple program that doesn't push anything, yet it uses stdcall Win32 API:
format PE GUI
include "WIN32A.INC"
section ".code" code executable readable writeable
entry $
mov esp, wicked_stack
MessageBox: jmp [__imp__MessageBoxA@16]
ExitProcess: jmp [__imp__ExitProcess@4]
eax_eq_literal?_branch:
cmp eax,
pop eax
pop eax
jnz @f
mov esp, eax
@@: ret
rb 65536
section ".data" data readable writeable
wicked_stack:
dd MessageBox
dd HWND_DESKTOP, hello_world, hello_caption, MB_OK+MB_ICONEXCLAMATION
dd eax_eq_literal?_branch
dd HWND_DESKTOP, goodbye_world, hello_caption, MB_YESNO+MB_ICONQUESTION
dd IDYES, goodbye_ok
dd MessageBox
dd ExitProcess
dd HWND_DESKTOP, goto_hell_world, hello_caption, MB_OK+MB_ICONINFORMATION
dd 0
dd -1
goodbye_ok: dd ExitProcess
dd 0
dd 0
hello_caption db "Weird Hello", 0
hello_world db "Hello, World!", 0
goodbye_world db "Goodbye, World?", 0
goto_hell_world db "Go to hell, cruel World!", 0
data import
library USER32, "USER32.DLL",\
KERNEL32, "KERNEL32.DLL"
import USER32,\
__imp__MessageBoxA@16, "MessageBoxA"
import KERNEL32,\
__imp__ExitProcess@4, "ExitProcess"
end data
PUSH (%bx)
If the instruction above is executed in 64 bit mode, then i can only push the first 64 k bytes of linear address(memory locations from 0 to FFFF). Is that right?
While executing the same instruction in 32 bits mode (legacy protected) can address any location at 4 G bytes RAM. So the 16 bit push of 64 bit mode seems a limit!!
Another question: in legacy/32 bit mode and the stack width is 16 bits (B=0), when PUSH is executed, ( suppose sp ==1), will the upper 16 bits of ESP is effected? means from hardware point of view, RSP is involved in this decrement process or ESP or only SP?
If the instruction above is executed in 64 bit mode, then i can only push the first 64 k bytes of linear address(memory locations from 0 to FFFF). Is that right?
While executing the same instruction in 32 bits mode (legacy protected) can address any location at 4 G bytes RAM. So the 16 bit push of 64 bit mode seems a limit!!
Another question: in legacy/32 bit mode and the stack width is 16 bits (B=0), when PUSH is executed, ( suppose sp ==1), will the upper 16 bits of ESP is effected? means from hardware point of view, RSP is involved in this decrement process or ESP or only SP?
logicman112,
Yes, with address-size 16 in 64-bit mode you can address only first 64 KiB of segment. Default ds segment with base 0 maps this range to first 64 KiB of linear address space, but fs or gs segment override prefix can place it anywhere.
In legacy/compatibility 32-bit mode the limitation is the same: you can address only first 64 KiB of any segment with 16-bit address. Moreover, in 16-bit real/protected mode it's the same! ;)
When stack-address-size is 16, only sp is used.
Yes, with address-size 16 in 64-bit mode you can address only first 64 KiB of segment. Default ds segment with base 0 maps this range to first 64 KiB of linear address space, but fs or gs segment override prefix can place it anywhere.
In legacy/compatibility 32-bit mode the limitation is the same: you can address only first 64 KiB of any segment with 16-bit address. Moreover, in 16-bit real/protected mode it's the same! ;)
When stack-address-size is 16, only sp is used.
As I understand logicman112's quote from the Intel manual, the emphasis should be on "segment register". I'm not familiar with 64-bit code, but in 32-bit code, pushing a segment register adjusts the stack by 32 bits - unlike pushing a 16-bit GP register! I think that's what it's getting at...
Best,
Frank
Best,
Frank
fbkotler,
You've understood it right.
Stack operations involve three attributes: stack-address-size (sp/esp/rsp), operand-size (obvious for r/m, not-so-obvious for segment registers) and address-size (when memory reference is used). In 64-bit mode stack-address-size is 64, default operand-size is 64 (one of exceptions to common 32 rule) and default address-size is 64 too.
Consequently, push fs is indeed push qword fs (i.e. fs is zero-extended to 64 bits, then result is pushed on stack, adjusting rsp by -8). With operand-size prefix this instruction becomes push word fs and does exactly what is expected: pushes word and adjusts rsp by -2.
In 32-bit mode the situation is similar (64->32, qword->dword, -8 -> -4).
logicman112,
I have to apologize for misleading statement in my previous post: 64-bit mode doesn't support 16-bit addressing. The rest of that is correct AFAIK.
You've understood it right.
Stack operations involve three attributes: stack-address-size (sp/esp/rsp), operand-size (obvious for r/m, not-so-obvious for segment registers) and address-size (when memory reference is used). In 64-bit mode stack-address-size is 64, default operand-size is 64 (one of exceptions to common 32 rule) and default address-size is 64 too.
Consequently, push fs is indeed push qword fs (i.e. fs is zero-extended to 64 bits, then result is pushed on stack, adjusting rsp by -8). With operand-size prefix this instruction becomes push word fs and does exactly what is expected: pushes word and adjusts rsp by -2.
In 32-bit mode the situation is similar (64->32, qword->dword, -8 -> -4).
logicman112,
I have to apologize for misleading statement in my previous post: 64-bit mode doesn't support 16-bit addressing. The rest of that is correct AFAIK.