4

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?

JFMR
  • 23,265
  • 4
  • 52
  • 76
  • The size of the argument is not obvious from that question. So it technically could have been a 16-bit push as well (x86 supports this). Maybe they prefer 32-bit alignment. – E. van Putten Aug 17 '18 at 07:26

1 Answers1

3

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Thanks for the answer, so pushw $0x08 or pushb $0x08 valid in IA32? –  Aug 17 '18 at 07:34
  • @amjad: no, `pushb` doesn't exist. See the last section of my answer, and/or the linked question for which operand-sizes are available. – Peter Cordes Aug 17 '18 at 07:38
  • @amjad: or you could have just tried it on your desktop: `cat > foo.S` / `pushb $0x8` and run `gcc -c foo.S && objdump -drwC foo.o` to see the error message, or the disassembly if it assembles. Or do it online: https://godbolt.org/g/iTwiws. But the compiler-explorer asm-source mode doesn't show the machine code :/ – Peter Cordes Aug 17 '18 at 07:42