【问题标题】:inline assembly print function not working内联汇编打印功能不起作用
【发布时间】:2020-08-24 23:12:54
【问题描述】:

这是我应该打印的新内核代码(顺便说一句,它之所以称为 printstack 是因为我试图通过堆栈传递参数,但这不起作用):

void printstack(char in){ /*print function*/
       asm ("mov ah,0x0e\n"
         "mov al,%0\n"
         "int 0x10\n"
    ::"r"(in)
    ); 
}
void main(){ /*kernel entry point*/
  printstack('a');
}

但是当我在 QEMU 中测试它时,它只打印空格。

这是构建 os.flp 的完整脚本:

 echo ">>> Creating floppy image..."
   mkdosfs -C os.flp 1440 || exit   
    echo ">>> Assembling bootloader..."

    nasm -O0 -w+orphan-labels -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit

    echo "compiling kernel"
    gcc -c ./source/kernel.c -masm=intel 
    ld --oformat binary kernel.o -o ./source/kernel.bin  -e main



    echo ">>> Adding bootloader to floppy image..."

    dd status=noxfer conv=notrunc if=source/bootload/bootload.bin   of=os.flp || exit


    echo ">>> Copying kernel"

    rm -rf tmp-loop

    mkdir tmp-loop && mount -o loop -t vfat os.flp tmp-loop && cp source/kernel.bin tmp-loop/


    sleep 0.2

    echo ">>> Unmounting loopback floppy..."

    umount tmp-loop || exit

    rm -rf tmp-loop


t

    echo '>>> Done!'

【问题讨论】:

  • 请发帖Minimal, Reproducible Exampleos.flp 是如何构建的?是否正确考虑了入口点?
  • 这应该取决于环境,但是将main() 的定义移到printstack 之一之前可能会使其表现更好。 (printstack 的声明应该在main() 之前)
  • 您的约束没有描述它修改 EAX(通过覆盖 AH)的事实。作为唯一的 C 语言,这似乎不太可能成为问题,尤其是对于 64 位代码。哦,但是你没有任何 asm 来调用你的 C!您正在制作 64 位机器代码,然后通过 QEMU 在 16 位实模式下执行它。 push rbp / mov rbp,rsp 上的 REX 前缀将解码为 dec eax 指令...在调试器中单步执行 asm 以查看发生了什么。此外,编译器在函数末尾的ret 可能会造成严重破坏。编写一个无限循环并使用gcc -m16编译。
  • 使用 GCC 生成代码以在 16 位实模式下运行是充满问题的(我不推荐它)。如果您不顾警告选择执行此操作,则需要使用-m16 GCC 选项;在调用 main 之前加载内核 SS=DS=CS=ES=0 (并设置 SP 堆栈指针)之前;使用-ffreestanding 编译。有一个答案(在 Proper use of Inline Assembly to Write a String Using the BIOS 部分下)给出了构建内核和使用针对实模式的内联汇编的示例stackoverflow.com/a/57932741/3857942

标签: c kernel x86-16 inline-assembly bootloader


【解决方案1】:

我通过切换 main 和 printstack 的位置以某种方式解决了它:

void main(){
  printstack('a');
}

void printstack(char in){
       asm volatile("mov ah,0x0e\n"
         "mov al,%0\n"
         "int 0x10\n"
    ::"r"(in)
    :"eax"
    ); 
}

【讨论】:

  • 如果这有所作为,那么某些东西就会严重损坏,您不能指望更复杂的 C 可以按预期工作。此外,您仍然缺少"eax" 上的clobber 声明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多