我的问题是RETurn指令在64位模式中及其操作数大小,它指定从堆栈到RIP的信息弹出量以及RSP增量的字节数。
我注意到一些汇编程序保留了Intel定义的默认操作数大小。即近返回64位,远回32位:
1 ; Assembled with NASM 2.12 command "nasm TestRET.asm -l TestRET.lst"
2 BITS 64
3 00000000 66CF IRETW ; Opsize 16.
4 00000002 CF IRETD ; Opsize 32.
5 00000003 48CF IRETQ ; Opsize 64.
6 00000005 66CF o16 IRET ; Opsize 16.
7 00000007 CF o32 IRET ; Opsize 32.
8 00000008 48CF o64 IRET ; Opsize 64.
9 0000000A CF IRET ; Opsize 32, default.
10
11 0000000B 66CB o16 RETF ; Opsize 16.
12 0000000D CB o32 RETF ; Opsize 32.
13 0000000E 48CB o64 RETF ; Opsize 64.
14 00000010 CB RETF ; Opsize 32, default.
15
16 00000011 66C3 o16 RETN ; Opsize 16.
17 00000013 C3 o32 RETN ; Opsize 32 should not be available, NASM error?
18 00000014 48C3 o64 RETN ; Opsize 64, REX.W ignored as RETN is promoted to 64 bits.
19 00000016 C3 RETN ; Opsize 64, default.
我没有编写调用门和任务门的经验,但我认为默认操作数大小应该与段大小相对应,在64位模式下为64。
程序员在没有进一步规范的情况下使用IRET、RETF、RETN时,对64位模式的汇编程序期望操作数是多少?。
发布于 2016-06-22 09:17:24
假设在asm源文件中写入ret
将汇编成一个单字节指令。
为什么有人会在64位代码中使用retf
,所以我对此没有意见。
仔细阅读你的桌子,我看到你在说NASM的操作数大小覆盖。它并不是特殊情况下的o32
/ o64
修饰符,用于RETN
这样的指令,从而导致像o64 retn
这样产生REX.W=1前缀(REX.W=1前缀,48 C3
)的虚假行为。
我认为我们应该将NASM的o32
前缀理解为“16位代码中的操作数大小前缀,否则就没有意义”,而不管它应用于什么指令,也绝不意味着REX.W=0 (因为对push
/pop
无论如何都不起作用)。
类似地,o64
实际上意味着应用REX.W=1,而不管它是在什么指令上。也就是说,它也不会在像push
或pop
这样的收入中忽略它,对吗?
ISA的设计使单字节ret
指令“工作”.在普通ret
上不需要REX前缀。正如 entry中记录的那样:
在64位模式下,该指令的默认操作大小是堆栈地址大小,即64位。这适用于接近返回,而不是远返回;far返回的默认操作大小为32位。
这与push
/pop
在长模式下默认为64位操作数大小类似。(与手册中的含义相反,REX.W=0
不能编码32位push/pop)。
AMD通常试图保持简单的解码。例如,movsxd r64, r/m32
需要一个REX前缀(否则它只是作为一个潜在的低效率的mov
运行),但是对于非常常见的指令,如push/pop和ret,它们通过这样的设计选择保存了代码大小。
https://stackoverflow.com/questions/37950640
复制相似问题