相关疑难解决方法(0)

INC指令与ADD 1:重要吗?

来自Ira Baxter回答,为什么INC和DEC指令不会影响进位标志(CF)?

大多数情况下,我远离INCDEC现在,因为他们做的部分条件代码更新,这样就可以在管道中引起滑稽的摊位,和ADD/ SUB没有.因此,无关紧要(大多数地方),我使用ADD/ SUB避免失速.我使用INC/ DEC仅在保持代码较小的情况下,例如,适合高速缓存行,其中一个或两个指令的大小产生足够的差异.这可能是毫无意义的纳米[字面意思!] - 优化,但我在编码习惯上相当老派.

我想问一下为什么它会导致管道中的停顿,而添加不会?毕竟,无论是ADDINC更新标志寄存器.唯一的区别是INC不更新CF.但为什么重要呢?

performance x86 assembly increment micro-optimization

26
推荐指数
2
解决办法
4234
查看次数

将CPU寄存器中的所有位有效地设置为1

要清除所有位,您经常会看到一个独占或在XOR eax, eax.反过来也有这样的伎俩吗?

我能想到的是用额外的指令反转零.

assembly arm x86-64 mips

17
推荐指数
1
解决办法
2154
查看次数

为什么GCC不使用部分寄存器?

write(1,"hi",3)在linux上反汇编,gcc -s -nostdlib -nostartfiles -O3结果如下:

ba03000000     mov edx, 3 ; thanks for the correction jester!
bf01000000     mov edi, 1
31c0           xor eax, eax
e9d8ffffff     jmp loc.imp.write
Run Code Online (Sandbox Code Playgroud)

我不是到编译器的开发,但由于移动到这些寄存器的每一个值是恒定的和已知的编译时间,我很好奇,为什么不GCC使用dl,dilal来代替.也许有人会说,此功能不会让任何性能上的差异,但有一个在之间的可执行文件的大小有很大的区别mov $1, %rax => b801000000,并mov $1, %al => b001当我们谈论数千寄存器的程序访问.如果软件的优雅部分不仅体积小,它确实会对性能产生影响.

有人可以解释为什么"海湾合作委员会决定"它无所谓?

x86 assembly gcc x86-64

13
推荐指数
2
解决办法
1655
查看次数

每个asm指令的大小是多少?

每个asm指令的大小是多少?每条指令占用多少字节?8个字节?四个用于操作码,四个用于参数?例如,当你在mov中有一个操作码和2个参数时会发生什么?它们在内存中是否具有固定大小或它们是否有所不同?EIP是否与此有关,它的值总是加1,完全独立于它所经过的指令类型?

我问这个当我正在阅读http://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames时,我偶然发现,看起来调用指令相当于push和jmp指令.

call MYFUNCTION
mov my_var, eax
Run Code Online (Sandbox Code Playgroud)

和...一样

push [eip + 2];
jmp MYFUNCTION;
mov my_var, eax
Run Code Online (Sandbox Code Playgroud)

当我们在堆栈上推动[eip + 2]时,我们指向的值是什么?到"jmp MYFUNCTION"旁边的行,移动my_var eax,对吧?

ps:MSVC++在第一行标记错误,因为它表示eip未定义.它适用于eax,esp,ebp等.我做错了什么?

x86 assembly

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

使用xmm寄存器而不是ymm时,vxorps在AMD Jaguar/Bulldozer/Zen上的归零速度是否更快?

AMD CPU通过解码为两个128b操作来处理256b AVX指令.例如,vaddps ymm0, ymm1,ymm1在AMD上,Steamroller解码为2个宏操作,吞吐量的一半vaddps xmm0, xmm1,xmm1.

XOR归零是一种特殊情况(没有输入依赖性,并且在Jaguar上至少避免消耗物理寄存器文件条目,并且使得来自该寄存器的movdqa在发出/重命名时被消除,就像Bulldozer一直在做非零的REG)中. 但它是否足够vxorps ymm0,ymm0,ymm0早被检测到仍然只能解码为1个具有相同性能的宏操作 vxorps xmm0,xmm0,xmm0?(不像vxorps ymm3, ymm2,ymm1)

或者,在已经解码为两个uop之后,独立检测是否会发生?此外,AMD CPU上的向量xor-zeroing是否仍然使用执行端口?在Intel-CPU上,Nehalem需要一个端口,但Sandybridge系列在发布/重命名阶段处理它.

Agner Fog的指令表没有列出这个特例,他的微指南没有提到uop的数量.


这可能意味着vxorps xmm0,xmm0,xmm0更好的实施方式_mm256_setzero_ps().

对于AVX512 _mm512_setzero_ps(),如果可能的话,也只使用VEX编码的归零惯用语而不是EVEX来保存字节.(即对于zmm0-15. vxorps xmm31,xmm31,xmm31仍然需要EVEX).gcc/clang目前使用他们想要的任何寄存器宽度的xor-zeroing习语,而不是总是使用AVX-128.

报告为clang bug 32862和gcc bug 80636.MSVC已经使用了xmm.尚未向ICC报告,ICC也使用zmm regs进行AVX512归零.(虽然英特尔可能不会改变,因为目前任何英特尔CPU都没有任何好处,只有AMD.如果他们发布的低功耗CPU将矢量分成两半,他们可能.他们目前的低功耗设计(Silvermont)没有t支持AVX,只支持SSE4.)


我知道使用AVX-128指令清零256b寄存器唯一可能的缺点是它不会触发Intel CPU上256b执行单元的预热.可能会破坏试图加热它们的C或C++黑客攻击.

(在第一个256b指令之后的第一个~56k周期内,256b向量指令较慢.请参阅Agner Fog微格式pdf中的Skylake部分).如果调用noinline返回的函数_mm256_setzero_ps不是预热执行单元的可靠方法,那可能没问题.(一个仍然可以在没有AVX2的情况下工作,并且避免任何负载(可以缓存未命中)是__m128 onebits = _mm_castsi128_ps(_mm_set1_epi8(0xff));
return _mm256_insertf128_ps(_mm256_castps128_ps256(onebits), onebits)应该编译为pcmpeqd xmm0,xmm0,xmm0/ vinsertf128 ymm0,xmm0,1.对于你曾经呼叫一次预热(或保持)执行单元的事情,这仍然是非常微不足道的.关键循环.如果你想要内联的东西,你可能需要inline-asm.)


我没有AMD硬件所以我无法测试这个.

如果有人拥有AMD硬件但不知道如何测试,请使用perf计数器来计算周期(最好是m-ops或uops或AMD称之为的任何内容).

这是我用来测试短序列的NASM/YASM源:

section .text
global _start …
Run Code Online (Sandbox Code Playgroud)

x86 assembly avx micro-optimization amd-processor

11
推荐指数
1
解决办法
691
查看次数

为什么XCHG reg,注册了关于现代英特尔架构的3微操作指令?

我正在对代码的性能关键部分进行微优化,并且遇到了指令序列(在AT&T语法中):

add %rax, %rbx
mov %rdx, %rax
mov %rbx, %rdx
Run Code Online (Sandbox Code Playgroud)

我以为我终于有一个用例xchg可以让我刮一个指令并写:

add  %rbx, %rax
xchg %rax, %rdx
Run Code Online (Sandbox Code Playgroud)

然而,根据Agner Fog的指令表,我发现这xchg是一个3微操作指令,在Sandy Bridge,Ivy Bridge,Broadwell,Haswell甚至Skylake上有2个周期延迟.3个完整的微操作和2个周期的延迟!3微操作抛出了我的4-1-1-1的节奏和2周期延迟使得它比在最好的情况下原来的,因为在原来的并行执行可能最后2条指令差.

现在......我得知CPU可能会将指令分解为相当于以下内容的微操作:

mov %rax, %tmp
mov %rdx, %rax
mov %tmp, %rdx 
Run Code Online (Sandbox Code Playgroud)

哪里tmp是匿名内部寄存器,我想最后两个微操作可以并行运行,因此延迟是2个周期.

鉴于寄存器重命名发生在这些微架构上,但对我来说这是以这种方式完成的.为什么寄存器重命名器不会交换标签?理论上,这将只有1个周期(可能是0?)的延迟,并且可以表示为单个微操作,因此它会便宜得多.

performance x86 assembly intel

11
推荐指数
1
解决办法
1907
查看次数

在64位系统上组装32位二进制文​​件(GNU工具链)

我编写了可以编译的汇编代码:

as power.s -o power.o
Run Code Online (Sandbox Code Playgroud)

当我链接power.o目标文件时出现问题:

ld power.o -o power
Run Code Online (Sandbox Code Playgroud)

为了在64位操作系统(Ubuntu 14.04)上运行,我.code32power.s文件的开头添加了,但是我仍然得到错误:

分段故障(核心转储)

power.s:

.code32
.section .data
.section .text
.global _start
_start:
pushl $3
pushl $2 
call power 
addl $8, %esp
pushl %eax 

pushl $2
pushl $5
call power
addl $8, %esp

popl %ebx
addl %eax, %ebx

movl $1, %eax
int $0x80



.type power, @function
power:
pushl %ebp  
movl %esp, %ebp 
subl $4, %esp 
movl 8(%ebp), %ebx 
movl 12(%ebp), %ecx 
movl %ebx, -4(%ebp) 

power_loop_start:
cmpl …
Run Code Online (Sandbox Code Playgroud)

linux x86 assembly build att

9
推荐指数
2
解决办法
3853
查看次数

考虑到指令具有不同的长度,CPU 如何知道它应该为下一条指令读取多少字节?

所以我正在阅读一篇论文,其中他们说静态反汇编二进制代码是不可判定的,因为一系列字节可以用图片(其 x86 )所示的尽可能多的方式表示

拆卸

所以我的问题是:

  1. 那么CPU如何执行呢?例如在图中,当我们到达 C3 之后,它如何知道下一条指令应该读取多少字节?

  2. CPU如何知道在执行一条指令后PC应该增加多少?它是否以某种方式存储当前指令的大小并在它想要增加 PC 时添加它?

  3. 如果 CPU 能够以某种方式知道它应该为下一条指令读取多少字节或者基本上如何解释下一条指令,为什么我们不能静态地做到这一点?

cpu x86 assembly

5
推荐指数
1
解决办法
870
查看次数

指令解码器如何区分前缀和主要操作码之间的区别?

我正在尝试围绕 x86 指令编码格式。我阅读的所有资料仍然使这个主题变得混乱。我开始有点理解它,但我无法理解的一件事是 CPU 指令解码器如何区分操作码前缀和操作码。

我知道指令的整个格式基本上取决于操作码(当然在操作码中定义了额外的位字段)。有时指令没有前缀,操作码是第一个字节。解码器怎么知道?

我假设指令解码器能够分辨出差异,因为操作码字节和前缀字节不会共享相同的二进制值。因此解码器可以判断字节中唯一的二进制数是指令还是前缀。例如(在本例中,我们将坚持使用单字节操作码)REXLOCK前缀不会与架构指令集中的任何操作码共享相同的字节值。

x86 assembly cpu-architecture machine-code instruction-encoding

5
推荐指数
1
解决办法
104
查看次数

为什么我的汇编器不使用 ADD EAX,1 手册文档中的 05 操作码 (add eax,imm32) 简写形式,但对 04 ADD AL, 1 却使用它?

我正在编写一个 x86-64 汇编程序。我正在浏览 Intel x86 手册第 2 卷,试图了解如何从程序集中生成正确的指令。我主要了解它是如何工作的,但一直在组装和拆卸说明以检查我是否正确。

在 ADD 参考表(第 2A 卷,3.31)中:

opcode        | Instruction  
04 ib         | ADD AL, imm8  
05 iw         | ADD AX, imm16  
05 id         | ADD EAX, imm32  
REX.W + 05 id | ADD RAX, imm32  
Run Code Online (Sandbox Code Playgroud)

集合:

;add.s   
add al, 1
add ax, 1
add eax, 1
add rax, 1
Run Code Online (Sandbox Code Playgroud)

拆卸:

.text:
   0:   04 01           add al, 1
   2:   66 83 c0 01     add ax, 1
   6:   83 c0 01        add eax, 1
   9: …
Run Code Online (Sandbox Code Playgroud)

x86 assembly machine-code opcode instruction-encoding

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

X86汇编 - 如何计算指令操作码长度(以字节为单位)

我正在尝试学习X86汇编(用于学习逆向工程).我学习了C#和C\C++语言以及IL

可能我的主要问题是英语,因为我是波斯语,而且我也找不到任何有用的文件来学习用波斯语写的X86程序集.所以我决定做我为学习C#和C++所做的事情.我试过阅读X86样本和你好世界,但我失败了因为我无法理解我必须选择哪个注册表以及其他只能通过查看源代码无法解决的问题.

所以我决定改变策略并做一个挑战:写一个X86反汇编程序 我很生气,我知道.但我们不能说这是不可能的.第一个认为我需要理解(但没有记住)的是这些表:http://ref.x86asm.net/coder32.html

我对操作码很好,但我不明白如何计算操作数的大小或者寄存器十六进制字节呢?

对不起,我的英语不好.

PS.我想用C#做它

c# assembly

0
推荐指数
1
解决办法
980
查看次数

GCC 是否优化汇编源文件?

我可以使用 GCC 将汇编代码文件转换为可重新分配的文件。

gcc -c source.S -o object.o -O2
Run Code Online (Sandbox Code Playgroud)

优化选项是否有效?我可以期望 GCC 优化我的汇编代码吗?

c assembly gcc gnu-assembler compiler-optimization

0
推荐指数
1
解决办法
359
查看次数