Reputation:
There is a question on my textbook: Give the correct suffix based on the operands:
push $0xFF
And the answer is:
pushl $0xFF
But why not pushb $0xFF
(I think pushb
doesn't exist) or pushw $0xFF
(pushw
does exist), since 0xFF
is one byte, why it has to be 'l' which is 32 bits/4 bytes?
Upvotes: 4
Views: 3881
Reputation: 365812
The default operand-size for push
in AT&T syntax (and in all other assemblers, like NASM and MASM) is the width of the current mode. (16 bits in 16-bit mode, 32 bits in 32-bit mode, 64 bits in 64-bit mode.) This matches the "stack width" of call
/ret
.
How many bytes does the push instruction push onto the stack when I don't specify the operand size?
The default version of pop
is also the version that takes no extra machine-code prefixes to encode.
Most instructions require an explicit operand-size when there's ambiguity, e.g. mov $1234567, (%esp)
is invalid, but mov %eax, (%esp)
is legal because a register implies the operand-size.
But push
-immediate if funny: non-default widths for push
are so rarely used that asm syntax designers chose to give it a default without requiring pushl $0xff
(AT&T) or push dword 0xff
(NASM). Note that Intel-syntax came first; AT&T came after. So perhaps the AT&T syntax designers were following the conventions of early Intel-syntax assemblers.
I point this out because it's only 1 extra letter for AT&T syntax for a size suffix, but more clunky looking in Intel syntax.
push
-immediate was heavily used in traditional inefficient calling conventions that always pass args on the stack, so it makes sense to make it easy to type.
Did your textbook really say "push a byte", or is that something you made up?
You can't push just a byte in x86, as you say.
Your assembler won't even be able to use the pushl imm8
encoding, because 0x000000FF
doesn't fit in a sign-extended 8-bit integer. Only values from -128 (0xFFFFFF80) to 127 (0x0000007F) fit in a signed 8-bit integer.
Upvotes: 3