在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汇编的怪癖).
我的探查器已将以下功能分析标识为热点.
typedef unsigned short ushort;
bool isInteriorTo( const std::vector<ushort>& point , const ushort* coord , const ushort dim )
{
for( unsigned i = 0; i < dim; ++i )
{
if( point[i + 1] >= coord[i] ) return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
特别是一个汇编指令MOVZX(Move with Zero-Extend)负责运行时的大部分.if语句被编译成
mov rcx, QWORD PTR [rdi]
lea r8d, [rax+1]
add rsi, 2
movzx r9d, WORD PTR [rsi-2]
mov rax, r8
cmp WORD PTR [rcx+r8*2], r9w
jae .L5
Run Code Online (Sandbox Code Playgroud)
我想哄骗编译器生成这条指令,但我想我首先需要理解为什么生成这条指令.为什么扩展/零扩展,考虑到我使用相同的数据类型?
在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?