在<<英特尔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. |
#猫-n TEST.ASM
1 bits 64
2
3 push byte 12
4 push word 12
5 push dword 12
6 push qword 12
7
#NASM TEST.ASM
test.asm:5: error: instruction not supported in 64-bit mode
为什么5号线是非法的? 我认为这符合“PUSH IMM32”。
为什么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.
请看下面的例子:
# 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'
该手册是错误的。 (这不是唯一的错误,顺便说一句)
在64位模式下,没有32位的推动。 push
是被提拔没有REX.W前缀到64位的几个指令之一,你不能降级了。
编辑:其实,我本手册的版本说,正确的事情:
按符号扩展IMM32。 堆栈指针堆栈指针的大小递减。
因此,在64位模式下,翻译过来就是“推四字,兆头立即扩展”。
编辑 :下面的受灾文字是错误的WRT立即数。
下面是它如何工作的?
无论操作数大小是,在64位模式下,可以仅由2首或8个字节与推进堆栈指针push
并在正是如此分配的空间或者是16位或64位值写。
所以,你不能推8位寄存器或32位寄存器,因为他们不会得到零或符号扩展。 但是,你可以把16位或64位的寄存器。
随着立即数这是一个有点不同。
push imm8
(操作码为6Ah随后的imm8)将首先的8位立即操作数符号扩展到64位,然后按所得到的8字节的值。
push imm32
(操作码68H随后IMM32)将首先的32位立即操作数符号扩展到64位,然后按所得到的8字节的值。
push imm16
(操作数大小前缀66H,操作码为6Ah随后imm16)将推16位立即操作数没有任何扩展为2个字节的值。
NASM当你说似乎有点宽容push qword 12
。 但是,如果你使用了无法表示为有符号的32位整数值时,它会发出警告,如push qword 0x80000000
或push qword 2147483648
或push qword -2147483649
。
This is the relevant piece of documentation:
ELSE IF SRC is immediate byte
THEN TEMP ← SignExtend(SRC); (* extend to operand size *)
ELSE IF SRC is immediate word (* operand size is 16 *)
THEN TEMP ← SRC;
ELSE IF SRC is immediate doubleword (* operand size is 32 or 64 *)
THEN
IF operand size = 32
THEN TEMP ← SRC;
ELSE TEMP ← SignExtend(SRC); (* extend to operand size of 64 *)
FI;
现在,我的版本的NASM(10年2月9日在2011年7月15日编译)实际上并没有发出警告或错误push dword 12
。 如果你确实,这是一个错误。
它看起来像我发现在NASM的错误。 它汇集push word 12
到66小时,为6Ah,0CH。 IOW,它使用的操作码push imm8
为push imm16
。 这不可能是正确的。 字节操作数保持字节操作数,无论操作数大小前缀。 只有“字”操作数,可以扩大或缩小以双精度和四字操作数。 这就是它一直是,对于相同的指令一对操作码的,一个对字节的操作数,其他的(Q / d)字操作数和操作数尺寸前缀会影响的“字”的“wordness”操作操作数。 的正确的编码push word 12
在64位模式下应该是66H,68H,0CH,0H。
5号线是非法的,因为在64位模式下,你不能把一个32位的操作数。 只能推一个64位操作数( push byte 12
被有效地push byte-sign-extended-to-qword 12
)或16位操作数。 看一个伪代码解释的操作push
:
IF in 64-bit mode (* stack-address size = 64 *)
THEN
IF operand size = 64
THEN
RSP ← RSP − 8;
Memory[RSP] ← TEMP; (* Push quadword *)
ELSE (* operand size = 16 *)
RSP ← RSP − 2;
Memory[RSP] ← TEMP; (* Push word *)
FI;
我不能告诉这个的确切原因,但有两个:
- 这是实现这种方式方便
- 设计者试图使不对齐的堆栈错误的可能性较小
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.
请看下面的例子:
# 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