如何为我的 OS 在 Windows 上一起编译 link C 和 ASM
How to compile and link C and ASM together on Windows for my OS
我的 32 位保护模式 OS 项目 Sinatra 有问题。我可以将源代码编译为目标文件,但我不知道如何将它们 link 放在一起。我在 Windows 上使用 NASM 和 TDM-GCC。我已经修复了我的代码的问题,所以它可以编译。为了简洁起见,我删除了评论。
我的文件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
开始加载 OS。我怎样才能正确编译和 link 我的代码来创建二进制图像?
首先,如果您要编译为 ELF,则不得在汇编中的函数前添加初始下划线。
现在,为了 link 不同的源文件放在一起,您显然必须让它们达到共同点,在本例中是目标代码。
所以,你要做的是:
- Assemble 汇编源文件到目标代码。
- 编译但不link C 源文件到目标代码。在 gcc 中:
gcc -c file.c -o file.o
- Link 那些在一起。在 gcc 中:
gcc cfile.o asfile.o -o app
在 Windows
上使用 GCC-TDM 和 NASM
因为您的目标是 OS 在没有 C 运行时的情况下加载到绝对地址,所以您需要确保编译为独立代码;您的 asm 和 C 文件针对相同类型的对象 (win32/PECOFF);最后一步是将 PECOFF 文件转换为二进制图像。
要编译 C 文件,您可以使用类似的东西:
gcc -m32 -ffreestanding -c JSinatra.c -o JSinatra.o
对于 assemble asm 文件,您可以使用类似的东西:
nasm -f win32 boot.asm -o boot.o
要link他们在一起你必须分两步完成:
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
我的 32 位保护模式 OS 项目 Sinatra 有问题。我可以将源代码编译为目标文件,但我不知道如何将它们 link 放在一起。我在 Windows 上使用 NASM 和 TDM-GCC。我已经修复了我的代码的问题,所以它可以编译。为了简洁起见,我删除了评论。
我的文件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
开始加载 OS。我怎样才能正确编译和 link 我的代码来创建二进制图像?
首先,如果您要编译为 ELF,则不得在汇编中的函数前添加初始下划线。
现在,为了 link 不同的源文件放在一起,您显然必须让它们达到共同点,在本例中是目标代码。
所以,你要做的是:
- Assemble 汇编源文件到目标代码。
- 编译但不link C 源文件到目标代码。在 gcc 中:
gcc -c file.c -o file.o
- Link 那些在一起。在 gcc 中:
gcc cfile.o asfile.o -o app
在 Windows
上使用 GCC-TDM 和 NASM因为您的目标是 OS 在没有 C 运行时的情况下加载到绝对地址,所以您需要确保编译为独立代码;您的 asm 和 C 文件针对相同类型的对象 (win32/PECOFF);最后一步是将 PECOFF 文件转换为二进制图像。
要编译 C 文件,您可以使用类似的东西:
gcc -m32 -ffreestanding -c JSinatra.c -o JSinatra.o
对于 assemble asm 文件,您可以使用类似的东西:
nasm -f win32 boot.asm -o boot.o
要link他们在一起你必须分两步完成:
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