我正在编写一个简单的x86引导加载程序。
这是我遇到麻烦的c程序:test4.c
__asm__(".code16\n");
__asm__("jmpl $0x0, $main\n");
void prints ( char* str )
{
char* pStr = str;
while( *pStr )
{
__asm__ __volatile (
"int $0x10"
:
: "a"(0x0e00 | *pStr), "b"(7)
);
pStr++;
}
}
void main ( )
{
char* str = "\n\rHello World\n\r";
char* pStr = str;
while( *pStr )
{
__asm__ __volatile (
"int $0x10"
:
: "a"(0x0e00 | *pStr)
);
pStr++;
}
prints ( str );
}
当我试图在main函数中打印字符串时,它起作用。但当我将字符串传递给另一个函数时,该函数执行相同的指令,但仍然只将
S
打印到屏幕上。所以最终的输出如下所示:Hello World
S
这是我使用的链接器文件:
test.ld
ENTRY(main);
SECTIONS
{
. = 0x7C00;
.text : AT(0x7C00)
{
*(.text);
}
.sig : AT(0x7DFE)
{
SHORT(0xaa55);
}
}
下面是我用来编译c程序和链接它的命令
$ gcc -c -g -Os -m32 -march=i686 -ffreestanding -Wall -Werror test4.c -o test4.o
$ ld -melf_i386 -static -Ttest.ld -nostdlib --nmagic -o test4.elf test4.o
$ objcopy -O binary test4.elf test4.bin
我使用
bochs
模拟器来测试这个引导加载程序 最佳答案
你不能用海合会。忽略那些说你可以的教程——它们是错误的。
最重要的是要记住GCC不是16位编译器。__asm__(".code16\n")
指令不会将其转换为一个;它只是将汇编程序混淆为将GCC的输出从32位x86重定目标为16位。这将导致奇怪和意外的行为,特别是在任何使用指针的代码中。
如果要编写x86引导加载程序,则需要:
使用C编译器,它可以专门针对16位x86(“实模式”)。例如,考虑OpenWatcom工具链。
非常熟悉x86 real模式的特点——特别是分段。
在程序集中编写引导加载程序的某些部分,特别是启动代码。