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.
Posted on 2010-07-17 01:59:24 by logicman112
logicman112,

No. In 64-bit mode opsize prefix changes operand size from 64-bit to 16-bit (?!).
Posted on 2010-07-17 03:43:43 by baldr
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? 
Posted on 2010-07-17 03:57:00 by logicman112
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?
Posted on 2010-07-17 04:04:01 by logicman112
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.
Posted on 2010-07-17 04:37:59 by baldr
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.
Posted on 2010-07-17 05:08:07 by Homer
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:

                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
Posted on 2010-07-17 05:54:33 by baldr
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?

Posted on 2010-07-17 23:21:29 by logicman112
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.
Posted on 2010-07-18 01:16:39 by baldr
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

Posted on 2010-07-18 10:01:03 by fbkotler
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.
Posted on 2010-07-18 15:06:13 by baldr