许多消息来源写道,有必要在汇编代码中插入一个指示地址的指令.org 0x7C00,据说代码从该地址开始执行(更准确地说,BIOS从磁盘的第一个扇区进入那里)。该指令存在于 Linux 内核源代码和许多其他源代码中,例如https://github.com/fffaraz/bootloader/blob/master/bootloader.asm(顺便说一句,nasm 立即生成一个文件512字节,也不清楚为什么,只有一个猜测:它被自动“trunked”。这个“顺便说一下”指的是链接后的文本)。
理论上说:需要设置16位模式,BIOS读取第一个扇区,分别检查511和512字节是否存在0x55和0xAA,如果检查成功,则将代码放置在地址处0x0000:0x7C00 并开始执行。
我只是想在启动时在屏幕上显示“X”,这是代码和后续步骤:
.org 0x7C00
.code16
start:
mov $'X', %al
mov $0xE, %ah
int $0x10
cli
hlt
. = start + 510
.byte = 0x55
.byte = 0xAA
我编译:
as -o boot.o boot.S
我得到 objdump -D
boot.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <_start-0x7c00>:
...
0000000000007c00 <_start>:
7c00: b0 58 mov $0x58,%al
7c02: b4 0e mov $0xe,%ah
7c04: cd 10 int $0x10
7c06: fa cli
7c07: f4 hlt
...
7dfc: 00 00 add %al,(%rax)
7dfe: 55 push %rbp
7dff: aa stos %al,%es:(%rdi)
Disassembly of section .note.gnu.property:
0000000000000000 <.note.gnu.property>:
0: 04 00 add $0x0,%al
2: 00 00 add %al,(%rax)
4: 20 00 and %al,(%rax)
6: 00 00 add %al,(%rax)
8: 05 00 00 00 47 add $0x47000000,%eax
d: 4e 55 rex.WRX push %rbp
f: 00 02 add %al,(%rdx)
11: 00 01 add %al,(%rcx)
13: c0 04 00 00 rolb $0x0,(%rax,%rax,1)
...
1f: 00 01 add %al,(%rcx)
21: 00 01 add %al,(%rcx)
23: c0 04 00 00 rolb $0x0,(%rax,%rax,1)
27: 00 01 add %al,(%rcx)
29: 00 00 add %al,(%rax)
2b: 00 00 add %al,(%rax)
2d: 00 00 add %al,(%rax)
我删除 .note.gnu.property
strip --remove-section=.note.gnu.property boot.o
关联:
ld --oformat binary -o boot boot.o
输出是一个大小为 32256 字节的文件。呵呵,当然,代码是从0x7C00开始的!查看该文件的十六进制转储,您可以看到该“地址”之前有零。那么问题来了,人们如何将这个文件写入第一个 512 字节扇区呢?当然没办法,有人不告诉什么,qemu-system-i386 -drive format=raw,file=boot他们甚至不会运行这个文件,前512字节中不会有代码
如果我们删除.org 0x7C00,生成的文件大小将恰好为 512 字节。这个文件已经可以启动qemu了。
如何在计算机启动时将控制权从 USB 转移到代码。我这样做:
为此,我使用 dd 实用程序。团队:
dd if=boot of=/dev/sdb bs=512 count=1 conv=notrunc
一切都被记录下来,hexdump也适用于/dev/sdb,前512的内容是相同的。qemu可以运行/dev/sdb
在BIOS中,我禁用安全模式,启用CSM支持(毕竟,uefi已经无处不在),准备好,转到启动选项卡,BIOS看到这个闪存驱动器(顺便说一下,KingstonDatatraveler 3.0),选择它,启动它,打印出令人垂涎的“X”符号。该代码无需 .org 0x7C00 即可运行。
问题:为什么需要这个指令?
更新:
现在我将0xAA更改为0xAF,代码仍然可以读取并运行。我是这样理解的:BIOS(没有uefi)仅将第一个扇区的前440字节复制到RAM中(https://wiki.archlinux.org/title/Arch_boot_process),这意味着它不会读取后续扇区和0x55和 0xAA 并不重要,它们是 uefi 所需要的。
问:我理解的对吗,或者是怎么回事?
