'push imm'如何编码?

yan*_*wen 2 x86 assembly intel nasm

<< Intel 64和IA-32架构软件开发人员手册第2B卷:指令集参考,NZ >>说:

| Opcode* | Instruction | Op/En | 64-Bit Mode | Compat/Leg Mode | Description |
|      6A | PUSH imm8   | C     | Valid       | Valid           | Push imm8.  |
|      68 | PUSH imm16  | C     | Valid       | Valid           | Push imm16. |
|      68 | PUSH imm32  | C     | Valid       | Valid           | Push imm32. |
Run Code Online (Sandbox Code Playgroud)

#cat -n test.asm

 1  bits 64
 2
 3  push byte 12
 4  push word 12
 5  push dword 12
 6  push qword 12
 7
Run Code Online (Sandbox Code Playgroud)

#nasm test.asm

 test.asm:5: error: instruction not supported in 64-bit mode
Run Code Online (Sandbox Code Playgroud)
  1. 为什么5号线是非法的?我认为它匹配'PUSH imm32'.

  2. 为什么第6行是合法的?它与"PUSH imm8/PUSH imm16/PUSH imm32"中的任何一个都不匹配.

请帮帮我!

======测试======

    I think that the Intel manual is right, the 'push imm' 
    instructions do have three encoding form:
    Form 1: 6a XX
    Form 2: 66 68 XX XX 
    Form 3: 68 XX XX XX XX

    What we are arguing is the implemental specific behavior of the NASM.

    In NASM 2.04rc1(the above example I given):
    1. The 'byte' in 'push byte imm' direct the NASM use the Form 1, 
       no matter how long the imm given in the instruction it is, the imm
       was trunked to a byte in final machine code. 
    2. The 'word' in 'push word imm' direct the NASM use the Form 2,
       no matter how long the imm given in the instruction it is, the imm 
       was trucked or zero-extended to a word in final machine code.
    3. The 'qword' in 'push dword imm' direct the NASM use the Form 3,
       no matter how long the imm given in the instruction it is, the imm 
       was trucked or zero-extended to a dword in final machine code.
       Note: the 'qword' in the instruction but 'dword' in final machine
       code, which made us confused.
    4. if none of 'byte', 'word', 'qword' is given, the NASM use the From 3.
Run Code Online (Sandbox Code Playgroud)

请参阅以下示例:

# cat -n push.asm
1  bits 64
2
3  push byte 0x21
4  push byte 0x4321
5
6  push word 0x4321
7  push word 0x654321
8
9  push qword 0x654321
10
11  push 0x21
12  push 0x4321
13  push 0x654321
14  push 0x87654321
15  push 0xa987654321
16
# nasm -v
NASM version 2.04rc1 compiled on Feb 21 2009
# nasm push.asm -o push.bin
push.asm:4: warning: signed byte value exceeds bounds
push.asm:7: warning: word data exceeds bounds
# ndisasm -b 32 push.bin // 'ndisasm -b 64 push.bin' not works right in this version of NASM.
00000000  6A21              push byte +0x21
00000002  6A21              push byte +0x21
00000004  66682143          push word 0x4321
00000008  66682143          push word 0x4321
0000000C  6821436500        push dword 0x654321
00000011  6821000000        push dword 0x21
00000016  6821430000        push dword 0x4321
0000001B  6821436500        push dword 0x654321
00000020  6821436587        push dword 0x87654321
00000025  6821436587        push dword 0x87654321

In newer NASM, the behavior changes:
(1) 'push 0x21' was encoded to '6A21' in NASM 2.10.01,
    while '6821000000' in NASM 2.04rc1; 
(2)'push dword 0x654321' in 64 bit mode was allowed 
    in NASM 2.10.01 and encoded to '6821436500'
Run Code Online (Sandbox Code Playgroud)

har*_*old 6

手册错了.(顺便说一句,这不是唯一的错误)

在64位模式下,没有32位推送.push是没有REX.W前缀的少数几个提升到64位的指令之一,你无法降级它.

编辑:实际上,我的手册版本说的是正确的:

推符号扩展imm32.堆栈指针按堆栈指针的大小递减.

所以在64位模式下,这意味着"推动qword,从立即扩展的标志".