C编译器未生成有效的程序集输出

C编译器未生成有效的程序集输出,c,assembly,kernel,C,Assembly,Kernel,我正在用C和ASM编写一个简单的内核(调用C编译生成的汇编指令)。我正在关注osdev.org上的这篇优秀文章。在读了一个用汇编编写、编译和执行的内核之后,它工作得很好,我看到kernel.bin在qemu上运行,太棒了。但我真的想用C写,我在同一个网页上找到的 我编译了它,并尝试在qemu上运行kernel.bin,但我从所有设备(硬盘、磁盘驱动器和CD-rom)得到了“引导失败”。然后我分解了由ks.o(使用nasm组装的kernel.asm)生成的kernel.bin和使用ld组装到bin

我正在用C和ASM编写一个简单的内核(调用C编译生成的汇编指令)。我正在关注osdev.org上的这篇优秀文章。在读了一个用汇编编写、编译和执行的内核之后,它工作得很好,我看到kernel.bin在qemu上运行,太棒了。但我真的想用C写,我在同一个网页上找到的

我编译了它,并尝试在qemu上运行kernel.bin,但我从所有设备(硬盘、磁盘驱动器和CD-rom)得到了“引导失败”。然后我分解了由ks.o(使用nasm组装的kernel.asm)生成的kernel.bin和使用ld组装到bin文件的kernel.o(使用gcc组装的kernel.c)。kernel.bin:

我看不到我的字符串,也看不到任何在视频中编写字符串的指令

生成它的C代码:

#define WHITE_TXT 0x07 // white on black text
unsigned int k_printf(char *message, unsigned int line);
void k_clear_screen();

k_main() 
{
    k_clear_screen();
    k_printf("Hi!\nHow's this for a starter OS?", 0);
};

unsigned int k_printf(char *message, unsigned int line) // the message and then the line #
{
    char *vidmem = (char *) 0xb8000;
    unsigned int i=0;

    i=(line*80*2);

    while(*message!=0)
    {
        if(*message=='\n') // check for a new line
        {
            line++;
            i=(line*80*2);
            *message++;
        } else {
            vidmem[i]=*message;
            *message++;
            i++;
            vidmem[i]=WHITE_TXT;
            i++;
        };
    };

    return(1);
};

void k_clear_screen() // clear the entire text screen
{
    char *vidmem = (char *) 0xb8000;
    unsigned int i=0;
    while(i < (80*25*2))
    {
        vidmem[i]=' ';
        i++;
        vidmem[i]=WHITE_TXT;
        i++;
    };
link.ld

OUTPUT_FORMAT("binary")

ENTRY(start)

SECTIONS

{

  .text  0x100000 : {

    code = .; _code = .; __code = .;

    *(.text)

    . = ALIGN(4096);

  }

  .data  : {

    data = .; _data = .; __data = .;

    *(.data)

    . = ALIGN(4096);

  }

  .bss  :

  {

    bss = .; _bss = .; __bss = .;

    *(.bss)

    . = ALIGN(4096);

  }

  end = .; _end = .; __end = .;

}
以及生成文件:

bin:
    nasm -f aout -o ks.o kernelbase.asm 
    gcc -Wall -c -o kernel.o kernel.c    
    ld -T link.ld -o kernel.bin ks.o kernel.o 
run1:
    qemu kernel.bin

clear:
    rm -f *.o

cbin:
    rm -f *.bin
以及纯汇编中的内核,已拆解: 这对我来说效果很好,我可以在视频上看到写作说明

我的操作系统:Ubuntu 10.4
编译器:gcc
汇编程序:NASM


我哪里错了?

我试着做那个教程,代码也失败了。最后我做到了:

编译两个32位文件:

nasm -f elf32 ks.asm -o kernelbase.o
gcc -m32 -c kernel.c -o kernel.o
和链接:

gcc -m32 kernelbase.o kernel.o -o Kernel.bin
过了一段时间,我发现使用gcc进行链接不会出现任何错误


希望我能帮上忙:-)

我试着做那个教程,但代码也失败了。最后我做到了:

编译两个32位文件:

nasm -f elf32 ks.asm -o kernelbase.o
gcc -m32 -c kernel.c -o kernel.o
和链接:

gcc -m32 kernelbase.o kernel.o -o Kernel.bin
过了一段时间,我发现使用gcc进行链接不会出现任何错误


希望我能帮忙:-)

代码缺失。C代码不可能以这种形式编译。不,C代码编译得不太好。此外,还有一些警告。你认为C转换成asm然后组装和“真正用C编写”之间的区别是什么。当然,gcc会这样做,您编译一个c程序,它编译成asm,然后为您调用汇编程序和链接器。没有区别(只要使用相同的编译器/汇编器/链接器、编译选项和链接器脚本)。@NiklasB:如何删除此警告?@dwelch:我知道没有区别,一切都是汇编。当我说“用C编写”时is使用C语法和C编译器进行汇编。缺少代码。C代码不可能以这种形式编译。不,C代码编译得不太好。还有警告。您认为C转换为asm然后进行汇编和“真正用C编写”之间的区别是什么。当然gcc会这样做,你编译一个c程序,它编译成asm,然后为你调用汇编程序和链接器。没有区别(只要你使用相同的编译器/汇编程序/链接器、编译选项和链接器脚本)。@NiklasB.:如何删除此警告?@dwelch:我知道没有区别,一切都是汇编。当我说“用c编写”时is使用C语法和C编译器生成程序集。nasm选项上的-C标志是什么?我删除了它并成功编译了它,并且可以看到有效的程序集输出。另一个问题:您是否尝试过运行kernel.bin?我尝试过使用qemu kernel.bin运行它,但得到类似“引导失败”的结果找不到任何设备,然后我喜欢使用ld:
ld-T link.ld-o kernel.bin kernelbase.o kernel.o
,看起来像是一个进步,它知道并显示“从硬盘引导”,但从未启动内核。非常感谢,@XCoder.Sorry“-c”是我的错误,我编译它时没有“-c”。到目前为止,我还没有测试它。(没有时间);)nasm选项上的-c标志是什么?我删除了它并成功编译了它,我可以看到有效的程序集输出。另一个问题:你试过运行kernel.bin吗?我试过用qemu kernel.bin运行它,但得到类似“boot failed”的结果找不到任何设备,然后我喜欢使用ld:
ld-T link.ld-o kernel.bin kernelbase.o kernel.o
,看起来像是一个进步,它知道并显示“从硬盘引导”,但从未启动内核。非常感谢,@XCoder.Sorry“-c”是我的错误,我编译它时没有“-c”。到目前为止,我还没有测试它。(没有时间);)