【发布时间】:2019-07-27 01:46:59
【问题描述】:
我从系统编程开始,但是我遇到了一个小僵局。 我不知道如何使用 NASM 和 g++ 编译器在 asm 文件中运行 cpp 过程。
这是我的文件 kernel.asm:
[BITS 32]
EXTERN scrollup, print
global _start
_start :
mov ax , msggdt
push ax
call print
pop ax
mov ax , msggdt32
push ax
call print
pop ax
mov ax , 3
push ax
call scrollup
pop ax
end:
jmp end
msggdt : db "Load gdt",13 , 10,0
msggdt32 : db "Load protected mode",13,10,0
我的 cpp 文件包含函数 print 和 scrollup
我的编译器是:NASM 2.14 版和 gcc 8.2.0 版(Debian 8.2.0-21)
g++ -c screen.cpp
screen.cpp: In function ‘void _putcar_(uchar)’:
screen.cpp:63:59: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
video = (unsigned char*) (RAMSCREEN + 2 * kX + 160 * kY ) ;
nasm -f elf64 -o kernel.o kernel.asm
您可能注意到了,我尝试调用ld 4 次——不仅要更改对象的顺序,还要更改输出。但是,没有任何效果。
ld --oformat binary -Ttext 1000 screen.o kernel.o -o screen
ld: kernel.o: in function `_start':
kernel.asm:(.text+0x7): undefined reference to `print'
ld: kernel.asm:(.text+0x14): undefined reference to `print'
ld: kernel.asm:(.text+0x21): undefined reference to `scrollup'
ld --oformat binary -Ttext 1000 screen.o kernel.o -o kernel
ld: kernel.o: in function `_start':
kernel.asm:(.text+0x7): undefined reference to `print'
ld: kernel.asm:(.text+0x14): undefined reference to `print'
ld: kernel.asm:(.text+0x21): undefined reference to `scrollup'
ld --oformat binary -Ttext 1000 kernel.o screen.o -o kernel
ld: kernel.o: in function `_start':
kernel.asm:(.text+0x7): undefined reference to `print'
ld: kernel.asm:(.text+0x14): undefined reference to `print'
ld: kernel.asm:(.text+0x21): undefined reference to `scrollup'
ld --oformat binary -Ttext 1000 kernel.o screen.o -o screen
ld: kernel.o: in function `_start':
kernel.asm:(.text+0x7): undefined reference to `print'
ld: kernel.asm:(.text+0x14): undefined reference to `print'
ld: kernel.asm:(.text+0x21): undefined reference to `scrollup'
【问题讨论】:
-
在您的 C++ 文件中,将从程序集调用的函数调用需要定义为
extern "C"以删除名称重整。由于您是在 Linux 上构建的,这意味着您很可能会生成 ELF 对象。你的 C++ 函数不应该有一个前导下划线(如果你在 MacOS 或本机 Windows 上会有所不同)。因为这不是 minimal reproducible example,所以很难说出你的 C++ 代码是什么样的(我必须根据一些错误猜测) -
支持迈克尔。您可以使用
readelf查看损坏的名称。还要注意整个事情的位数:我看到了 16、32 和 64 位的使用/格式。此外,不要忽略警告,尤其是在构建操作系统时。最后,您似乎正在使用 C++,但像 C 一样编程,请考虑切换到后者(可能更容易处理)。 -
Margaret 是正确的。鉴于有关 GDT 的评论以及您正在使用
-f elf64进行汇编的事实,您似乎正在尝试创建 64 位可执行文件,您可以使用 @ 指定 32 位汇编代码生成987654329@,但您的代码似乎是实模式。除非您知道自己在做什么,否则这将走向一个痛苦的世界,因为 GCC 对生成可以在 16 位模式下运行的代码的支持非常缺乏(这是一个严重的hack) 即使使用-m16GCC 选项。 -
我建议使用 GRUB/Multiboot 并且不要创建自己的自定义引导加载程序。然后你需要决定你是在写 64 位操作系统还是 32 位操作系统。