gpt4 book ai didi

assembly - 诊断 QEMU 中的引导加载程序代码?

转载 作者:行者123 更新时间:2023-12-02 04:14:56 25 4
gpt4 key购买 nike

诊断 QEMU 中的引导加载程序代码?

我正在尝试创建一个最小的“引导加载程序代码”,打印字符“A”然后停止。

我为此目的编写了以下 C++ 程序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
/*
* If I run these code directly in Windows, it crashes, for I believe Windows
* do not allow accessing the BIOS directly, that make sense
*
* But I can compile a binary, then I can use the debugger to view what machine code
* does these correspond to, and build to boot program!
*/
/*
__asm
{
mov ah, 0x0e
mov al, 0x41
mov bx, 15
int 0x10
hlt
lp: jmp lp
}
*/
int disk_length = 80 * 18 * 512 * 2;
char* disk = (char*)calloc(disk_length, sizeof(char));

const char program[] =
{
0xb4, 0x0e, // mov ah, 0EH
0xb0, 0x41, // mov al, 41H
0x66, 0xbb, 0x0f, 0x00, // mov bx, 0FH
0xcd, 0x10, // int 10H
0xf4, // hlt
0xeb, 0xfe // lp: jmp lp
};
const char boot_signature[] = {0x55, 0xAA};

const int program_length = _countof(program);
const int boot_signature_length = _countof(boot_signature);

// Be careful with file mode
FILE* imgFile = fopen("disk.img", "wb");

memcpy(disk, program, program_length);
memcpy(disk + 510, boot_signature, boot_signature_length);

int written = 0;
while (written < disk_length)
{
written += fwrite(disk + written, sizeof(char), disk_length - written, imgFile);
}
fclose(imgFile);

return 0;
}

首先,我运行了未注释内联程序集的代码。在调试器中,我导出了操作码,并确定操作码与源代码中的操作码相匹配。接下来,我运行带有注释的内联程序集的代码,然后生成一个 img 文件。我使用二进制编辑器来查看内容并确保它看起来像我想要的那样。最后,我运行了 qemu-system-i386.exe -fda disk.img,我期望引导加载程序显示大写的“A”,但什么也没有显示。

现在我有两个问题:

1.) 我的代码有什么问题?2.) 如何诊断?

最佳答案

问题似乎出在这个指令序列上:

0x66, 0xbb, 0x0f, 0x00, //     mov bx, 0FH
0xcd, 0x10, // int 10H

operand prefix 0x66在实模式下,将指令解码为 32 位寄存器(在本例中),然后使用 4 个字节对立即值进行编码。这当然会使用 int 10h 作为 mov 数据的一部分。所以你的指令真正做的是:

0x66, 0xbb, 0x0f, 0x00, 0xcd, 0x10,  // mov ebx,0x10cd000f

之后是通常出现的 hltjmp 指令。在针对 16 位实模式(并预计在 8086/8088 上运行)的代码中,您根本不想使用此类前缀。您的代码应该简单地排除前缀,如下所示:

0xbb, 0x0f, 0x00,       //     mov bx, 0FH
0xcd, 0x10, // int 10H

您可以使用理解 16 位指令的反汇编程序来反汇编 disk.img 文件。 NDISASM 是一种可以处理 16 位代码的优秀反汇编程序,它是 NASM 程序 (Netwide Assembler) 的一部分。 NASM 适用于 WindowsNDISASM 将按以下方式安装并运行:

ndisasm -b16 disk.img

这将尝试将 disk.img 解码为 16 位 (-b16) 二进制文件。您可能会发现字节中翻译后的指令是什么以及出了什么问题。

您还可以尝试使用QEMU中的远程调试功能并使用GDB调试器来单步调试您的代码。我不在 Windows 上运行 QEMU,所以我不知道它是否是使用远程调试支持构建的。


您可以考虑使用可用于生成适合在引导加载程序中使用的 16 位 8086/8088 代码的汇编器(如 NASM),而不是按您现在的方式编写引导加载程序。 Stackoverflow 上有许多问题和解答,展示了如何使用 NASM 来创建引导加载程序。

关于assembly - 诊断 QEMU 中的引导加载程序代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34388084/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com