当前位置: 首页 > 知识库问答 >
问题:

对于MOV MOFFS32在64位模式下地址的符号或零扩展?

许子平
2023-03-14

2.2.1.3 64位模式下的位移
寻址使用现有的32位MODR/M和SIB编码。MODR/M和SIB大小不变。它们保持8位或32位,并符号扩展到64位。

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

2.2.1.6 RIP相对寻址

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

EAX将从哪个地址加载,A)FFFFFFFFFFFFFFFFFFFFF或B)00000000FFFFFFFF?

共有1个答案

拓拔松
2023-03-14

67 A1 ffffffffff不使用disp32寻址模式,因此文档中的mod/rm部分不适用。

英特尔的x86手册第一卷说:

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

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

正确的YASM/NASM语法将汇编回该机器代码为

NASM也接受MOV eax,[a320xffffffff],但YASM不接受。

GNUAS还提供了一种表达它的方法(不使用.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

Agner Fog的objconv反汇编程序错误(将用GNU生成的机器代码从上面的块中反汇编为)。objconv似乎假定为符号扩展。(它将机器代码作为前缀放在注释中: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也会不正确地反汇编代码,这些代码甚至不能以相同的方式工作:

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

如果它不使用A32关键字,我会预期会出现类似MOV eax、[qword0xffffffff]的反汇编。它将组装成一个64位moffs,该MOFF引用与原始地址相同的地址,但更长。在将AMD64支持添加到ndisasm时,可能忽略了这一点,而ndisasm在AMD64之前就已经存在了。

 类似资料:
  • 我阅读了关于64位模式下地址计算的英特尔手册。假设我们有64位模式,默认地址大小是64位。另外,假设所讨论的指令前面有地址大小覆盖前缀,因此地址大小变成32位。 现在,假设指令用寄存器号0(RAX/EAX/AX...)指定的地址编码内存操作数。 现在我不完全理解的是,CPU是只查看eax值并在内部扩展它以形成“本地”64位地址,还是查看整个rax值并将其截断到有效的32位范围(例如,rax包含类似

  • 我使用SIMD创建了一个64位*64位到128位的函数。目前我已经使用SSE2(实际上是SSE4.1)实现了它。这意味着它同时生产两个64b*64b到128b的产品。同样的想法可以扩展到AVX2或AVX512,同时提供四个或八个64b*64到128b的产品。我的算法基于http://www.hackersdelight.org/hdcodetxt/muldws.c.txt 该算法执行一次无符号乘法

  • 摘要:我在查看程序集代码以指导我的优化,并且在将int32添加到指针时看到了大量的符号或零扩展。 起初,我认为我的编译器在添加32bit到64bit的整数时遇到了挑战,但我已经在Intel ICC 11、ICC 14和GCC 5.3中证实了这种行为。

  • 3.8 32位地址的寻址方式 在32位微机系统中,除了支持前面的七种寻址方式外,又提供了一种更灵活、方便,但也更复杂的内存寻址方式,从而使内存地址的寻址范围得到了进一步扩大。 在用16位寄存器来访问存储单元时,只能使用基地址寄存器(BX和BP)和变址寄存器(SI和DI)来作为地址偏移量的一部分,但在用32位寄存器寻址时,不存在上述限制,所有32位寄存器(EAX、EBX、ECX、EDX、ESI、ED

  • 这是对前一篇文章中的一些评论的跟进: 递归斐波那契汇编 以下代码片段计算Fibonacci,第一个示例使用循环,第二个示例使用计算跳转(索引分支)到展开的循环。这是在采用英特尔3770K 3.5ghz处理器的Windows 7 Pro 64位模式下使用Visual Studio 2015 Desktop Express进行测试的。使用一个测试fib(0)到fib(93)的单循环,我得到的循环版本的

  • 我正在通过Kochan的C语言编程学习C语言,其中一个练习是: 使函数搜索数字0xE1F4(=1110 0001 1111 0100二进制)是否出现三位模式0x5(=101二进制)。该函数返回,以指示在中找到了以11位开头的模式。 确保函数没有对的大小做任何假设。 这是我实现函数的方式: 但是,我的程序的输出结果是14,而不是11。我用铅笔和纸跟着程序走,不明白哪里出了问题...帮忙?