首页 > 解决方案 > 自制内核内联汇编给出错误的寄存器名称错误。C

问题描述

我正在编写一个自定义内核(其中一些工作来自https://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part)。这是错误

test.c: Assembler messages:
test.c:12: Error: bad register name `%dil'
ld: cannot find test.o: No such file or directory
objcopy: 'test.elf': No such file

这里是文件:

compile.sh

gcc -c -g -Os -march=x86-64 -ffreestanding -Wall -Werror test.c -o test.o
ld -static -Ttest.ld -nostdlib --nmagic -o test.elf test.o
objcopy -O binary test.elf test.bin

test.ld

ENTRY(main);
SECTIONS
{
    . = 0x7c00;
    .text : AT(0x7c00)
    {
        *(.text)
    }
    .sig : AT(0x7dfe)
    {
        SHORT(0xaa55)
    }
}

这是c(与内联汇编混合)源

__asm__(".code16\n");
__asm("jmpl $0x0000, $main\n");

void printChar(char value);

void main() {
    printChar('c');
    printChar('i');
}

void printChar(char value) {
        __asm__("movb %0, %%al\n"
                "movb $0x0e, %%ah\n"
                "int $0x10\n"
                :
                : "r" ( value )
            );
}

我认为错误来自被破坏的寄存器约束(我玩了一点,但是因为我在 16 位中,因为这在引导扇区中,寄存器的行为与我认为的 64 位时不同)。非常感谢任何帮助。另外,请注意,即使是指导我正确方式的提示也足够了。我不一定需要修复 c 代码,我主要寻找的是为什么会发生此错误。谢谢编辑:

我尝试使用 March i686 进行编译,但它说 The cpu you selected doesn't support the x86-64 instructions set and - fcf-protection=full –</p>

我还在 gcc 行中添加了 m16 并且它可以编译,但是当我运行 ld 时,它说输入文件 test.o 的 i386 架构与 i385:x86-64 输出不兼容,所以 gcc 命令是 gcc -c -g -Os -游行=i686 -ffreestanding -Wall -Werror test.c -o test.o - m16

编辑:感谢@Peter Cordes,我找到了解决方法:

Build.sh

gcc -c -g  -march=i686 -Os -ffreestanding -Wall -Werror test.c -o test.o -m32
ld -static -Ttest.ld -nostdlib --nmagic -o test.elf test.o -melf_i386
objcopy -O binary test.elf test.bin

And the c source code
__asm__(".code16\n");
__asm("jmpl $0x0000, $main\n");

void printChar(char value);

void main() {
        printChar('c');
}

void printChar(char value) {
        __asm__(
                "int $0x10\n"
                :
                : "a"(value | (0x0e<<8))
                );
}

我仍然没有理解 "a"(value | (0x0e<<8)) 的作用。有人可以给我一些很好的资源来学习内联汇编吗?

标签: cassemblykernelinline-assemblycpu-registers

解决方案


像这样的寄存器%dil仅在 64 位模式下可用。本教程使用该-march=i686选项,但这假设您的编译器是针对 32 位环境构建的,而本机 Linux x86-64 编译器不是。

正如@Peter Cordes 指出的那样,您需要使用-m16.

或者,如果您打算在本教程之外进行 OS 开发,则应考虑为通用目标环境构建适当的 gcc 交叉编译器。使用操作系统的本机编译器通常会导致操作系统开发出现问题。OSDev 的这个页面是一个很好的起点。


推荐阅读