【问题标题】:C compiler is not generating valid assembly outputC 编译器没有生成有效的汇编输出
【发布时间】:2012-03-22 07:24:29
【问题描述】:

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

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

http://pastebin.com/Y0pLFvij我看不到我的字符串或任何汇编指令将我的字符串写在视频上。

生成它的 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++;
    };

以及调用它的assembly

[bits 32]

[global start]
[extern k_main] ; this is in the c file

start:
  call k_main

  cli  ; stop interrupts
  hlt ; halt the CPU

链接.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

和内核在纯汇编中,反汇编:http://pastebin.com/Bkvkq3YQ 这对我来说效果很好,我可以看到在视频上写字的说明。

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

我哪里错了?

【问题讨论】:

  • 缺少代码。 C 代码不可能以这种形式编译。
  • 不,C 代码编译得不太好。此外,还有警告。
  • 您认为 C 转换为 asm 然后组装和“真正用 C 编写”之间的区别是什么。当然 gcc 会这样做,你编译一个 c 程序,它编译成 asm,然后为你调用汇编器和链接器。没有区别(只要您使用相同的编译器/汇编器/链接器、编译选项和链接器脚本。
  • @NiklasB.:如何删除此警告?
  • @dwelch:我知道没有区别,都是组装。当我说“用 C 编写”时,是使用 C 语法和 C 编译器进行汇编。

标签: c assembly kernel


【解决方案1】:

我尝试完成该教程,但代码也失败了。最后我做到了:

为 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 进行链接没有任何错误。

希望我能帮上忙 :-)

【讨论】:

  • nasm 选项上的 -c 标志是什么?我删除它并成功编译,我可以看到有效的程序集输出。另一个问题:你试过运行 kernel.bin 吗?我尝试使用 qemu kernel.bin 运行它,但我得到类似“启动失败”找不到任何设备,然后我喜欢使用 ld:ld -T link.ld -o kernel.bin kernelbase.o kernel.o ,看起来像是一个进步,它知道并显示“从硬盘启动”但永远不要启动内核。非常感谢,@XCoder。
  • 对不起“-c”是我的错误我编译它没有“-c”。到目前为止,我还没有测试它。 (没时间);)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-24
  • 2014-02-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多