如何告诉g ++链接器x86-64程序集(目标文件)中实现了外部添加功能?

4 c++ ubuntu x86-64 simd nasm

我对链接器为什么不链接到目标文件中的函数感到困惑。

我用x86-64汇编语言实现了一个功能,并通过-f elf64生成了一个目标文件。(Ubuntu是我的目标操作系统。)目标文件已成功生成,但是尝试使用上述目标文件编译我的C ++项目会导致链接器找不到我定义的函数(在目标文件内部)。编译过程如下:

g++ -W -Wall -pedantic -g -std=c++17 main.cpp SSE_Ubuntu_Tuple.cpp SSE_Ubuntu_Tuple.o -o test
Run Code Online (Sandbox Code Playgroud)
#ifndef MATH_TUPLE_HPP
#define MATH_TUPLE_HPP

namespace Math
{
    struct Tuple
    {
        float components[4]; // x, y, z, w
        Tuple(float, float, float, float);
        Tuple operator+(Tuple&) const;
    }; // struct Tuple
} // namespace Math

#endif // MATH_TUPLE_HPP
Run Code Online (Sandbox Code Playgroud)
section .text
global sse_ubuntu_tuple_add

; rdi = &x, rsi = &y

sse_ubuntu_tuple_add:
    movdqa xmm0, [rdi] ; xmm0 = *rdi
    addps xmm0, [rsi] ; *rdi + *rsi
    movdqa [rdi], xmm0 ; *rdi = xmm0
    ret

Run Code Online (Sandbox Code Playgroud)
#include "Tuple.hpp"
#include <algorithm>

namespace Math
{
    extern void sse_ubuntu_tuple_add(float[4], float[4]);

    Tuple::Tuple(float t_x, float t_y, float t_z, float t_w) : components{t_x, t_y, t_z, t_w} {}
    Tuple Tuple::operator+(Tuple& t_rhs) const
    {
        float sum[4]{};
        constexpr int number_of_components = 4;
        std::copy(components, components + number_of_components, sum);
        sse_ubuntu_tuple_add(sum, t_rhs.components);
        return Tuple(sum[0], sum[1], sum[2], sum[3]);
    }
} // namespace Math
Run Code Online (Sandbox Code Playgroud)

我期望没有错误的链接和编译。

Bre*_*ent 5

您需要声明sse_ubuntu_tuple_addextern "C"

extern "C" void sse_ubuntu_tuple_add(float[4], float[4]);
Run Code Online (Sandbox Code Playgroud)

另外,在某些系统上,可能需要在汇编文件中创建带下划线的符号:_sse_ubuntu_tuple_add

编辑:显然,使用ELF,您不需要领先的下划线。

  • 下划线用于Windows COFF格式/ PE可执行文件以及Macho(MacOS)对象和可执行文件。 (4认同)
  • 要扩展此答案,请尝试使用g ++ -c SSE_Ubuntu_Tuple.cpp,然后使用nm检查两个.o文件的符号列表:如果没有extern“ C”,名称将被修改(以允许重载) ),该名称与汇编程序列表中未修改的名称不匹配。 (2认同)