Tag: 汇编

英特尔Broadwell处理器中出现的重大FMA性能exception

代码1: vzeroall mov rcx, 1000000 startLabel1: vfmadd231ps ymm0, ymm0, ymm0 vfmadd231ps ymm1, ymm1, ymm1 vfmadd231ps ymm2, ymm2, ymm2 vfmadd231ps ymm3, ymm3, ymm3 vfmadd231ps ymm4, ymm4, ymm4 vfmadd231ps ymm5, ymm5, ymm5 vfmadd231ps ymm6, ymm6, ymm6 vfmadd231ps ymm7, ymm7, ymm7 vfmadd231ps ymm8, ymm8, ymm8 vfmadd231ps ymm9, ymm9, ymm9 vpaddd ymm10, ymm10, ymm10 vpaddd ymm11, ymm11, ymm11 vpaddd […]

如何查看由C / C ++程序的gcc(任何风格)编译器生成的汇编代码?

我正在尝试优化大量乘法和指针算术,并希望看到当我放入优化标志时,编译器会做什么。 – 编辑 – 如何限制它到一个特定的function或代码块? –Edit_2– 如何让gcc生成一个不太冗长的汇编代码?

在x86汇编中,“lock”指令是什么意思?

我在Qt的源文件中看到了一些x86汇编: q_atomic_increment: movl 4(%esp), %ecx lock incl (%ecx) mov $0,%eax setne %al ret .align 4,0×90 .type q_atomic_increment,@function .size q_atomic_increment,.-q_atomic_increment 从谷歌search,我知道lock指令将导致CPUlocking总线,但我不知道什么时候CPU释放总线? 关于整个上面的代码,我不明白这个代码如何实现Add ?

一个好的NASM / FASM教程?

有谁知道任何好的NASM或FASM教程? 我正在尝试学习汇编,但似乎无法find任何好的资源。

堆栈分配,填充和alignment

我一直试图深入了解编译器如何生成机器码,更具体地说,GCC如何处理堆栈。 为此,我一直在编写简单的C程序,将它们编译成程序集,并尽我所能了解结果。 这里有一个简单的程序和它生成的输出: asmtest.c : void main() { char buffer[5]; } asmtest.s : pushl %ebp movl %esp, %ebp subl $24, %esp leave ret 令我费解的是为什么24字节被分配给堆栈。 我知道,由于处理器如何处理内存,堆栈必须以4为增量进行分配,但如果是这种情况,我们应该只将堆栈指针移动8个字节,而不是24个。作为参考,缓冲区为17字节产生一个移动了40个字节的堆栈指针,并且根本没有任何缓冲区移动堆栈指针8.一个1到16字节的缓冲区移动了ESP 24个字节。 现在假定8个字节是一个必要的常量(它需要什么?),这意味着我们正在分配16个字节的块。 为什么编译器会这样调整呢? 我正在使用x86_64处理器,但是即使是64位字也只需要8字节的alignment方式。 为什么这个差距? 作为参考,我正在使用gcc 4.0.1运行10.5的Mac上进行编译,并且没有启用优化。

C代码循环性能

我的应用程序中有一个乘加内核,我想提高它的性能。 我使用Intel Core i7-960(3.2 GHz时钟),并已经使用SSE内部函数手动实现了内核,如下所示: for(int i=0; i<iterations; i+=4) { y1 = _mm_set_ss(output[i]); y2 = _mm_set_ss(output[i+1]); y3 = _mm_set_ss(output[i+2]); y4 = _mm_set_ss(output[i+3]); for(k=0; k<ksize; k++){ for(l=0; l<ksize; l++){ w = _mm_set_ss(weight[i+k+l]); x1 = _mm_set_ss(input[i+k+l]); y1 = _mm_add_ss(y1,_mm_mul_ss(w,x1)); … x4 = _mm_set_ss(input[i+k+l+3]); y4 = _mm_add_ss(y4,_mm_mul_ss(w,x4)); } } _mm_store_ss(&output[i],y1); _mm_store_ss(&output[i+1],y2); _mm_store_ss(&output[i+2],y3); _mm_store_ss(&output[i+3],y4); } 我知道我可以使用打包的fp向量来提高性能,而且我已经成功地做到了这一点,但是我想知道为什么单个标量代码无法满足处理器的峰值性能。 这个内核在我的机器上的性能是每个周期约1.6个FP操作,而每个周期最多可以有2个FP操作(因为FP + FP […]

x86_64寄存器rax / eax / ax / al覆盖整个寄存器的内容

正如广泛宣传的那样,现代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 […]

为什么unique_ptr实例化比原始指针更大的二进制编译?

我总是觉得std::unique_ptr与使用原始指针相比没有开销。 但是,编译下面的代码 #include <memory> void raw_pointer() { int* p = new int[100]; delete[] p; } void smart_pointer() { auto p = std::make_unique<int[]>(100); } 用g++ -std=c++14 -O3产生下面的程序集: raw_pointer(): sub rsp, 8 mov edi, 400 call operator new[](unsigned long) add rsp, 8 mov rdi, rax jmp operator delete[](void*) smart_pointer(): sub rsp, 8 mov edi, 400 call operator […]

为什么GCC在分配variables之前将variables移动到临时位置?

在看一些反编译的C代码时,我看到了这个: movl -0xc(%rbp), %esi movl %esi, -0x8(%rbp) 这对应于这个C代码: x = y; 这让我想到:gcc如何将y移动到%esi ,然后将%esi移动到x而不是直接将y移动到x ? 这是整个C和反编译的代码,如果它很重要: C int main(void) { int x, y, z; while(1) { x = 0; y = 1; do { printf("%d\n", x); z = x + y; x = y; y = z; } while(x < 255); } } 反编译 pushq %rbp […]

assembly指令如何变成CPU上的电压变化?

在过去的3 – 5年里,我一直在C和CPython工作。 考虑一下我的知识基础。 如果我将一个汇编指令(如MOV AL, 61h用于支持它的处理器,那么处理器内部究竟是什么内容来解释这个代码并将其作为电压信号进行调度? 这样一个简单的指令怎么可能被执行呢? 当我试图想到MOV AL, 61h甚至XOR EAX, EBX包含的大量步骤时,Assembly甚至感觉像是高级语言。 编辑:我读了一些评论,问为什么我把这个作为embedded式时,x86系列是不常见的embedded式系统。 欢迎来到我自己的无知。 现在我认为,如果我对此一无所知,也可能有其他人对此毫无所知。 考虑到你们所有人的努力,对于我来说,select一个最喜欢的答案是困难的,但是我感到不得不作出决定。 没有伤害的感觉,家伙。 我经常发现,我对计算机了解得越多,我越是意识到自己真的知道了。 感谢您打开我的想法微码和晶体pipe逻辑! 编辑#2:感谢这个线程,我只是理解为什么XOR EAX, EAX比MOV EAX, 0h更快。 🙂