gpt4 book ai didi

assembly - 加载引导加载程序的第二阶段并启动它

转载 作者:行者123 更新时间:2023-12-02 22:12:55 26 4
gpt4 key购买 nike

最近我试图了解引导加载程序的工作原理。我正在用 nasm 汇编器编写我的加载程序,并使用 bochs 和软盘镜像对其进行测试。

第 1 阶段和第 2 阶段编译的二进制文件通过复制合并到一个镜像中。这张图片正是我想要的。第二个扇区有 512 字节 stage1 代码(包括 magicnumber,加载得很好)和 512 个 stage2 代码。

但我认为我的问题是将扇区加载到内存中并跳入其中。我的代码有问题吗?

Stage1.asm

BITS 16
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096

mov ax, 07C0h ;Set data segment to where we're loaded
mov ds, ax

mov si,s_version
call print_string

; ## Load stage2
mov si,s_loading
call print_string

xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx

;read 2nd sector
mov ah,02h
mov al,1 ;read 1
mov ch,0 ;on track 0
mov cl,2 ;2nd sector
mov dh,0 ;head 1
mov dl,0 ;from floppy a

mov bx,09C0h;destination segment
mov es,bx

mov bx,0 ;destination offset

int 13h ;<-- Fails right here

mov si,s_sector
call print_string

;print number of read sectors
add ax, 48
mov ah, 0Eh
int 10h
mov al, 21
mov ah, 0Eh
int 10h

;print the sector's magicnumber (debugging purposes)
mov al, [09C0h+511]
int 10h

xor ax,ax
int 16h

mov si,s_jumping
call print_string

call word 09C0h:0000h

; #### print a string from si
print_string:
push ax
push bx
mov ah, 0Eh
.repeat:
lodsb
cmp al, 0
je .exit
int 10h
jmp .repeat
.exit:
pop bx
pop ax
ret
; ****

; #### define strings
s_version db 'VeOS 0.0.0.1',10,13,0
s_loading db 'Loading Stage2...',10,13,0
s_sector db 'Loading sector...',10,13,0
s_jumping db 'Passing control to Stage2.',10,13,0
; ****

;fillup with zeros
times 510-($-$$) db 0
;boot signature
dw 0xAA55

stage2.asm

BITS 16
start:
mov ax, 09C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096

mov ax, 09C0h ;Set data segment to where we're loaded
mov ds, ax

mov ah, 0Eh
mov al, 21 ;"!"
int 10h

mov ah, 00h
int 16h

jmp $


times 511-($-$$) db 0
;Magicnumber for debugging
db 0x41

我彻底用谷歌搜索,没有找到任何具体描述如何将扇区加载到内存中并跳入其中的内容。我的程序连第二个扇区的 Magicnumber 都找不到。

如果只是地址计算错误,那就太好了。

更新:当前源代码,锁定的行已标记。出于纯粹的偏执,我将所有 4 个主要寄存器都设置为 0。

更新2:又是当前版本。在设置寄存器和发出 int 13h 之间没有完成任何事情。

最佳答案

更新:除了以下内容之外,加载时您还会覆盖堆栈!

您的堆栈位于07C0h + 288 : 4096这是 08E0h:1000h = 09E0h:0000h ,您正在阅读 09C0h:0000 ,并向前 512 个字节(以 09E0h:0000h 结尾)覆盖堆栈。要么移动你的堆栈,要么读到其他地方。请参阅memory map from osdev.org寻求灵感。

恐怕我不知道一个好的逐步调试器。我刚刚放置了一个 jmp $-2代码中的指令并使用 QEMU 内置调试​​器在适当的点执行“信息寄存器”。我认为 Bochs 可能也有类似的东西。

我看到的三(2.5)件事(尽管可能还有更多):

;read 2nd sector
mov ah,02h
mov al,1 ;read 1
mov ch,0 ;on track 0
mov cl,1 ;2nd sector
mov dl,0 ;from floppy a
mov bx,09C0h ;destination
mov es,bx
int 13h
  • 你要离开bx09c0h ,因此它将读取为 09C0h:09C0h而不是09C0h:0000h .
  • 您说您正在从第二个扇区 ( cl = 1 ) 读取内容,但实际上您正在从第一个扇区读取!。请参阅Ralph Brown .
  • 您没有设置dh (头)。在 Bochs 中可能没问题,但我记不起除了 dl being set to the drive number 之外还保证了哪些初始条件。 .

如果您想比较/复制,这是我用于小型测试内核的引导加载程序(部分取自 osdev.org 的各个部分,可能有我引入的错误,所以要小心)。 (我保留 dl 不变,因为它包含启动驱动器,因此您不必对其进行硬编码)。

        bits 16
org 0x7c00

Start: jmp EntryPoint

PrintString16:
pusha
.PrintLoop:
lodsb
or al, al
jz .PrintDone
mov ah, 0xe
int 0x10
jmp .PrintLoop
.PrintDone:
popa
ret

EntryPoint:
xor ax, ax
mov ss, ax
mov ds, ax
mov sp, 0x7c00
.DiskReset:
mov ah, 0
int 0x13
jc .DiskReset
mov ax, 0x50 ; load to 0x500 linear address. It has unused space up to 0x7bff
mov es, ax
xor bx, bx
mov ax, 0x023B ; count = 0x3b = 59, the maximum (while still leaving soom room for the stack and the boot sector code we're currently running)
mov cx, 0x0002
xor dh, dh ; leave dl intact
int 0x13
jnc .ReadDone
mov si, ReadError
call PrintString16
jmp .DiskReset
.ReadDone:
;jmp 0x50:0x0 ;jump to stage 2 loaded at 0x500

cli
xor ax, ax
mov ds, ax
mov es, ax
mov ax, 0x9000
mov ss, ax
mov sp, 0xffff
sti

mov si, HelloMsg
call PrintString16

; Disable interrupts until safely in protected mode
cli

; Install GDT
lgdt [toc]

; Enable A20
mov al, 0xdd
out 0x64, al

mov si, GoPMode
call PrintString16

; enable protected mode
mov eax, cr0
or eax, 1
mov cr0, eax

jmp 0x8:PmodeStart
bits 32
PmodeStart:
; setup stack and datasegments
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax

; Setup stack at 0x90000
mov esp, 0x90000

; Jump to C-code
jmp 0x8:0x500

; Reboot if C-code returns
Reboot:
mov word [0x472], 0x1234
jmp 0x8:0xffff0


ReadError db 'Read error - retrying...', 13, 10, 0
HelloMsg db 'Loading...',0
GoPMode db 'Entering protected mode..',0
gdt_data:
dd 0 ; null descriptor
dd 0

; gdt code: ; code descriptor
dw 0FFFFh ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high

; gdt data: ; data descriptor
dw 0FFFFh ; limit low (Same as code)10:56 AM 7/8/2007
dw 0 ; base low
db 0 ; base middle
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high

end_of_gdt:
toc:
dw end_of_gdt - gdt_data - 1 ; limit (Size of GDT)
dd gdt_data ; base of GDT


times 510 - ($-$$) db 0 ; pad to 512 bytees, will also warn if we exceed 512 bytes

dw 0xAA55 ; boot signature

关于assembly - 加载引导加载程序的第二阶段并启动它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7716427/

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