【问题标题】:c bootloader passing function parameters doesn't work rightc引导加载程序传递函数参数无法正常工作
【发布时间】:2017-11-27 20:46:14
【问题描述】:

我在 c 中有一个基本的引导加载程序,但是当我尝试将参数传递给函数时,它不能正常工作。 以下代码不起作用:

__asm__(".code16\n");
__asm__("call main\n");

void main(){
    putchar('X');
    while(1){}
}

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

它应该打印出一个 X,但它只是像打印一个空格一样向前移动光标。

以下代码有效,因为它没有将字符作为参数传递:

__asm__(".code16\n");
__asm__("call main\n");

char c;

void main(){
    c = 'X';
    putchar();
    while(1){}
}

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

有人可以解释为什么它不起作用吗?

【问题讨论】:

  • 我不认为这是你的问题,但 putchar 是一个内置函数
  • @TheAschr :当您使用 -ffreestanding 构建代码时不是这样,因为这是一个引导加载程序。
  • 使用.code16 会遇到严重问题。 .code16 会出现严重的问题,尤其是在传递参数时。你会想要使用.code16gcc。最近的一个问题与这个问题有一些相似之处。我写了这个答案:stackoverflow.com/a/47276625/3857942。您可能希望阅读 GCC Inline Assembly is Hard to Get Right.code16 几乎没用,不应该使用这些部分
  • 您是否碰巧关注了 Codeproject 上的教程?更重要的是你能告诉我你用来编译.c文件的gcc命令行吗?
  • @MichaelPetch :是的,我确实使用了一些关于 codeproject 的教程。这是我的编译器命令: gcc -m32 -c -Os -march=i686 -ffreestanding -Wall -o kernel.o kernel.c -Iinclude

标签: c gcc parameters x86-16 bootloader


【解决方案1】:

问题不在于它作为参数传递,而是我错误地使用了程序集。以下代码有效:

__asm__(".code16\n");
__asm__("call main\n");

void main(){
    putchar('!');
    while(1){}
}

void putchar(char c){
    __asm__ __volatile__("int $0x10" : : "a"(0x0e00 | c), "b"(0x0007));
}

【讨论】:

  • 这不是答案的原因是因为您碰巧运气好优化器内联了函数并且没有使用堆栈来传递参数。为了证明如果函数没有内联并且参数 X 通过堆栈传递,这将中断,可以将这行代码 void putchar(char c){ 修改为 void __attribute__((noinline)) putchar(char c){ 。现在,如果您构建它,它应该会失败。实际上,您很幸运,由于优化器,代码可以正常工作。您还会发现,如果将 GCC 参数 -Os 更改为 -O0 以禁用优化,它也会失败。
猜你喜欢
  • 2017-11-19
  • 1970-01-01
  • 2020-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-12
相关资源
最近更新 更多