3

我正在尝试构建一个像 OS 一样的旧 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)
    ) ;
 }

然后它工作正常。但是当我将参数传递给它时(即在前面的代码中),它会为任何字符打印一个空格。我该怎么办?

4

2 回答 2

3

如果您尝试让 gcc 生成 16 位代码,则需要使用.code16gcc而不是.code16,以便正确处理函数参数的堆栈:请参阅gas 文档中的“编写 16 位代码”

(此外,根据您使用的 gcc 版本,您可能需要使用 or 选项来编译您kernel.c-fno-unit-at-a-time-fno-toplevel-reorder以确保asm()在任何编译代码之前汇编器确实遇到了该指令 - 否则编译器可能会随机播放。)

于 2010-04-26T23:23:48.737 回答
1

我找到了另一个编译器来解决这个问题:bcc

这是一个用于 8086 cpu 的 C 编译器,对于开发引导加载程序或 BIOS 相关的 8086 代码非常重要。

于 2011-11-29T12:57:23.290 回答