【发布时间】:2015-02-26 04:17:24
【问题描述】:
我正在尝试完成我的操作系统项目的第一部分。这部分涉及通过模拟器 qemu 运行引导加载程序程序集文件,并让该引导加载程序加载并执行任意数量(希望超过 512 字节)的内核。
我在完成此操作时遇到了问题,我无法准确指出,但我可能已将其缩小到两件事。
第一,我缺乏对内存地址的理解,以及使用堆栈来加载我的内核并执行它。
二,我将我的两个文件(引导加载程序和内核文件)错误地复制到软盘映像中。
这是我第一部分的代码,即引导加载程序。 boot.asm
;;;
;;; Header information
;;;
BITS 16
ORG 0
START: jmp MAIN
;;;
;;; Parameters
;;;
SectorsPerTrack dw 18
HeadsPerTrack dw 2
BytesPerSector dw 512
DriveNumber db 0
;;;
;;; Variables
;;;
absSector db 0x00
absHead db 0x00
absTrack db 0x00
;;;
;;; Print function
;;; Input:
;;; - SI => Null terminated string
;;; Output:
;;; - None
;;;
PRINT:
lodsb
or al, al
jz PRINTDONE
int 10h
jmp PRINT
PRINTDONE:
ret
;;;
;;; LBA to CHS
;;; Input:
;;; - AX => LBA address
;;; - SectorsPerTrack => Sectors per track
;;; - HeadsPerTrack => Heads per track
;;; Output:
;;; - absSector => CHS sector address
;;; - absHead => CHS head address
;;; - absTrack => CHS track address
;;;
LBACHS:
xor dx, dx
div WORD [SectorsPerTrack]
inc dl
mov BYTE [absSector], dl
xor dx, dx
div WORD [HeadsPerTrack]
mov BYTE [absHead], dl
mov BYTE [absTrack], al
ret
;;;
;;; Read sectors
;;; Input:
;;; - CX => Number of sectors to read
;;; - AX => LBA address to start from
;;; Output:
;;; - ES:BX => Loaded sector address:offset
;;;
READSECTORS:
READSECTORSMAIN:
mov di, 0x0005
READSECTORSLOOP:
push ax
push bx
push cx
call LBACHS
mov ah, 0x02
mov al, 0x01
mov ch, BYTE [absTrack]
mov cl, BYTE [absSector]
mov dh, BYTE [absHead]
mov dl, BYTE [DriveNumber]
int 0x13
jnc READSECTORSDONE
xor ax, ax
int 0x13
dec di
pop cx
pop bx
pop ax
jnz READSECTORSLOOP
int 0x18
READSECTORSDONE:
pop cx
pop bx
pop ax
add bx, WORD [BytesPerSector]
inc ax
loop READSECTORSMAIN
ret
;;;
;;; Main section
;;;
MAIN:
cli ; Move registers for offset of BIOS 0x07C0 load point
mov ax, 0x07C0 ; OFFSET
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, 0x0000 ; Initialize the stack
mov ss, ax
mov sp, 0xFFFF
sti
mov ax, 0x01 ; LBA number 1 for sector number 2
mov cx, 0x01 ; Read one sector from the floppy disk
call READSECTORS ; Call the read sectors function
jmp [es:bx] ; Address ES offset BX returned from read sectors
;;;
;;; Footer information
;;;
times 510-($-$$) db 0
dw 0xAA55
这是我的第二部分代码,内核。 kernel.asm
BITS 16
ORG 0
START: jmp MAIN
message db 'Kernel Loaded', 13, 10, 0
PRINT:
lodsb
or al, al
jz PRINTDONE
int 10h
jmp PRINT
PRINTDONE:
ret
MAIN:
mov si, message
call PRINT
jmp $
times 510-($-$$) db 0
dw 0xAA55
这是我在 Ubuntu Desktop x64 上运行的编译、复制和模拟文件及其二进制文件的方式。
nasm -f bin -o boot.bin boot.asm
nasm -f bin -o kernel.bin kernel.asm
cat kernel.bin >> boot.bin
dd status=noxfer conv=notrunc if=boot.bin of=floppy.fda
qemu-system-x86_64 -fda floppy.fda
如果您尝试运行、编译和模拟它。你会看到内核永远不会被加载,也不会打印出它应该加载的内容。
我不知道除此之外该怎么做,我尝试研究如何将第二阶段引导加载程序正确加载到软盘映像中,但未能成功。在从引导加载程序加载内核时我可能做错了什么,我也遇到了障碍。
如果您有任何建议或修复,我们将不胜感激。另外,如果我的代码中有任何错误,或者您需要澄清任何内容以便更好地帮助我,请不要犹豫。
编辑
如果您需要参考,这里是我用来创建此代码的教程。
http://www.brokenthorn.com/Resources/
【问题讨论】:
标签: assembly kernel bootloader