相关疑难解决方法(0)

为什么32位寄存器上的x86-64指令归零整个64位寄存器的上半部分?

x86-64 Tour of Intel Manuals中,我读到了

也许最令人惊讶的事实是,诸如MOV EAX, EBX自动将指令的高32位归零的指令RAX.

同一来源引用的英特尔文档(3.4.1.1 64位手动基本架构中的通用寄存器)告诉我们:

  • 64位操作数在目标通用寄存器中生成64位结果.
  • 32位操作数生成32位结果,在目标通用寄存器中零扩展为64位结果.
  • 8位和16位操作数生成8位或16位结果.目标通用寄存器的高56位或48位(分别)不会被操作修改.如果8位或16位操作的结果用于64位地址计算,则将寄存器显式符号扩展为完整的64位.

在x86-32和x86-64汇编中,16位指令如

mov ax, bx
Run Code Online (Sandbox Code Playgroud)

不要表现出这种"奇怪"的行为,即eax的上层词被归零.

因此:引入这种行为的原因是什么?乍一看似乎不合逻辑(但原因可能是我习惯了x86-32汇编的怪癖).

x86 assembly x86-64 cpu-registers zero-extension

97
推荐指数
3
解决办法
2万
查看次数

Clang 和 GCC 对 movzx 的奇怪使用

我知道这movzx可以用于打破依赖关系,但我偶然发现了movzxClang 和 GCC 的一些用途,我真的看不出它们有什么用处。这是我在 Godbolt 编译器浏览器上尝试的一个简单示例:

#include <stdint.h>

int add2bytes(uint8_t* a, uint8_t* b) {
    return uint8_t(*a + *b);
}
Run Code Online (Sandbox Code Playgroud)

与海湾合作委员会 12 -O3

add2bytes(unsigned char*, unsigned char*):
        movzx   eax, BYTE PTR [rsi]
        add     al, BYTE PTR [rdi]
        movzx   eax, al
        ret
Run Code Online (Sandbox Code Playgroud)

如果我理解正确的话,这里的第一个movzx打破了对先前eax值的依赖,但第二个是什么movzx做什么?我认为它不会破坏任何依赖关系,也不应该影响结果。

使用 clang 14 -O3,情况更加奇怪:

add2bytes(unsigned char*, unsigned char*):                       # @add2bytes(unsigned char*, unsigned char*)
        mov     al, byte ptr [rsi]
        add     al, byte ptr [rdi]
        movzx   eax, al
        ret …
Run Code Online (Sandbox Code Playgroud)

c++ x86 assembly gcc clang

53
推荐指数
2
解决办法
3028
查看次数

为什么我不能直接将字节移动到64位寄存器?

为什么我不能直接将一个字节从内存移动到Intel x86-64汇编中的64位寄存器?

例如,这段代码:

extern printf

global main

segment .text

main:
    enter   2, 0

    mov     byte [rbp - 1], 'A'
    mov     byte [rbp - 2], 'B'

    mov     r12, [rbp - 1]
    mov     r13, [rbp - 2]             

    xor     rax, rax           
    mov     rdi, Format                                                                                             
    mov     rsi, r12                                                                                                
    mov     rdx, r13                                                                                                
    call    printf                                                                                                  

    leave                                                                                                           
    ret                                                                                                             

segment .data                                                                                                       
Format:     db "%d %d", 10, 0
Run Code Online (Sandbox Code Playgroud)

打印:

65 16706
Run Code Online (Sandbox Code Playgroud)

我需要将移动字节更改为寄存器r12和r13,以使代码正常工作:

xor     rax, rax
mov     al, byte [rbp - 1]
mov     r12, rax
xor     rax, rax
mov     al, …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64

4
推荐指数
1
解决办法
4335
查看次数

为什么在Intel微处理器的64位模式下不支持MOV AH,1?

在Barry B. Brey的"THE INTEL MICROPROCESSORS"一书中写道

MOV AH, 1
Run Code Online (Sandbox Code Playgroud)

在64位模式下不允许,但在32位或16位模式下允许.如果MOV AL, 1可以在64位模式下允许,有什么问题MOV AH, 1

x86 assembly x86-64

2
推荐指数
1
解决办法
568
查看次数

标签 统计

assembly ×4

x86 ×3

x86-64 ×3

c++ ×1

clang ×1

cpu-registers ×1

gcc ×1

zero-extension ×1