多年来我多次读过你应该做XOR ax,ax因为它更快......或者用C编程时使用counter ++或counter + = 1因为它们会INC或ADD ......或者在Netburst Pentium中4 INC比ADD 1慢,因此必须警告编译器你的目标是一个Netburst所以它会将所有var ++翻译成ADD 1 ......
我的问题是:为什么INC和ADD有不同的表现?为什么例如INC声称在Netburst上速度较慢而在其他处理器中比ADD快?
我一直在寻找如何将BSWAP用于64位寄存器的低32位子寄存器的答案.例如,0x0123456789abcdef在RAX寄存器中,我想0x01234567efcdab89用一条指令将其更改为(由于性能).
所以我尝试了以下内联函数:
#define BSWAP(T) { \
__asm__ __volatile__ ( \
"bswap %k0" \
: "=q" (T) \
: "q" (T)); \
}
Run Code Online (Sandbox Code Playgroud)
结果是0x00000000efcdab89.我不明白为什么编译器就像这样.有人知道有效的解决方案吗?
我理解在x86_64汇编中有例如(64位)rax寄存器,但它也可以作为32位寄存器,eax,16位,ax和8位来访问.在什么情况下我不会只使用完整的64位,以及为什么会有什么优势?
举个例子,通过这个简单的hello world程序:
section .data
msg: db "Hello World!", 0x0a, 0x00
len: equ $-msg
section .text
global start
start:
mov rax, 0x2000004 ; System call write = 4
mov rdi, 1 ; Write to standard out = 1
mov rsi, msg ; The address of hello_world string
mov rdx, len ; The size to write
syscall ; Invoke the kernel
mov rax, 0x2000001 ; System call number for exit = 1
mov rdi, 0 ; Exit success = 0
syscall …Run Code Online (Sandbox Code Playgroud) 我对Linux内核的一个头文件(arch/x86/include/asm/nops.h)中的注释感到有些困惑.它说明了这一点
<...>以下指令在64位模式下不是nops,对于64位模式,使用K8或P6 nops而不是
movl%esi,%esi
leal 0x00(%esi),%esi
<...>
我想作者暗示机器指令(分别是'89 F6'和'8D 76 00')而不是汇编指令.根据LEA英特尔软件开发人员手册第2A卷中的描述,后一条指令(lea 0x00(%rsi), %esi)与前者相同,mov %esi,%esi.
所以这简化了问题,是否mov %esi,%esi实际上是x86-64上的无操作.
mov不会改变旗帜.这种mov也不会改变记忆.似乎,如果它改变了一些东西%rip,那应该是通用寄存器.但我不知道它如何改变内容%rsi或其他内容.如果你操纵通用寄存器的下半部分,上半部分不应该改变,对吧?
我正在阅读英特尔指令手册并注意到有一条'NOP'指令在主CPU上没有任何作用,而且一条'FNOP'指令在FPU上什么都不做.为什么有两个单独的指令什么都不做?
我看到的唯一不同之处是它们会抛出不同的异常,因此您可能会从FNOP中查看异常,以检测是否有可用的FPU.但是没有像CPUID这样的其他机制来检测这个吗?有什么实际的理由有两个单独的NOP指令?
可能这甚至都不是微观但纳米优化,但主题让我感兴趣,我想知道在长模式下使用非本机寄存器大小时是否存在任何惩罚?
我从各种来源了解到,部分寄存器更新(比如ax代替eax)会导致eflags停顿并降低性能.但我不确定长模式.对于此处理器操作模式,哪个寄存器大小被视为原生?x86-64仍然是x86架构的扩展,因此我相信32位仍然是原生的.还是我错了?
例如,像
sub eax, r14d
Run Code Online (Sandbox Code Playgroud)
要么
sub rax, r14
Run Code Online (Sandbox Code Playgroud)
具有相同的尺寸,但在使用其中任何一种时可能会有任何处罚吗?在如下连续指令中混合寄存器大小时可能会有任何处罚吗?(假设高dword在所有情况下均为零)
sub ecx, eax
sub r14, rax
Run Code Online (Sandbox Code Playgroud) 我在集会上总是一个菜鸟,只是捅了一下看看发生了什么.无论如何,我写了一个非常简单的函数:
void multA(double *x,long size)
{
long i;
for(i=0; i<size; ++i){
x[i] = 2.4*x[i];
}
}
Run Code Online (Sandbox Code Playgroud)
我编译它:
gcc -S -m64 -O2 fun.c
Run Code Online (Sandbox Code Playgroud)
我得到了这个:
.file "fun.c"
.text
.p2align 4,,15
.globl multA
.type multA, @function
multA:
.LFB34:
.cfi_startproc
testq %rsi, %rsi
jle .L1
movsd .LC0(%rip), %xmm1
xorl %eax, %eax
.p2align 4,,10
.p2align 3
.L3:
movsd (%rdi,%rax,8), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, (%rdi,%rax,8)
addq $1, %rax
cmpq %rsi, %rax
jne .L3
.L1:
rep
ret
.cfi_endproc
.LFE34:
.size multA, .-multA
.section .rodata.cst8,"aM",@progbits,8
.align …Run Code Online (Sandbox Code Playgroud) 有时gcc使用32位寄存器,当我希望它使用64位寄存器时.例如以下C代码:
unsigned long long
div(unsigned long long a, unsigned long long b){
return a/b;
}
Run Code Online (Sandbox Code Playgroud)
使用-O2选项编译(省略一些样板文件):
div:
movq %rdi, %rax
xorl %edx, %edx
divq %rsi
ret
Run Code Online (Sandbox Code Playgroud)
对于无符号除法,寄存器%rdx需要0.这可以通过xorq %rdx, %rdx但xorl %edx, %edx似乎具有相同的效果来实现.
至少在我的机器上没有性能提升(即加速)进行xorl了xorq.
我实际上不只是一个问题:
xorl并且不使用xorw?xorl比这更快的机器xorq?我的探查器已将以下功能分析标识为热点.
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)
我想哄骗编译器生成这条指令,但我想我首先需要理解为什么生成这条指令.为什么扩展/零扩展,考虑到我使用相同的数据类型?
我不是最有经验的汇编程序员,我遇到了“cqo”、“cdq”和“cwd”指令,它们都是有效的 x86_64 汇编。
我想知道在操作较小的值时使用 cdq 或 cwd 是否有任何优势。性能上有什么区别吗?
编辑:最初在计算一位数的绝对值时开始研究这一点。
例如,如果我们在 al 中有 -9 值:
cwd
xor al,dl
sub al,dl
Run Code Online (Sandbox Code Playgroud)
与将其作为 32 位值并计算
cdq
xor eax,edx
sub eax,edx
Run Code Online (Sandbox Code Playgroud)
或者如果我们有 -9 的 64 位值
cqo
xor rax,rdx
sub rax,rdx
Run Code Online (Sandbox Code Playgroud)
如果原始值是 64 位并且由一个值 -9 到 9 组成,那么实际上它们看起来都是一样的。
assembly ×9
x86-64 ×5
gcc ×3
optimization ×3
x86 ×3
64-bit ×2
c ×1
c++ ×1
endianness ×1
hardware ×1
linux-kernel ×1
nasm ×1
profiling ×1
x87 ×1