正如广泛宣传的那样,现代x86_64处理器有64位寄存器,可以以32位寄存器,16位寄存器甚至8位寄存器的后向兼容方式使用,例如: 0x1122334455667788 ================ rax (64 bits) ======== eax (32 bits) ==== ax (16 bits) == ah (8 bits) == al (8 bits) 这样的scheme可以从字面上理解,也就是说,人们总是只能使用指定的名称来访问寄存器的一部分,以便读写,这是非常合乎逻辑的。 实际上,对于高达32位的所有内容都是如此: mov eax, 0x11112222 ; eax = 0x11112222 mov ax, 0x3333 ; eax = 0x11113333 (works, only low 16 bits changed) mov al, 0x44 ; eax = 0x11113344 (works, only low 8 […]
今天我了解了x64程序集(资料来源: http : //x86asm.net/articles/x86-64-tour-of-intel-manuals/ ) 也许最令人惊讶的事实是,诸如MOV EAX,EBX之类的指令自动将RAX寄存器的高32位清零。 英特尔文档(3.4.1.1通用基本体系结构中的64位模式的通用寄存器)在同一来源中引用告诉我们: 64位操作数在目标通用寄存器中生成一个64位结果。 32位操作数产生一个32位结果,在目标通用寄存器中零扩展为一个64位结果。 8位和16位操作数生成8位或16位结果。 目标通用寄存器的高56位或48位(分别)不会被操作修改。 如果8位或16位操作的结果是用于64位地址计算的,则明确地将寄存器扩展为完整的64位。 在x86-32汇编中,16位指令如 mov ax, bx 不要performance出这种eax的上位字“零”的“奇怪”的行为。 因此:这种行为被引入的原因是什么? 乍一看这似乎不合逻辑(但原因可能是我习惯了x86-32汇编的怪癖)。