Tag: assembly

退出的Syscall实现()

我写了一个简单的C程序,只调用exit()函数,但是strace说二进制文件实际上是调用exit_group,exit()是一个exit_group()包装器吗? 这两个function是否相同? 如果是这样,为什么编译器会选择exit_group()而不是exit()?

一个目标文件中的代码对齐正在影响另一个目标文件中的函数的性能

我熟悉数据对齐和性能,但我很擅长对齐代码。 我最近开始使用NASM在x86-64汇编中进行编程,并且一直在使用代码对齐来比较性能。 据我所知,NASM插入nop指令来实现代码对齐。 这是我在Ivy Bridge系统上尝试过的function void triad(float *x, float *y, float *z, int n, int repeat) { float k = 3.14159f; int(int r=0; r<repeat; r++) { for(int i=0; i<n; i++) { z[i] = x[i] + k*y[i]; } } } 我正在使用的组件如下。 如果我没有指定对齐,我的性能与峰值相比只有大约90%。 但是,当我将循环前的代码以及两个内部循环对齐到16个字节时,性能会跳跃到96%。 很明显,这种情况下的代码对齐有所不同。 但这是最奇怪的部分。 如果我将最里面的循环对齐到32个字节,那么这个函数的性能没有任何区别,但是,在这个函数的另一个版本中,在单独的目标文件中使用内在函数,我将其性能从90%链接到95%! 我做了一个对象转储(使用objdump -d -M intel )的版本对齐到16个字节(我将结果发布到这个问题的结尾)和32个字节,它们是相同的! 事实certificate,在两个目标文件中,最内层循环无论如何都对齐到32个字节。 但必须有一些区别。 我对每个目标文件进行了hex转储,目标文件中有一个字节不同。 对齐到16个字节的目标文件具有0x10的字节,并且对应于32个字节的目标文件具有0x20的字节。 到底是怎么回事! […]

at&t asm inline c ++问题

我的代码 const int howmany = 5046; char buffer[howmany]; asm(“lea buffer,%esi”); //Get the address of buffer asm(“mov howmany,%ebx”); //Set the loop number asm(“buf_loop:”); //Lable for beginning of loop asm(“movb (%esi),%al”); //Copy buffer[x] to al asm(“inc %esi”); //Increment buffer address asm(“dec %ebx”); //Decrement loop count asm(“jnz buf_loop”); //jump to buf_loop if(ebx>0) 我的问题 我正在使用gcc编译器。 出于某种原因,我的缓冲区/ howmany变量在我的asm眼中是不确定的。 我不知道为什么。 我只想将缓冲区数组的起始地址移动到esi寄存器中,将每个元素复制到al寄存器时循环“howmany”次。

使用谓词指令将c转换为程序集

我想使用谓词指令将此代码转换为程序集 If (A>B){ C=A; D=B; E=0 } else{ C=B; } 它是正确的还是我如何使用跳跃? cmp R1,R2; considering B is assigned to R2 and A assigned to R1 movlf R3,R1;R3 assign to C mov R4,R2;R4 assign to D mov R5,0; R5 assign to E movlt R3,R2

在GNU C inline asm中,对于单个操作数,xmm / ymm / zmm的修饰符是什么?

在尝试使用内在函数和汇编来回答嵌入式广播时 ,我试图做这样的事情: __m512 mul_broad(__m512 a, float b) { int scratch = 0; asm( “vbroadcastss %k[scalar], %q[scalar]\n\t” // want vbr.. %xmm0, %zmm0 “vmulps %q[scalar], %[vec], %[vec]\n\t” // how it’s done for integer registers “movw symbol(%q[inttmp]), %w[inttmp]\n\t” // movw symbol(%rax), %ax “movsbl %h[inttmp], %k[inttmp]\n\t” // movsx %ah, %eax : [vec] “+x” (a), [scalar] “+x” (b), [inttmp] “=r” […]

如何从C程序内部或内联汇编中获取C函数的大小?

假设我有如下函数: # cat 003.c int foo(int a, int b) { return a+b; } 并编译它像这样: gcc -S 003.c 得到以下汇编结果: .file “003.c” .text .globl foo .type foo, @function foo: .LFB2: pushq %rbp .LCFI0: movq %rsp, %rbp .LCFI1: movl %edi, -4(%rbp) movl %esi, -8(%rbp) movl -8(%rbp), %edx movl -4(%rbp), %eax addl %edx, %eax leave ret .LFE2: .size foo, […]

海湾合作委员会:禁止使用某些登记册

这是一个奇怪的请求,但我有一种感觉,它可能是可能的。 我想要的是将一些pragma或指令插入到我的代码区域(用C语言编写),这样GCC的寄存器分配器就不会使用它们。 我知道我可以做这样的事情,这可能会为这个变量留下这个寄存器 register int var1 asm (“EBX”) = 1984; register int var2 asm (“r9”) = 101; 问题是我直接插入新指令(用于硬件模拟器),而GCC和GAS还没有识别出这些指令。 我的新指令可以使用现有的通用寄存器,我想确保我保留了一些(即r12-> r15)。 现在,我正在模拟环境中工作,我想快速完成我的实验。 将来我会添加GAS并将内在函数添加到GCC中,但是现在我正在寻找快速修复。 谢谢!

使用进位标志添加多字

GCC具有128位整数。 使用这些我可以让编译器使用mul (或只有一个操作数的imul )指令。 例如 uint64_t x,y; unsigned __in128 z = (unsigned __int128)x*y; 生产多 我用它来创建一个128×128到256的函数(在更新之前,请参阅此问题的结尾,如果您感兴趣,请参阅此代码)。 现在我想要进行256位加法,除了使用汇编之外,我还没有找到让编译器使用ADC的方法。 我可以使用汇编程序,但我想要内联函数以提高效率。 编译器已经生成了一个有效的128×128到256函数(因为我在这个问题的开头解释了)所以我不明白为什么我应该在汇编中重写它(或者编译器已经有效实现的任何其他函数) 。 这是我提出的内联汇编函数: #define ADD256(X1, X2, X3, X4, Y1, Y2, Y3, Y4) \ __asm__ __volatile__ ( \ “addq %[v1], %[u1] \n” \ “adcq %[v2], %[u2] \n” \ “adcq %[v3], %[u3] \n” \ “adcq %[v4], %[u4] \n” \ : […]

混合SSE整数/浮点SIMD指令时,是否会降低性能?

我最近以内在函数的forms使用了x86 SIMD指令(SSE1234)。 我发现令人沮丧的是SSE ISA有几个简单的指令,只能用于浮点数或仅用于整数,但理论上应该对两者都有相同的效果。 例如,float和double向量都有指令从地址( movhps , movhpd )加载更高的64位128位向量,但是没有这样的整数向量指令。 我的问题: 在整数向量上使用浮点指令时,有没有理由期望性能受到影响,例如使用movhps将数据加载到整数向量? 我写了几个测试来检查,但我认为他们的结果不可信。 编写一个正确的测试来探索这些事情的所有极端情况真的很难,特别是在这里最可能涉及指令调度时。 相关问题: 其他平凡相似的东西也有几个基本相同的指令。 例如,我可以使用por , orps或orpd按位OR。 任何人都可以解释这些附加说明的目的是什么? 我想这可能与应用于每条指令的不同调度算法有关。

x86的MOV真的可以“免费”吗? 为什么我不能重现这个呢?

我一直看到人们声称MOV指令可以在x86中免费,因为寄存器重命名。 对于我的生活,我无法在一个测试用例中validation这一点。 每个测试用例我尝试揭穿它。 例如,这是我用Visual C ++编译的代码: #include #include #include int main(void) { unsigned int k, l, j; clock_t tstart = clock(); for (k = 0, j = 0, l = 0; j < UINT_MAX; ++j) { ++k; k = j; // <– comment out this line to remove the MOV instruction l += j; } […]