【问题标题】:Extern C++ compiled fn in asmExtern C++ 在 asm 中编译 fn
【发布时间】:2022-01-15 20:46:08
【问题描述】:

我正在关注 poncho 在 yt 上的操作系统开发系列。

6th video 使用 extern 将 C++ 与汇编代码链接,但代码链接为 C 代码,因为它是 extern "C" void _start()

ExtendedProgram.asm_start 被称为:

[extern _start]
Start64bit:
    mov edi, 0xb8000
    mov rax, 0x1f201f201f201f20
    mov ecx, 500
    rep stosq
    call _start
    jmp $

Kernel.cpp 有:

extern "C" void _start() {
    return;
}

视频中的一个 cmets 显示,对于 C++ 的不同名称,_Z6_startv 是 已创建。
因此,为了尝试,我将Kernel.cpp 修改为:

extern void _Z6_startv() { return; }

还修改了ExtendedProgram.asm,将_start替换为_Z6_startv,但链接器抱怨,

/usr/local/x86_64elfgcc/bin/x86_64-elf-ld:警告:找不到入口符号_start;默认为 0000000000008000

然后我尝试了, 内核.cpp

extern "C++" void _Z6_startv() { return; } // I didn't even know wut i was doin'

链接器又抱怨了。
我确实尝试了一些其他的组合和方法,都以悲惨的结局结束,最终登陆 Stack Overflow。

那么问题来了:

如何将函数编译为C++函数并将其链接到程序集?

【问题讨论】:

  • extern "C" not 表示编译为C 代码。这确实意味着该名称具有外部C 链接。
  • 不,如果您在 C++ 代码中继续使用 start_Z6_startv 是错误符号名称。您需要在 asm 端使用_Z6_startv,而不是 C++ 端。
  • @Jester 是start 还是_start,函数签名应该是extern void _start()

标签: c++ assembly linker


【解决方案1】:

符号之间存在混淆:

您的函数名称start 将在编译时被修改为_Z6_startv,这意味着链接器(和您的asm 代码)可以使用的符号是_Z6_startv。 mangling 是 c++ 编译器通常会做的事情,但是 extern "C" 告诉编译器将该函数视为为 C 程序声明的函数,不会发生 mangling 所以 _start 保持 _start 这意味着您不需要更改代码中的任何内容你最初展示了。

或者如果你想删除extern "C" 你想做的是:

[extern _Z6_startv]
Start64bit:
    mov edi, 0xb8000
    mov rax, 0x1f201f201f201f20
    mov ecx, 500
    rep stosq
    call _Z6_startv
    jmp $

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    相关资源
    最近更新 更多