如何在 Windows 上为我的操作系统编译和链接 C 和 ASM
Posted
技术标签:
【中文标题】如何在 Windows 上为我的操作系统编译和链接 C 和 ASM【英文标题】:How to compile and link C and ASM together on Windows for my OS 【发布时间】:2015-08-28 20:52:24 【问题描述】:我的 32 位保护模式操作系统项目 Sinatra 有问题。我可以将源代码编译为目标文件,但我不知道如何将它们链接在一起。我在 Windows 上使用 NASM 和 TDM-GCC。我已经修复了我的代码的问题,因此它可以编译。为简洁起见,我删除了 cmets。
我的档案boot.asm
:
[BITS 32]
[global start]
[extern _JlMain]
start:
cli
call _JlMain
hlt
我的档案JSinatra.h
:
#ifndef __SINATRA_H__
#define __SINATRA_H__
#define JWhiteText 0x07
void JlMain();
void JlClearScreen();
unsigned int JlPrintF(char * message, unsigned int line);
#endif
我的档案JSinatra.c
:
#include "JSinatra.h"
void JlClearScreen() // clear entire screen
char * vidmem = (char * ) 0xb8000;
unsigned int i = 0;
while (i < (80 * 25 * 2))
vidmem[i] = ' ';
i += 1;
vidmem[i] = JWhiteText;
i += 1;
unsigned int JlPrintF(char * message, unsigned int line)
char * vidmem = (char * ) 0xb8000;
unsigned int i = 0;
i = line * 80 * 2;
while ( * message != 0)
if ( * message == '\n')
line += 1;
i = (line * 80 * 2); * message += 1;
else
vidmem[i] = * message; * message += 1;
i += 1;
vidmem[i] = JWhiteText;
i += 1;
return (1);
void JlMain()
JlClearScreen();
JlPrintF("Sinatra v0 Virgin/Kernel Mode\n", 0);
我需要从绝对地址0x100000
开始加载我的操作系统。如何正确编译和链接我的代码以创建二进制图像?
【问题讨论】:
您使用的是什么编译器和链接器工具链?使用 GCC 和 GNU binutils,这是微不足道的。 C 和汇编文件都会生成ld
知道如何链接的 ELF 文件。抱歉,您的问题非常含糊,我认为您需要先了解一些基础知识,然后再询问我们如何帮助您的操作系统项目。
我正在使用 GCC/G++(在我看来,它们是相同的)和 Netw。 Windows 中的汇编程序。正如我所说,我有源文件,但我不明白 ld 也不知道应该如何使用链接器脚本。
什么“Windows 中的汇编程序”?听起来很糟糕。
很抱歉,这对于 Stack Overflow 来说太宽泛了。我们不可能在一个问题中教你所有你需要知道的关于编译器、汇编器、链接器、链接器脚本等的知识。我强烈建议您自己进行研究,通过查找教程和示例代码,您可以从中学习。
对不起,宽泛。正如我所说,我不知道链接器脚本,我正在在线添加其中一个 ld 脚本。
【参考方案1】:
首先,如果您要编译为 ELF,那么您不能在汇编中的函数之前添加初始下划线。
现在,为了将不同的源文件链接在一起,您显然必须让它们有共同点,在这种情况下,就是目标代码。
那么,你要做的是:
-
将汇编源文件组装成目标代码。
编译但不将 C 源文件链接到目标代码。在 gcc 中:
gcc -c file.c -o file.o
将这些链接在一起。在 gcc 中:gcc cfile.o asfile.o -o app
【讨论】:
asfile.o:文件无法识别:文件格式无法识别 -- collect2.exe:错误:ld 返回 1 退出状态@amr-ayman 尝试 32 位的-m32
选项。 -m64
用于 64 位。【参考方案2】:
在 Windows 上使用 GCC-TDM 和 NASM
因为您的目标是在没有 C 运行时的绝对地址加载操作系统,所以您需要确保编译为独立代码;您的 asm 和 C 文件以相同类型的对象 (win32/PECOFF) 为目标;最后一步是将 PECOFF 文件转换为二进制图像。
要编译 C 文件,你会使用类似的东西:
gcc -m32 -ffreestanding -c JSinatra.c -o JSinatra.o
要组装 asm 文件,您可以使用以下内容:
nasm -f win32 boot.asm -o boot.o
要将它们链接在一起,您必须分两步完成:
ld -m i386pe -T NUL -o sinatra.tmp -Ttext 0x100000 boot.o JSinatra.o
上面的ld
命令将创建一个临时文件sinatra.tmp
,它是一个32 位PECOFF 可执行文件。然后,您需要使用以下命令将sinatra.tmp
转换为二进制图像:
objcopy -O binary sinatra.tmp sinatra.img
你应该在文件sinatra.img
中有一个二进制图像
【讨论】:
ld:无法识别的仿真模式:elf_i386,支持的仿真:i386pe @MichaelPetch ld: 无法对非 PE 输出文件 'sinatra' 执行 PE 操作。 @MichaelPetch 它说的一样! (而且我使用 TDM-GCC、Cygwin 或 MinGW 需要几个世纪才能安装......)@MichaelPetch 你来的时候请通知我。 @MichaelPetch @AraneaSerket6848 :我刚刚更新了答案。我原来的ld
命令出错了,因为我无意中删除了.text
部分,这意味着最终图像中不存在要显示的字符串以上是关于如何在 Windows 上为我的操作系统编译和链接 C 和 ASM的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Windows 上为 CUDA 链接库(例如 CUBLAS、CUSPARSE)
如何在 Windows 上为 CUDA 链接库(例如 CUBLAS、CUSPARSE)
如何从多台机器上为我的 django 网站提供服务,即如何使其分布式?