2016-06-21 112 views
1

我的问题涉及RET64位模式和它们的操作数大小,它指定有多少信息从堆栈弹出到RIP以及RSP增加了多少字节的指令。RET默认的操作数大小是多少?

我注意到一些汇编程序留下了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位模式的汇编程序得到什么操作数大小?

+0

谁知道?我怀疑有人做过调查。你真正的问题是什么? –

+0

@RossRidge我的程序是否应该将RETF转换为CB或48CB? – vitsoft

+0

你的程序是汇编程序?我认为它不会太重要,实际上没有任何理由在64位代码中编写远程返回。此外,RETF不是正式的指令,所以如果你记录它,你可以做任何你想做的事情。 –

回答

1

假设编写一个asm源文件中的ret将组合成一个单字节指令。

IDK为什么有人会在64位代码中使用retf,所以我对此没有任何意见。


在仔细阅读您的表格后,我会看到您对NASM操作数大小覆盖的看法。它不会特别针对RETN之类的说明修改器,导致产生伪造行为,如o64 retn产生REX.W = 1前缀(48 C3)。

我认为我们应该将NASM的o32前缀理解为“16位代码中的操作数大小前缀,否则不管”,而不管它应用于哪个指令,并且永远不会暗示REX.W = 0(因为它不无论如何工作push/pop)。

而且类似地,o64的确意味着应用REX.W = 1,而不管它使用什么指令。即它不会在像pushpop之类的insn上省略它,是吗?



的ISA被设计成单字节指令ret “工作”。您在正常的ret上不需要REX前缀。如the instruction set manual's ret entry中所述:

在64位模式下,该指令的默认操作大小是堆栈地址大小,即64位。这适用于接近收益,而不是很远的收益; far return的默认操作大小是32位。

这与在长模式下push/pop默认为64位操作数大小类似。 (并且,与手册中的暗示相反,REX.W=0无法编码32位推/压)。

AMD通常试图保持简单的解码。例如movsxd r64, r/m32需要一个REX前缀(否则它只是作为一个潜在效率较低的mov运行),但对于像push/pop和ret这样的常见指令,他们使用这样的设计选择保存了代码大小。

+2

a16 retf和a32 retf的场景 - 您试图返回到16位或32位代码。 a64 retf,这很困难,但假设你刚刚用LGDT重载了GDT并且表中的代码段描述符不一样,那么你需要强制CS重新加载。在这种情况下,a64 retf是有道理的。 –

+1

@MichaelPetch Tnx,需要'o64 IRET(48CF)'的另一个例子可能是从加载的代码触发的中断处理程序返回4GB以上。 BTW不应该阅读'o64,o32,o16'而不是'a64,a32,a16'?正如POP中所记录的,AFAIK a64(地址大小前缀67)在64位模式下基于RSP的指令上没有意义。这里堆栈指针大小固定为64位。 – vitsoft

+0

是的@vitsoft应该都不是'a'。是我昨晚做出的最后一条评论,甚至没有注意到错字。 –