[英]How to load a kernel from disk with BIOS int 13h in NASM assembly?
我已經堅持了好幾個星期了,並且不知道我哪里出錯了,因為NASM沒有給我任何錯誤。 由於評論,代碼非常自我解釋。
這是從BIOS加載的代碼
;--------------------------------------------
; 'boot.asm'
; loaded from BIOS
[org 0x7C00]
[bits 16]
;--------------------------------------------
main:
mov ah, 0x0E ; print function
mov al, '.' ; ascii char
int 0x10 ; IO int
resetdisk:
mov ah, 0x00 ; reset function
mov dl, 0x00 ; drive
int 0x13 ; disk int
jc resetdisk
readdisk:
mov bx, 0x8000 ; segment
mov es, bx
mov bx, 0x0000 ; offset
mov ah, 0x02 ; read function
mov al, 0x03 ; sectors
mov ch, 0x00 ; cylinder
mov cl, 0x02 ; sector
mov dh, 0x00 ; head
mov dl, 0x00 ; drive
int 0x13 ; disk int
jc readdisk
jmp [es:bx] ; buffer
;--------------------------------------------
times 510 - ($ - $$) db 0x00
db 0x55, 0xAA
這是應該(但未加載)的代碼
;--------------------------------------------
; 'load.asm'
; loaded from 'boot.asm'
[org 0x8000]
[bits 16]
;--------------------------------------------
main:
mov ah, 0x0E ; print function
mov al, '.' ; ascii char
int 0x10 ; IO int
jmp $ ; hang
任何幫助將不勝感激。
帕特里克
jmp [es:bx]
不會跳轉到地址es:bx
。 此命令幾乎跳轉到es:bx
存儲在單詞中的地址。 這就是為什么許多較舊的匯編程序使你將這種指令拼寫為jmp word ptr [es:bx]
或甚至是jmp near ptr [es:bx]
; 這種方式更清楚將會發生什么。 您可能想要的是遠離固定位置:
; jmp far 8000:0000
db 0eah
dw 00000h ; offset
dw 08000h ; segment
如果你想跳轉到es:bx
,請使用retf
:
push es
push bx
retf
我不確定你要用代碼實現什么,但如果我理解正確,你想從磁盤讀取幾個扇區到0x8000位置,然后執行該代碼?
如果是這種情況,那么你將不得不明確地向該特定位置發出CALL / JUMP。 BIOS不會為您調用該代碼。 在啟動時,初始化BIOS后,它會將指令指針IP設置為地址0x7c00。 然后cpu將開始按順序執行代碼,因此,如果沒有JMP / CALL到0x8000,它將不會執行0x8000處的代碼,直到它執行0x7c00到0x8000之間的每個內存地址等。
所以解決方案是在你的jc readdisk之后有一個jmp或call指令。
如果我的理解不正確,那么我道歉。 希望這可以幫助。
INT13的一個問題是磁頭和磁道編號從0開始,但扇區編號由於某種原因從1開始。您可能會檢查您的扇區寫入實用程序是否符合此編號方案。
問題:
我不知道你是否正在使用軟盤來啟動你的操作系統,但如果你正在使用,我建議你在ORG和Bits聲明之后聲明一些事情,看看(它們非常重要):
JMP short main ; Jump past disk description section
NOP ; Pad out before disk description
; ------------------------------------------------------------------
; Disk description table, to make it a valid floppy
; Note: some of these values are hard-coded in the source!
; Values are those used by IBM for 1.44 MB, 3.5 diskette
OEMLabel db "BERL OS" ; Disk label - 8 chars
BytesPerSector dw 512 ; Bytes per sector
SectorsPerCluster db 1 ; Sectors per cluster
ReservedForBoot dw 1 ; Reserved sectors for boot record
NumberOfFats db 2 ; Number of copies of the FAT
RootDirEntries dw 224 ; Number of entries in root dir
LogicalSectors dw 2880 ; Number of logical sectors
MediumByte db 0F0h ; Medium descriptor byte
SectorsPerFat dw 9 ; Sectors per FAT
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
Sides dw 2 ; Number of sides/heads
HiddenSectors dd 0 ; Number of hidden sectors
LargeSectors dd 0 ; Number of LBA sectors
DriveNo dw 0 ; Drive No: 0
Signature db 41 ; Drive signature: 41 for floppy
VolumeID dd 00000000h ; Volume ID: any number
VolumeLabel db "BERL OS" ; Volume Label: any 11 chars
FileSystem db "FAT12" ; File system type: don't change!
; End of the disk description table
; ------------------------------------------------------------------
這個是個好主意。
問候。
我不確定為什么代碼不起作用,因為我無法檢查整個環境(磁盤,內存轉儲等)......但我能說的是......代碼錯了。 你正在加載第二個程序,而不是0x8000
(這是使用0rg 0x8000
的點嗎?),但是在0x80000
。
原因是,您正在使用段:偏移尋址方式錯誤,地址0x8000:0x0000
被解析為線性地址0x80000
,因為段值向左移位4位,然后加到偏移量。
要解決此問題,您應該查看內存轉儲並查看程序是否按預期工作....或者您正在加載磁盤的錯誤扇區。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.