【问题标题】:Why is my bare metal hello world code not booting in x86_64为什么我的裸机 hello world 代码无法在 x86_64 中启动
【发布时间】:2020-03-27 00:38:47
【问题描述】:

我正在做一个 hello world 项目以在我的 x86 裸机物理机上运行, 但是代码没有运行(启动)并且机器继续进行下一个启动设备, 我在汇编中编写了代码,以下步骤是我所做的:

第 1 步:通过 Bios 调用显示字符 A abd B 的代码

.L1 :
mov %ah,0x0E     
mov %bh,0x00     
mov %bl,0x07     
mov %al,65   
INT $0x10    

mov %ah,0x0E     
mov %bh,0x00     
mov %bl,0x07     
mov %al,66   
INT $0x10   
jmp .L1

第 2 步:

组装代码并以二进制格式生成代码:

as -o Code Code.txt
objcopy -O binary Code binfile

第 3 步:

打开HxD并显示汇编代码的二进制形式并填充 它用零直到我填充它们的第一个 512 字节的最后两个字节 55AA(十六进制)看起来像:

第四步:

将图像复制到闪存中:

dd bs=512 count=1 if=binfile of="\\.\e:"

(注意:我在 windows 上使用 dd)


  • 注意:依赖于第一个扇区中的引导代码将显示两个字符的事实 没有使用 anu 进一步的引导加载程序,因为那是我的第一个项目,所以我设法保持简单。

  • 不显示这些字符,并显示一条消息无效可启动设备,设备跳到下一个设备并正常启动窗口..我在这里缺少什么?

【问题讨论】:

  • @rfmodulator:我认为那部分是正确的:对于主引导记录,它应该是单词0xAA55,也就是两个字节0x55 0xAA
  • @rfmodulator:不,我不这么认为。十六进制编辑器正在显示字节。偏移量 510 处的字节为55,偏移量 511 处的字节为AA,它们以小端形式一起构成单词0xAA55
  • @NateEldredge 好的,感谢您的澄清...我认为 UEFI 也必须被禁用?很抱歉劫持了 Eng_Boody!
  • 但是分区表是的前512个字节,所以通过写入你的文件,你已经用零覆盖了它。
  • @rfmodulator:是的,这是另一个好点:BIOS 可能未设置为从 MBR 启动。

标签: assembly x86 bootloader bios att


【解决方案1】:

收集cmets中讨论的一些问题:

  1. 每台 x86 机器都以 16 位 real mode 启动,因此您的启动代码必须是 16 位代码。您需要在源文件的顶部指定 .code16 才能让 gnu 生成它。如果要最终以 64 位长模式执行,则必须编写代码来进行模式切换。这在 CPU 手册中有详细记录,但有点复杂。 (请注意,这样做之后,您将无法再调用int 10h BIOS 函数,因为它们也是 16 位代码。)

  2. 在 AT&T 汇编语法中,这是 gnu 默认使用的,将立即 0x0e 加载到 ah 寄存器中写为 mov $0x0e, %ah。您的版本会将%ah 的内容存储到内存位置0x0e,这不是您想要的。这几乎适用于代码中的每条指令。但您可能希望改用其他汇编程序,例如 nasm,它更适合处理 16 位代码。

  3. 主引导记录(硬盘的零扇区)应该包含磁盘的分区表,从偏移量 446 开始。你的只包含零。从某种意义上说,这并不重要,因为您的代码永远不会尝试从磁盘读取任何内容,但它可能会导致您的 BIOS 确定 MBR 无效并且磁盘不可启动。

  4. 我不相信您的dd 命令实际上正在写入磁盘的主引导记录。相反,它可能正在写入其分区之一的引导扇区。我对dd for windows 不是很熟悉,所以您需要自己解决。

我不确定您的问题是由这些问题之一还是其​​他原因引起的,但无论如何您最终都需要解决所有问题。

【讨论】:

  • 它实际上是写入卷引导记录(分区)而不是 MBR。一种解决方法是使用 Chrysocome DD 。最新版本具有 OD= 选项,您可以在其中指定驱动器号(即:E:),并且 OD= 将相对于媒体的开头而不是卷引导记录开始写入。我在这个答案中写了一些信息:stackoverflow.com/a/34108769/3857942。如果您从 USB 启动,并且 BIOS 作为 USB FDD 媒体启动,您可能需要 BPB。我在这里讨论潜在的问题:stackoverflow.com/a/47320115/3857942
  • 哎呀,以前讨论 Windows 上的 DD 的答案的链接是这个答案:stackoverflow.com/a/32897160/3857942。该答案还讨论了写入 VBR 而不是 MBR 的问题。
  • 有趣的事实:在这种特殊情况下,mov reg8, imm16 实际上在 16 位和 64 位模式下具有相同的机器代码。 (mov [absolute], reg8` 没有。所以(un?)幸运的是,即使没有.code16,只要修复.intel_syntax noprefix 以 AT&T 语法正确编写它,OP 的代码就会发生工作。但是是的,你肯定想要.code16 汇编将在 16 位模式下执行的代码。任何使用 16 位或 32 位寄存器或 16/32 位立即数或位移的内容在有/没有 6667 的情况下都将是错误的大小前缀。)
  • @PeterCordes 你的意思是mov re8, imm8
  • @fuz:是的,谢谢。我已经在考虑指令长度取决于操作数大小的 imm16 案例。 >.
猜你喜欢
  • 2019-05-28
  • 1970-01-01
  • 2022-12-16
  • 2019-09-19
  • 1970-01-01
  • 1970-01-01
  • 2018-01-12
  • 1970-01-01
  • 2019-05-08
相关资源
最近更新 更多