是否可以在C++中从程序集中调用内置函数

Abd*_*had 2 c++ assembly gcc inline-assembly built-in

考虑以下汇编代码循环:

#include <iostream>

#define ADD_LOOP(i, n, v)       \
asm volatile (                  \
    "movw %1, %%cx      ;"      \
    "movq %2, %%rax     ;"      \
    "movq $0, %%rbx     ;"      \
    "for:               ;"      \
    "addq %%rax, %%rbx  ;"      \
    "decw %%cx          ;"      \
    "jnz for            ;"      \
    "movq %%rbx, %0     ;"      \
    : "=x"(v)                   \
    : "n"(i), "x"(n)            \
    : "%cx", "%rax", "%rbx"     \
);

int main() {
    uint16_t iter(10000);
    uint64_t num(5);
    uint64_t val;

    ADD_LOOP(iter, num, val)

    std::cout << val << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

是否可以在循环内调用C函数(或它的机器代码输出),如上所述?

例如:

#include <wmmintrin.h>

int main() {
    __m128i x, y;

    for(int i = 0; i < 10; i++) {
        x = __builtin_ia32_aesenc128(x, y);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

谢谢

Pet*_*des 10

不行.内置函数不是可以调用的实际函数call.它们总是在C/C++中使用时内联.

例如,如果您想要int __builtin_popcount (unsigned int x)获取popcnt目标指令-mpopcnt,或者为不支持该popcnt指令的目标获取逐字节查找表,那么您就不走运了.您必须#ifdef自己使用popcnt或使用其他指令序列.


你在谈论的功能,__builtin_ia32_aesenc128仅仅是一个包装aesenc汇编指令,你可以只如果汇编编写直接使用.


如果您正在编写asm而不是使用C++内在函数(就像#include <immintrin.h>性能一样,您需要查看http://agner.org/optimize/以编写更高效的asm(例如,%ecx用作循环计数器,而不是%cx.你'使用16位部分寄存器不会获得任何好处.

您还可以编写更有效的inline-asm约束,例如movq %%rbx, %0浪费指令.你可以使用%0整个时间而不是显示%rbx.如果你的内联asm以一个mov指令开始或结束来复制到输出/输入操作数,那么通常你做错了.让编译器为您分配寄存器.请参阅标记wiki.

或者更好,https://gcc.gnu.org/wiki/DontUseInlineAsm.具有内在函数的代码通常可以很好地编译x86.请参阅英特尔的内在指南:#include <immintrin.h>并使用__m128i _mm_aesenc_si128 (__m128i a, __m128i RoundKey).(在gcc中它只是一个包装器__builtin_ia32_aesenc128,但它使你的代码可以移植到其他x86编译器.)