Dru*_*ker 5 linux assembly kernel nasm 16-bit
我试图在nasm中构建一个简单的x86 Linux引导程序.
Linux bzImage从第一个扇区开始存储在磁盘分区sda1上.
我从bzImage(15个扇区)读取实际模式代码到0x7E00开始的内存中.但是,当我跳入代码时,它只是挂起,没有任何反应.
我已经在sda上为主启动记录创建了代码.如果我只是附上整件事,我可能是最好的.我想知道为什么它只是在跳远指令后挂起.
[BITS 16]
%define BOOTSEG 0x7C0
%define BOOTADDR (BOOTSEG * 0x10)
%define HDRSEG (BOOTSEG + 0x20)
%define HDRADDR (HDRSEG * 0x10)
%define KERNSEG (HDRSEG + 0x20)
[ORG BOOTADDR]
entry_section:
cli
jmp start
start:
; Clear segments
xor ax, ax
mov ds, ax
mov es, ax
mov gs, ax
mov fs, ax
mov ss, ax
mov sp, BOOTADDR ; Lots of room for it to grow down from here
; Read all 15 sectors of realmode code in the kernel
mov ah, 0x42
mov si, dap
mov dl, 0x80
int 0x13
jc bad
; Test magic number of kernel header
mov eax, dword [HDRADDR + 0x202]
cmp eax, 'HdrS'
jne bad
; Test jump instruction is there
mov al, byte [KERNSEG * 16]
cmp al, 0xEB
jne bad
xor ax, ax ; Kernel entry code will set ds = ax
xor bx, bx ; Will also set ss = dx
jmp dword KERNSEG:0
; Simple function to report an error and halt
bad:
mov al, "B"
call putc
jmp halt
; Param: char in al
putc:
mov ah, 0X0E
mov bh, 0x0F
xor bl, bl
int 0x10
ret
halt:
hlt
jmp halt
; Begin data section
dap: ; Disk address packet
db 0x10 ; Size of dap in bytes
db 0 ; Unused
dw 15 ; Number of sectors to read
dw 0 ; Offset where to place data
dw HDRSEG ; Segment where to place data
dd 0x3F ; Low order of start addres in sectors
dd 0 ; High order of start address in sectors
; End data section
times 446-($-$$) db 0 ; Padding to make the MBR 512 bytes
; Hardcoded partition entries
part_boot:
dw 0x0180, 0x0001, 0xFE83, 0x3c3f, 0x003F, 0x0000, 0xF3BE, 0x000E
part_sda2:
dw 0x0000, 0x3D01, 0xFE83, 0xFFFF, 0xF3FD, 0x000E, 0x5AF0, 0x01B3
part_sda3:
dw 0xFE00, 0xFFFF, 0xFE83, 0xFFFF, 0x4EED, 0x01C2, 0xb113, 0x001D
part_sda4:
dw 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
dw 0xAA55 ; Magic number at relative address 510
mbrend: ; Relative address 512
Run Code Online (Sandbox Code Playgroud)
假设您的代码是引导加载程序(因此不是 MBR):
puts("Read error while trying to load boot loader")而不仅仅是putc('B'))。其他所有内容(加载内核片段、设置视频模式、在“实模式内核头”字段中设置正确的值等)都应该位于附加扇区中,而不是位于第一个扇区中。请注意,计算机的启动方式经过精心设计,以便任何 MBR 都可以链式加载任何磁盘的任何分区上的任何操作系统;并且MBR可能是允许安装多个操作系统的更大的东西(例如启动管理器)的一部分(例如用户可以使用漂亮的菜单或其他东西来选择MBR的代码应该链式加载的分区)。这种设计允许用户随时用其他任何东西替换 MBR(或启动管理器),而不会影响任何已安装的操作系统(或导致所有已安装的操作系统需要修复)。举一个简单的例子,用户应该能够拥有 12 个不同的分区,它们都包含引导加载程序和单独/独立版本的 Linux,然后安装他们需要的任何引导管理器(例如 GRUB、Plop、GAG、MasterBooter 等)。随时想要。
至于代码挂起的原因,这并不是很重要,因为无论如何都需要重写所有代码。如果您好奇,我强烈建议在带有调试器(例如 Bochs)的模拟器中运行它,以便您可以准确检查发生了什么(例如,在 0x00007E00 处转储内存以查看它包含的内容,单步执行 JMP 到查看正在执行的内容等)。
| 归档时间: |
|
| 查看次数: |
1167 次 |
| 最近记录: |