c - 使用扩展汇编语法在实模式下调用 BIOS 服务存在困难

标签 c gcc assembly interrupt real-mode

我正在编写引导加载程序,引导扇区已经移交给第二阶段。从现在开始,我将使用 C 语言进行编程,而不是使用 x86 汇编语言对所有内容进行编程。我的最终目标是制作比 u-boot 更简单但可以查看多重引导 header 并启动内核的东西。大部分操作都是在实模式下完成的。

我正在努力处理这段代码。我的目标是等待击键并获取按下的相应 ASCII 字符。

#include "keyboard.h"

char keyboard_getc(void)
{
    char user_input;

wait_keystroke:
    __asm__ __volatile__ goto ("clc;"
                               "movb %[bios_service], %%ah;"
                               "int $0x16;"
                               "jnc %l[wait_keystroke];"
                               "movb %%al, %[char_input]"
                               : [char_input] "=rm" (user_input)
                               : [bios_service] "r" (0x00)
                               : "%ax", "cc"
                               : wait_keystroke
                               );

   return user_input;
}

编译器侮辱我如下:

i386-elf-gcc -std=c99 -DDEBUG -O1 -c -g -march=i386 -m16 -ffreestanding -Wall -W -I../inc -o keyboard.o keyboard.c
keyboard.c: In function ‘keyboard_getc’:
keyboard.c:13:34: error: expected ‘:’ before ‘[’ token
                                : [char_input] "=rm" (user_input)
                                  ^
keyboard.c:7:1: warning: label ‘wait_keystroke’ defined but not used [-Wunused-label]
 wait_keystroke:
 ^
make: *** [keyboard.o] Error 1

我尝试遵循此文档 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html但我没有找到答案。

有人知道为什么吗?

最佳答案

Section 6.44.3.3 Goto Labels在您链接的文档中说:

An asm goto statement cannot have outputs.

编译器错误试图告诉您这一点,尽管不是以非常明确的方式。 由于在这种情况下,您不需要将标签放在 C 代码中,因此简单的解决方法是将其放入 asm block 中并使用普通的旧 goto-less 内联 asm。为了避免冲突,请使用本地标签。

PS:您不需要mov结果,您可以使用"=a"约束。 bios_service 也不需要是寄存器,并且您不需要 clc。这应该就是您所需要的:

char keyboard_getc(void)
{
    char user_input;

    __asm__ __volatile__("1: movb %[bios_service], %%ah;"
                               "int $0x16;"
                               "jnc 1b;"
                               : "=a" (user_input)
                               : [bios_service] "i" (0x00)
                               : "cc"
                               );

   return user_input;
}

关于c - 使用扩展汇编语法在实模式下调用 BIOS 服务存在困难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34767342/

相关文章:

assembly - 8051组装按钮点击

c - 如何提升函数以在 C 中获取额外参数?

c++ - 静态存储和大对象

C 调用 semget 返回错误 "semget: No such file or directory"

c - 执行期间出现段错误

C++ 自动预处理器代码生成

c++ - 如何使用代码块和 gcc 创建预编译头文件

linux - CentOS yum安装gcc错误: glibc-common conflicts with glibc

assembly - USB 硬盘模拟导致磁盘读取失败(BIOS int 13)?

assembly - 外部符号的目标文件链接如何工作?