是否可以从C 中的汇编中调用内置功能

Is it possible to call a built in function from assembly in C++

本文关键字:汇编 调用 内置 功能 是否      更新时间:2023-10-16

考虑以下汇编代码循环:

#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;
}

可以从上面指定的循环中调用C函数(或它的机器代码输出)?

例如:

#include <wmmintrin.h>
int main() {
    __m128i x, y;
    for(int i = 0; i < 10; i++) {
        x = __builtin_ia32_aesenc128(x, y);
    }
    return 0;
}

谢谢

no。内置功能不是您可以使用call调用的实际功能。在C/C 中使用时,它们总是内联。

例如,如果您希望 int __builtin_popcount (unsigned int x)获取具有-mpopcnt目标的popcnt指令,或者要获得不支持popcnt指令的目标的字节查找表,您将不运气。您必须自己#ifdef并使用popcnt或替代说明顺序。


您正在谈论的功能,__builtin_ia32_aesenc128只是aesenc汇编指令的包装器,如果在ASM中写入。

,您可以直接使用它。

如果您正在编写ASM而不是使用C interins(例如#include <immintrin.h>)进行性能,则需要查看http://agner.org/optimize/来编写更有效的ASM。例如使用%ecx作为循环计数器,而不是%cx。您从使用16位部分寄存器中获得了什么。

您还可以写更有效的内联刺激约束,例如movq %%rbx, %0是浪费指令。您可以一直使用%0,而不是说明%rbx。如果您的内联ASM以MOV指令启动或结尾,以复制到输出/输入操作数,通常您会做错。让编译器为您分配寄存器。请参阅内联组装标签Wiki。

或更好,https://gcc.gnu.org/wiki/dontuseinlinelineasm 。内在的代码通常适用于x86。请参阅英特尔的内在指南:#include <immintrin.h>并使用__m128i _mm_aesenc_si128 (__m128i a, __m128i RoundKey)。(在GCC中,这只是__builtin_ia32_aesenc128的包装器,但它使您的代码可移植到其他X86编译器。)

回答您的问题的回答可能分为两个部分。

可以从汇编中调用C函数。为此,您需要遵循呼叫约定(在ABI文档中描述的),该公约指定了如何通过参数并获取返回值。请记住,您有寄存器,堆栈和内存可以移动数据。

内在的,尽管它们看起来像是C函数不是函数。您可以将C视为一个高水平的组装,可用于各种架构。在某些情况下,您想利用您的特定体系结构指令集,因此编译器为您提供了通过内在手段进行操作的方法。每个固有的映射到某些特定体系结构的指令。因此,在一天结束时,您不需要从汇编中调用它们,而是需要找到指令本身,例如,我希望__builtin_ia32_aesenc128被AESenc指令替换。