GCC 裸机内联汇编 SI 寄存器与指针不能很好地配合

2024-01-29

嗯,这显然是一个初学者的问题,但这是我第一次尝试制作操作系统C(实际上,我几乎完全陌生C..我已经习惯了asm)那么,为什么这实际上是无效的呢?据我所知,一个pointer in C只是一个uint16_t用于指向内存中的某个区域,右(或uint32_t这就是为什么它不起作用)? 我制作了以下内核(“我已经制作了引导加载程序和所有组件以加载生成的 KERNEL.BIN 文件):

kernel.c

void printf(char *str)
{
__asm__(
"mov    si, %0\n"
"pusha\n"
"mov    ah, 0x0E\n"
".repeat:\n"
"lodsb\n"
"cmp    al, 0\n"
"je .done\n"
"int    0x10\n"
"jmp    .repeat\n"
".done:\n"
"popa\n"
:
: "r" (str)
);
return;
}

int main()
{
char *msg = "Hello, world!";
printf(msg);
__asm__("jmp $");
return 0;
}

我使用以下命令来编译它kernel.c:

gcc kernel.c -ffreestanding -m32 -std=c99 -g -O0 -masm=intel -o kernel.bin

返回以下错误:

kernel.c:3: Error: operand type mismatch for 'mov'

为什么可能是导致此错误的原因?


正如 Michael Petch 已经解释的那样,您仅将内联汇编用于 C 中无法完成的绝对最少的代码。其余的都可以使用内联汇编,但您必须非常小心地设置正确的约束和破坏列表。

让 GCC 始终完成将值传递到正确寄存器中的工作,并仅指定值应位于哪个寄存器中。

对于你的问题,你可能想做这样的事情

#include <stdint.h>

void print( const char *str )
{
  for ( ; *str; str++) {
    __asm__ __volatile__("int $0x10" : : "a" ((int16_t)((0x0E << 8) + *str)), "b" ((int16_t)0) : );
  }
}

编辑:您的程序集存在问题,您尝试在 16 位寄存器中传递指针。这不适用于 32 位代码,因为 32 位也是指针大小。 如果您想生成 16 位实模式代码,可以使用 -m16 选项。但这并不能使 GCC 成为真正的 16 位编译器,它有其局限性。本质上,它在代码中发出 .code16gcc 指令。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GCC 裸机内联汇编 SI 寄存器与指针不能很好地配合 的相关文章

随机推荐