我正在尝试构建一个旧的 16 位 DOS 操作系统。
我的示例内核代码:
asm(".code16\n");
void putchar(char);
int main()
{
putchar('A');
return 0;
}
void putchar(char val)
{
asm("movb %0, %%al\n"
"movb $0x0E, %%ah\n"
"int $0x10\n"
:
:"r"(val)
) ;
}
这就是我编译它的方式:
nasm -f bin -o ./bin/boot.bin ./source/boot.asm
gcc -nostdinc -fno-builtin -I./include -c -o ./bin/kernel.o ./source/kernel.c
ld -Ttext=0x9000 -o ./bin/kernel.bin ./bin/kernel.o -e 0x0
dd if=/dev/zero of=./bin/empty.bin bs=1440K count=1
cat ./bin/boot.bin ./bin/kernel.bin ./bin/empty.bin|head -c 1440K > ./bin/os
rm ./bin/empty.bin
我在虚拟机中运行它。
当我将 putchar 函数(在内核代码中)设置为常量值时......即像这样:
void putchar()
{
char val = 'A';
asm("movb %0, %%al\n"
"movb $0x0E, %%ah\n"
"int $0x10\n"
:
:"r"(val)
) ;
}
然后就可以正常工作了。但是当我向它传递参数时(即在前面的代码中),它会为任何字符打印一个空格。
我应该怎么办?
如果你试图让 gcc 生成 16 位代码,你需要使用.code16gcc
而不是.code16
,为了获得函数参数的正确堆栈操作:请参阅Gas 文档中的“编写 16 位代码” http://sourceware.org/binutils/docs-2.20/as/i386_002d16bit.html.
(此外,根据您使用的 gcc 版本,您可能需要编译您的kernel.c
与任一-fno-unit-at-a-time
or -fno-toplevel-reorder
选项,以确保asm()
汇编器确实在任何编译代码之前遇到指令 - 否则编译器可能会打乱一切。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)