Extern C++ 在 asm 中编译 fn

Extern C++ compiled fn in asm

我正在 yt 上关注 poncho 的 OS 开发系列。

6th video link 使用 extern 使用汇编代码编辑了 C++,但代码 link 编辑为 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;
}

视频中的一条评论显示,对于 C++ 不同的名称,_Z6_startv 是 已创建。
所以为了尝试,我将 Kernel.cpp 修改为:

extern void _Z6_startv() { return; }

并且还修改了 ExtendedProgram.asm,将 _start 替换为 _Z6_startv,但 link 人抱怨说,

/usr/local/x86_64elfgcc/bin/x86_64-elf-ld: warning: cannot find entry symbol _start; defaulting to 0000000000008000

然后我尝试了, Kernel.cpp

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

然后link她又投诉了。
我确实尝试了一些其他的组合和方法,都以悲惨的结局结束,最终在 Stack Overflow 上登陆。

所以,问题:

如何将函数编译为 C++ 函数并 link 汇编?

符号之间存在混淆:

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

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

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