MOV moffs32在64位模式下地址的符号扩展还是零扩展? [英] Sign or Zero Extension of address in 64bit mode for MOV moffs32?

查看:257
本文介绍了MOV moffs32在64位模式下地址的符号扩展还是零扩展?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们以 64位模式将指令 MOV EAX,[0xFFFFFFFF] 编码为 67A1FFFFFFFF (有效的地址大小由67个前缀默认为64到32位).

Let's have an instruction MOV EAX,[0xFFFFFFFF] encoded in 64bit mode as 67A1FFFFFFFF (effective address-size is toggled by 67 prefix from default 64 to 32 bits).

Intel的说明参考手册(从2015年12月起,文档订单号:325383-057US)在第Vol. 2A 2-11说:

Intel's instruction reference manual (doc Order Number: 325383-057US from December 2015) on page Vol. 2A 2-11 says:

2.2.1.3排量
在64位模式下寻址使用现有的32位ModR/M和SIB编码. ModR/M和SIB大小不变.他们 保留8位或32位,并符号扩展为64位.

2.2.1.3 Displacement
Addressing in 64-bit mode uses existing 32-bit ModR/M and SIB encodings. The ModR/M and SIB sizes do not change. They remain 8 bits or 32 bits and are sign-extended to 64 bits.

这表明应该对32位位移进行符号扩展,但是我不确定这是否也涉及特殊的moffs寻址模式. 英特尔在下一页上说:

This suggests that 32bit displacement should be sign-extended but I am not sure if this concerns special moffs addressing mode as well. On the next page Intel says:

2.2.1.6 RIP相对寻址

2.2.1.6 RIP-Relative Addressing

RIP相对寻址是通过64位模式而不是64位地址大小启用的.使用 address-size前缀不会禁用RIP相对寻址.这 地址大小前缀的作用是截断和零扩展 计算出的有效地址为32位.

RIP-relative addressing is enabled by 64-bit mode, not by a 64-bit address-size. The use of the address-size prefix does not disable RIP-relative addressing. The effect of the address-size prefix is to truncate and zero-extend the computed effective address to 32 bits.

这表明在相对寻址模式下,disp32被符号扩展为64位,添加到RIP,然后被截断并零扩展. 但是,我不确定同一规则是否适用于绝对寻址模式,MOV moffs操作就是这种情况.

This suggests that in relative addressing mode the disp32 is sign-extended to 64 bit, added to RIP and then truncated and zero-extended. Hovever I am not sure if the same rule applies to absolute addressing mode, which is the case of MOV moffs operations.

将从AAX加载什么地址,A)FFFFFFFFFFFFFFFF或B)00000000FFFFFFFF?

推荐答案

67 A1 FFFFFFFF没有使用disp32寻址模式,因此该文档的Mod/RM部分不适用.

67 A1 FFFFFFFF isn't using a disp32 addressing mode, so the Mod/RM section of the documentation doesn't apply.

英特尔x86手册第1卷说:

Intel's x86 manual vol.1 says:

在IA-32e模式下,所有16位和 32位地址计算都进行零扩展,以形成64位地址.首先,地址计算将被截断为当前模式(64位模式或兼容模式)的有效地址大小,并被任何地址大小前缀覆盖.然后将结果零扩展到整个64位地址宽度. [...]在64位模式下生成的32位地址只能访问64位模式有效地址的低4 GB.

All 16-bit and 32-bit address calculations are zero-extended in IA-32e mode to form 64-bit addresses. Address calculations are first truncated to the effective address size of the current mode (64-bit mode or compatibility mode), as overridden by any address-size prefix. The result is then zero-extended to the full 64-bit address width. [...] A 32-bit address generated in 64-bit mode can access only the low 4 GBytes of the 64-bit mode effective addresses.

这也适用于mov 的特殊 moffs绝对寻址形式关于常规的ModR/M寻址模式,例如mov eax, [edi]而不是mov eax, [rdi].

This applies to the special moffs absolute addressing forms of mov as well as to regular ModR/M addressing modes like mov eax, [edi] instead of mov eax, [rdi].

请注意,moffs8/16/32/64命名显示的是操作数大小,而不是地址大小(例如mov al, moffs8).对于64位模式下的32位地址大小moffs没有不同的术语.

Note that the moffs8/16/32/64 naming shows the operand-size, not the address size (e.g. mov al, moffs8). There isn't a different term for a 32-bit address size moffs in 64-bit mode.

地址大小前缀将A1操作码从64位立即地址更改为32位,即,它更改了指令 rest 的长度(与ModR/M不同)寻址模式(始终为disp0/8/32)(64位模式).根据我的测试,实际上导致LCP在Skylake上停止运行 a32 mov eax, [abs buf](NASM选择在这种情况下使用moffs编码,因为指定了a32替代,它比ModR/M + disp32短)

The address-size prefix changes the A1 opcode from a 64-bit immediate address to a 32-bit, i.e. it changes the length of the rest of the instruction (unlike ModR/M addressing mode in 64-bit mode, which are always disp0/8/32). This actually causes LCP stalls on Skylake, according to my testing, for a32 mov eax, [abs buf] (NASM chooses to use the moffs encoding for that case, because with the a32 override specified, it's shorter than ModR/M + disp32)

无论如何,这意味着将其反汇编为mov eax, [0xFFFFFFFF]是错误的(至少在NASM语法中如此),因为它将重新组合成一条执行不同操作的指令.

Anyway, this means that disassembling it as mov eax, [0xFFFFFFFF] is wrong (at least in NASM syntax), because that assembles back into an instruction that does something different.

正确的YASM/ NASM语法将重新组合机器代码是

The correct YASM/NASM syntax that will assemble back to that machine code is

NASM也接受mov eax, [a32 0xFFFFFFFF],但YASM不接受.

NASM also accepts mov eax, [a32 0xFFFFFFFF], but YASM doesn't.

GNU as还提供了一种表达它的方式(不使用.byte):
addr32 mov 0xffffffff,%eax

GNU as also provides a way to express it (without using .byte):
addr32 mov 0xffffffff,%eax

movl    0x7FFFFFFF, %eax  # 8B mod/rm disp32
movl    0xFFFFFFFF, %eax  # A1 64bit-moffs32: Older GAS versions may have required the movabs mnemonic to force a moffs encoding

movabs  0x7FFFFF, %eax    #     A1 64b-moffs32: movabs forces MOFFS
movabs  0xFFFFFFFF, %rax  # REX A1 64b-moffs64
movabs  0xFFFF, %ax       #  66 A1 64b-moffs64: operand-size prefix

.byte 0x67, 0xa1, 0xff, 0xff, 0xff, 0xff  # disassembles to  addr32 mov 0xffffffff,%eax
                                          # and that syntax works as assembler input:
addr32 mov 0xffffffff,%eax    # 67 A1 FF FF FF FF:  32b-moffs32


对于NASM/YASM,无法以除拒绝AL/AX/EAX/RAX以外的其他寄存器汇编的方式强制强制执行32位MOFFS编码. a32 mov [0xfffffff], cl组装为67 88 0c 25 ff ff ff 0f addr32 mov BYTE PTR ds:0xfffffff,cl(mov r/m8, r8的ModR/M + disp32编码).


With NASM/YASM, there's no way to force a 32-bit MOFFS encoding in a way that refuses assemble with a register other than AL/AX/EAX/RAX. a32 mov [0xfffffff], cl assembles to 67 88 0c 25 ff ff ff 0f addr32 mov BYTE PTR ds:0xfffffff,cl (a ModR/M + disp32 encoding of mov r/m8, r8).

您可以编写mov eax, [qword 0xffff...]以获得moffs64编码,但是无法要求32位moffs编码.

You can write mov eax, [qword 0xffff...] to get the moffs64 encoding, but there's no way to require a 32-bit moffs encoding.

Agner Fog的objconv反汇编程序弄错了(从上面的块中反汇编GNU as生成的机器代码). objconv似乎采用符号扩展名. (它将机器代码放在注释中为prefixes: opcode, operands)

Agner Fog's objconv disassembler gets it wrong (disassembling the machine code produced with GNU as from the block above). objconv appears to assume sign-extension. (It puts the machine code in comments as prefixes: opcode, operands)

; Note: Absolute memory address without relocation
    mov     eax, dword [abs qword 7FFFFFH]          ; 0033 _ A1, 00000000007FFFFF
 ...
; Note: Absolute memory address without relocation
    mov     eax, dword [0FFFFFFFFFFFFFFFFH]         ; 0056 _ 67: A1, FFFFFFFF

ndisasm -b64也会错误地反汇编,导致代码甚至无法以相同的方式工作:

ndisasm -b64 also disassembles incorrectly, to code that doesn't even work the same way:

00000073  A1FFFF7F00000000  mov eax,[qword 0x7fffff]
         -00
...
00000090  67A1FFFFFFFF      mov eax,[0xffffffff]

如果不使用a32关键字,我会期望像mov eax, [qword 0xffffffff]这样的反汇编.这将汇编成一个64位的moffs,该moffs引用与原始地址相同的地址,但更长.当向ndisasm添加AMD64支持时,这可能被忽略了,而ndisasm在AMD64之前已经存在.

I would have expected a disassembly like mov eax, [qword 0xffffffff], if it's not going to use the a32 keyword. That would assemble to a 64-bit moffs that references the same address as the original, but is longer. Probably this was overlooked when adding AMD64 support to ndisasm, which already existed before AMD64.

这篇关于MOV moffs32在64位模式下地址的符号扩展还是零扩展?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆