为什么用 int 13h 读取扇区后 int 10h 不起作用?
Why does int 10h not work after reading sectors with int 13h?
我想写一个简单的bootloader。但是,从磁盘读取 2 个扇区后,我的引导扇区无法打印带有 int 10h, ah=0Eh
的字符串
它在我调用 int 13h 之前有效,ah=02h
我的代码:
;-------------------------------------------------------------------------------
; boot.asm - First boot sector
;-------------------------------------------------------------------------------
org 0x7c00
bits 16
jmp word _start
;-------------------------------------------------------------------------------
; BIOS Parameter Block (FAT32)
;-------------------------------------------------------------------------------
BS_OEMName: db "TestOS "
BPB_BytesPerSector: dw 512
BPB_SectorsPerCluster: db 1
BPB_ReservedSectors: dw 4
BPB_FATCount: db 2
BPB_RootEntryCount: dw 0
BPB_TotalSectors16: dw 0
BPB_Media: db 0xf0
BPB_FATSize16: dw 0
BPB_SectorsPerTrack: dw 18
BPB_HeadCount: dw 2
BPB_HiddenSectors: dd 0
BPB_TotalSectors32: dd 2880
BPB_FATSize32: dd 23
BPB_ExtendedFlags: dw 0x0000
BPB_FileSystemVersion: dw 0
BPB_RootCluster: dd 2
BPB_FSInfo: dw 3
BPB_BackupBootSector: dw 0
BPB_Reserved: times 12 db 0
BS_DriveNum: db 0x00
BS_Reserved1: db 0x0
BS_BootSignature: db 0x29
BS_VolumeID: dd 0x12345678
BS_VolumeLabel: db "TestOS "
BS_FileSystemType: db "FAT32 "
;-------------------------------------------------------------------------------
_start:
; Initialize segment registers and set up stack at 0x7c00 (grows downwards)
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7a00
sti
; Save drive number in DL
mov [BS_DriveNum], dl
; Copy this boot sector from 0x7c00 to 0x7a00
mov si, 0x7c00
mov di, 0x7a00
mov cx, 512
cld
rep movsb
; Jump to the new location
jmp 0x0000:(_continue - 0x200)
_continue:
; Reset boot disk (try it 3 times before error message is printed)
mov cx, 4
_reset:
sub cx, 1
cmp cx, 0
je _error
mov ah, 0
mov dl, [BS_DriveNum]
int 0x13
jc _reset
; Load second boot sector into memory at 0x7c00 (try it 3 times before error message is printed)
mov cx, 4
_load:
sub cx, 1
cmp cx, 0
je _error
mov ah, 0x02
mov al, 2
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, [BS_DriveNum]
mov bx, 0x7c00
; IT STILL WORKS HERE <--------
int 0x13
; IT DOESN'T WORK ANYMORE <--------
jc _load
mov si, error_msg
call print
; Jump to the second boot sector
; End of program
_end:
hlt
jmp _end
_error:
mov si, error_msg
call print
jmp _end
;-------------------------------------------------------------------------------
; Prints a zero-terminated string onto the screen
; SI = string to write
;-------------------------------------------------------------------------------
print:
pusha
.print_lbl:
lodsb
cmp al, 0
je .finished
mov ah, 0x0e
mov bl, 0
int 0x10
jmp .print_lbl
.finished:
popa
ret
;-------------------------------------------------------------------------------
error_msg: db "Operating system not found", 0xa, 0xd, "Press Ctrl+Alt+Del to reboot", 0x0
; Fill the rest of the 512 bytes with 0, byte 510 and 511
; contains 0xaa55 (boot signature for BIOS)
times 510 - ($ - $$) db 0
dw 0xaa55
我搜索 google 来解决这个问题,但以前没有其他人遇到过这个问题。
我用bochs调试发现...
我可以通过将字符写入 b800:0000
来在屏幕上打印一些东西
2 个扇区读取正确。我用 bochs 将内存转储到 0x7c00,它显示了正确的值
我的 bootloader 没有死循环,因为用 bochs 调试显示它在读取 2 个扇区后执行指令
我不知道如何解决这个问题。谁能帮帮我?
TL;DR 正如@jester 所指出的,您的代码的主要问题是您使用了 org 0x7c00
,这意味着所有绝对引用都是相对于 0x7c00 的。当您复制到 0x7a00 时,您生成的代码仍然引用 0x7c?地址。当您覆盖 0x7c00 处的内存时,对 error_msg
、BS_DriveNum
等标签的引用是针对已被替换的数据,并且失败。
有几种方法可以解决此问题:
最简单的解决方法是确保在跳转到 _continue
之前执行的代码是位置独立的(目前是)并将 org 0x7c00
更改为 org 0x7a00
。您还需要将 jmp 0x0000:(_continue - 0x200)
更改为 jmp 0x0000:_continue
使用 org 0x0000
并加载具有适当值 0x07c0 和 0x07a0 的段,具体取决于您需要访问哪个段。通过具有 0x0000 的原点,生成的代码和数据是相对于段的开头(您可以更改),而不是内存的开头。
您可以使用 NASM 的 segment
指令使用 vstart
(虚拟内存地址)选项更改代码的原点。您可以使用带有 start
(加载内存地址)选项的 segment
指令来更改放置引导签名的文件偏移量。
您的代码中的其他问题:
- 正如@RossRidge 指出的那样,如果在磁盘操作后发生错误(进位标志设置),它将进入无限循环,因为您使用 CX 寄存器,它也用于执行 Int 13h/AH=02h。您还使用 CX 进行磁盘重置重试计数器和磁盘操作。
- 一般来说,您可以避免检查 Int 13h/AH=0 磁盘重置上的任何错误,并删除该操作的重试循环。如果先前的磁盘操作失败,您应该只需要重置磁盘。重试磁盘操作 3 次在真实硬件上是正常的。
- 当您的代码成功将新代码和数据读取到 0x7c00 时,它会显示一条错误消息。它应该会打印一条磁盘读取成功的消息。
代码使用 选项 1:
;-------------------------------------------------------------------------------
; boot.asm - First boot sector
;-------------------------------------------------------------------------------
org 0x7a00
bits 16
jmp word _start
;-------------------------------------------------------------------------------
; BIOS Parameter Block (FAT32)
;-------------------------------------------------------------------------------
BS_OEMName: db "TestOS "
BPB_BytesPerSector: dw 512
BPB_SectorsPerCluster: db 1
BPB_ReservedSectors: dw 4
BPB_FATCount: db 2
BPB_RootEntryCount: dw 0
BPB_TotalSectors16: dw 0
BPB_Media: db 0xf0
BPB_FATSize16: dw 0
BPB_SectorsPerTrack: dw 18
BPB_HeadCount: dw 2
BPB_HiddenSectors: dd 0
BPB_TotalSectors32: dd 2880
BPB_FATSize32: dd 23
BPB_ExtendedFlags: dw 0x0000
BPB_FileSystemVersion: dw 0
BPB_RootCluster: dd 2
BPB_FSInfo: dw 3
BPB_BackupBootSector: dw 0
BPB_Reserved: times 12 db 0
BS_DriveNum: db 0x00
BS_Reserved1: db 0x0
BS_BootSignature: db 0x29
BS_VolumeID: dd 0x12345678
BS_VolumeLabel: db "TestOS "
BS_FileSystemType: db "FAT32 "
;-------------------------------------------------------------------------------
_start:
; Initialize segment registers and set up stack at 0x7c00 (grows downwards)
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7a00
sti
; Save drive number in DL
mov [BS_DriveNum], dl
; Copy this boot sector from 0x7c00 to 0x7a00
mov si, 0x7c00
mov di, 0x7a00
mov cx, 512
cld
rep movsb
; Jump to the new location
jmp 0x0000:(_continue)
_continue:
; Reset boot disk (try it 3 times before error message is printed)
mov si, 4
_reset:
mov ah, 0
mov dl, [BS_DriveNum]
int 0x13
; Load second boot sector into memory at 0x7c00 (try it 3 times before error message is printed)
_load:
dec si
je _error
mov ah, 0x02
mov al, 2
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, [BS_DriveNum]
mov bx, 0x7c00
int 0x13
jc _load
mov si, loaded_msg
call print
; Jump to the second boot sector
jmp 0x0000:0x7c00
; End of program
_end:
hlt
jmp _end
_error:
mov si, error_msg
call print
jmp _end
;-------------------------------------------------------------------------------
; Prints a zero-terminated string onto the screen
; SI = string to write
;-------------------------------------------------------------------------------
print:
pusha
.print_lbl:
lodsb
cmp al, 0
je .finished
mov ah, 0x0e
mov bl, 0
int 0x10
jmp .print_lbl
.finished:
popa
ret
;-------------------------------------------------------------------------------
loaded_msg: db "Operating system loaded", 0xa, 0xd, 0x0
error_msg: db "Operating system not found", 0xa, 0xd, "Press Ctrl+Alt+Del to reboot", 0x0
; Fill the rest of the 512 bytes with 0, byte 510 and 511
; contains 0xaa55 (boot signature for BIOS)
times 510 - ($ - $$) db 0
dw 0xaa55
代码使用选项 2:
;-------------------------------------------------------------------------------
; boot.asm - First boot sector
;-------------------------------------------------------------------------------
org 0x00
bits 16
jmp word _start
;-------------------------------------------------------------------------------
; BIOS Parameter Block (FAT32)
;-------------------------------------------------------------------------------
BS_OEMName: db "TestOS "
BPB_BytesPerSector: dw 512
BPB_SectorsPerCluster: db 1
BPB_ReservedSectors: dw 4
BPB_FATCount: db 2
BPB_RootEntryCount: dw 0
BPB_TotalSectors16: dw 0
BPB_Media: db 0xf0
BPB_FATSize16: dw 0
BPB_SectorsPerTrack: dw 18
BPB_HeadCount: dw 2
BPB_HiddenSectors: dd 0
BPB_TotalSectors32: dd 2880
BPB_FATSize32: dd 23
BPB_ExtendedFlags: dw 0x0000
BPB_FileSystemVersion: dw 0
BPB_RootCluster: dd 2
BPB_FSInfo: dw 3
BPB_BackupBootSector: dw 0
BPB_Reserved: times 12 db 0
BS_DriveNum: db 0x00
BS_Reserved1: db 0x0
BS_BootSignature: db 0x29
BS_VolumeID: dd 0x12345678
BS_VolumeLabel: db "TestOS "
BS_FileSystemType: db "FAT32 "
;-------------------------------------------------------------------------------
_start:
; Initialize segment registers and set up stack at 0x7c00 (grows downwards)
cli
mov ax, 0x7c0
mov ds, ax
mov ss, ax
xor ax, ax
mov sp, 0x7a00
sti
; Save drive number in DL
mov [BS_DriveNum], dl
; Copy this boot sector from 0x7c00 to 0x7a00
mov ax, 0x7a0
mov es, ax
xor si, si
xor di, di
mov cx, 512
cld
rep movsb
; Jump to the new location
jmp 0x07a0:(_continue)
_continue:
mov ax, 0x7c0
mov es, ax
mov ax, 0x7a0
mov ds, ax
; Load second boot sector into memory at 0x7c00 (try it 3 times before error message is printed)
mov si, 4
; Reset boot disk
_reset:
mov ah, 0
mov dl, [BS_DriveNum]
int 0x13
_load:
dec si
je _error
mov ah, 0x02
mov al, 2
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, [BS_DriveNum]
xor bx, bx
int 0x13
jc _load
mov si, loaded_msg
call print
; Jump to the second boot sector
jmp 0x0000:0x7c00
; End of program
_end:
hlt
jmp _end
_error:
mov si, error_msg
call print
jmp _end
;-------------------------------------------------------------------------------
; Prints a zero-terminated string onto the screen
; SI = string to write
;-------------------------------------------------------------------------------
print:
pusha
.print_lbl:
lodsb
cmp al, 0
je .finished
mov ah, 0x0e
mov bl, 0
int 0x10
jmp .print_lbl
.finished:
popa
ret
;-------------------------------------------------------------------------------
loaded_msg: db "Operating system loaded", 0xa, 0xd, 0x0
error_msg: db "Operating system not found", 0xa, 0xd, "Press Ctrl+Alt+Del to reboot", 0x0
; Fill the rest of the 512 bytes with 0, byte 510 and 511
; contains 0xaa55 (boot signature for BIOS)
times 510 - ($ - $$) db 0
dw 0xaa55
代码使用选项 3:
BOOT_ORG EQU 0x7c00
;-------------------------------------------------------------------------------
; boot.asm - First boot sector
;-------------------------------------------------------------------------------
org BOOT_ORG
bits 16
jmp word _start
;-------------------------------------------------------------------------------
; BIOS Parameter Block (FAT32)
;-------------------------------------------------------------------------------
BS_OEMName: db "TestOS "
BPB_BytesPerSector: dw 512
BPB_SectorsPerCluster: db 1
BPB_ReservedSectors: dw 4
BPB_FATCount: db 2
BPB_RootEntryCount: dw 0
BPB_TotalSectors16: dw 0
BPB_Media: db 0xf0
BPB_FATSize16: dw 0
BPB_SectorsPerTrack: dw 18
BPB_HeadCount: dw 2
BPB_HiddenSectors: dd 0
BPB_TotalSectors32: dd 2880
BPB_FATSize32: dd 23
BPB_ExtendedFlags: dw 0x0000
BPB_FileSystemVersion: dw 0
BPB_RootCluster: dd 2
BPB_FSInfo: dw 3
BPB_BackupBootSector: dw 0
BPB_Reserved: times 12 db 0
BS_DriveNum: db 0x00
BS_Reserved1: db 0x0
BS_BootSignature: db 0x29
BS_VolumeID: dd 0x12345678
BS_VolumeLabel: db "TestOS "
BS_FileSystemType: db "FAT32 "
;-------------------------------------------------------------------------------
_start:
; Initialize segment registers and set up stack at 0x7c00 (grows downwards)
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7a00
sti
; Save drive number in DL
mov [BS_DriveNum], dl
; Copy this boot sector from 0x7c00 to 0x7a00
mov si, 0x7c00
mov di, 0x7a00
mov cx, 512
cld
rep movsb
; Jump to the new location
jmp 0x0000:_continue
; The code and data past this point will have an origin point (vstart)
; relative to 0x7a00. Align=1 for no padding.
section bootreloc vstart=(($-$$)+0x7a00) align=1
_continue:
; Load second boot sector into memory at 0x7c00 (try it 3 times before error message is printed)
mov si, 4
; Reset boot disk
_reset:
mov ah, 0
mov dl, [BS_DriveNum]
int 0x13
_load:
dec si
jz _error
mov ah, 0x02
mov al, 2
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, [BS_DriveNum]
mov bx, 0x7c00
int 0x13
jc _load
mov si, loaded_msg
call print
; Jump to the second boot sector
jmp 0x0000:0x7c00
; End of program
_end:
hlt
jmp _end
_error:
mov si, error_msg
call print
jmp _end
;-------------------------------------------------------------------------------
; Prints a zero-terminated string onto the screen
; SI = string to write
;-------------------------------------------------------------------------------
print:
pusha
.print_lbl:
lodsb
cmp al, 0
je .finished
mov ah, 0x0e
mov bl, 0
int 0x10
jmp .print_lbl
.finished:
popa
ret
;-------------------------------------------------------------------------------
loaded_msg: db "Operating system loaded", 0xa, 0xd, 0x0
error_msg: db "Operating system not found", 0xa, 0xd, "Press Ctrl+Alt+Del to reboot", 0x0
; Set position to 510 bytes from BOOT_ORG so that bytes 510 and 511
; in te disk image will contain 0xaa55 (boot signature for BIOS)
section bootsig start=(BOOT_ORG+510)
dw 0xaa55
我想写一个简单的bootloader。但是,从磁盘读取 2 个扇区后,我的引导扇区无法打印带有 int 10h, ah=0Eh
的字符串它在我调用 int 13h 之前有效,ah=02h
我的代码:
;-------------------------------------------------------------------------------
; boot.asm - First boot sector
;-------------------------------------------------------------------------------
org 0x7c00
bits 16
jmp word _start
;-------------------------------------------------------------------------------
; BIOS Parameter Block (FAT32)
;-------------------------------------------------------------------------------
BS_OEMName: db "TestOS "
BPB_BytesPerSector: dw 512
BPB_SectorsPerCluster: db 1
BPB_ReservedSectors: dw 4
BPB_FATCount: db 2
BPB_RootEntryCount: dw 0
BPB_TotalSectors16: dw 0
BPB_Media: db 0xf0
BPB_FATSize16: dw 0
BPB_SectorsPerTrack: dw 18
BPB_HeadCount: dw 2
BPB_HiddenSectors: dd 0
BPB_TotalSectors32: dd 2880
BPB_FATSize32: dd 23
BPB_ExtendedFlags: dw 0x0000
BPB_FileSystemVersion: dw 0
BPB_RootCluster: dd 2
BPB_FSInfo: dw 3
BPB_BackupBootSector: dw 0
BPB_Reserved: times 12 db 0
BS_DriveNum: db 0x00
BS_Reserved1: db 0x0
BS_BootSignature: db 0x29
BS_VolumeID: dd 0x12345678
BS_VolumeLabel: db "TestOS "
BS_FileSystemType: db "FAT32 "
;-------------------------------------------------------------------------------
_start:
; Initialize segment registers and set up stack at 0x7c00 (grows downwards)
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7a00
sti
; Save drive number in DL
mov [BS_DriveNum], dl
; Copy this boot sector from 0x7c00 to 0x7a00
mov si, 0x7c00
mov di, 0x7a00
mov cx, 512
cld
rep movsb
; Jump to the new location
jmp 0x0000:(_continue - 0x200)
_continue:
; Reset boot disk (try it 3 times before error message is printed)
mov cx, 4
_reset:
sub cx, 1
cmp cx, 0
je _error
mov ah, 0
mov dl, [BS_DriveNum]
int 0x13
jc _reset
; Load second boot sector into memory at 0x7c00 (try it 3 times before error message is printed)
mov cx, 4
_load:
sub cx, 1
cmp cx, 0
je _error
mov ah, 0x02
mov al, 2
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, [BS_DriveNum]
mov bx, 0x7c00
; IT STILL WORKS HERE <--------
int 0x13
; IT DOESN'T WORK ANYMORE <--------
jc _load
mov si, error_msg
call print
; Jump to the second boot sector
; End of program
_end:
hlt
jmp _end
_error:
mov si, error_msg
call print
jmp _end
;-------------------------------------------------------------------------------
; Prints a zero-terminated string onto the screen
; SI = string to write
;-------------------------------------------------------------------------------
print:
pusha
.print_lbl:
lodsb
cmp al, 0
je .finished
mov ah, 0x0e
mov bl, 0
int 0x10
jmp .print_lbl
.finished:
popa
ret
;-------------------------------------------------------------------------------
error_msg: db "Operating system not found", 0xa, 0xd, "Press Ctrl+Alt+Del to reboot", 0x0
; Fill the rest of the 512 bytes with 0, byte 510 and 511
; contains 0xaa55 (boot signature for BIOS)
times 510 - ($ - $$) db 0
dw 0xaa55
我搜索 google 来解决这个问题,但以前没有其他人遇到过这个问题。
我用bochs调试发现...
我可以通过将字符写入 b800:0000
来在屏幕上打印一些东西
2 个扇区读取正确。我用 bochs 将内存转储到 0x7c00,它显示了正确的值
我的 bootloader 没有死循环,因为用 bochs 调试显示它在读取 2 个扇区后执行指令
我不知道如何解决这个问题。谁能帮帮我?
TL;DR 正如@jester 所指出的,您的代码的主要问题是您使用了 org 0x7c00
,这意味着所有绝对引用都是相对于 0x7c00 的。当您复制到 0x7a00 时,您生成的代码仍然引用 0x7c?地址。当您覆盖 0x7c00 处的内存时,对 error_msg
、BS_DriveNum
等标签的引用是针对已被替换的数据,并且失败。
有几种方法可以解决此问题:
最简单的解决方法是确保在跳转到
_continue
之前执行的代码是位置独立的(目前是)并将org 0x7c00
更改为org 0x7a00
。您还需要将jmp 0x0000:(_continue - 0x200)
更改为jmp 0x0000:_continue
使用
org 0x0000
并加载具有适当值 0x07c0 和 0x07a0 的段,具体取决于您需要访问哪个段。通过具有 0x0000 的原点,生成的代码和数据是相对于段的开头(您可以更改),而不是内存的开头。您可以使用 NASM 的
segment
指令使用vstart
(虚拟内存地址)选项更改代码的原点。您可以使用带有start
(加载内存地址)选项的segment
指令来更改放置引导签名的文件偏移量。
您的代码中的其他问题:
- 正如@RossRidge 指出的那样,如果在磁盘操作后发生错误(进位标志设置),它将进入无限循环,因为您使用 CX 寄存器,它也用于执行 Int 13h/AH=02h。您还使用 CX 进行磁盘重置重试计数器和磁盘操作。
- 一般来说,您可以避免检查 Int 13h/AH=0 磁盘重置上的任何错误,并删除该操作的重试循环。如果先前的磁盘操作失败,您应该只需要重置磁盘。重试磁盘操作 3 次在真实硬件上是正常的。
- 当您的代码成功将新代码和数据读取到 0x7c00 时,它会显示一条错误消息。它应该会打印一条磁盘读取成功的消息。
代码使用 选项 1:
;-------------------------------------------------------------------------------
; boot.asm - First boot sector
;-------------------------------------------------------------------------------
org 0x7a00
bits 16
jmp word _start
;-------------------------------------------------------------------------------
; BIOS Parameter Block (FAT32)
;-------------------------------------------------------------------------------
BS_OEMName: db "TestOS "
BPB_BytesPerSector: dw 512
BPB_SectorsPerCluster: db 1
BPB_ReservedSectors: dw 4
BPB_FATCount: db 2
BPB_RootEntryCount: dw 0
BPB_TotalSectors16: dw 0
BPB_Media: db 0xf0
BPB_FATSize16: dw 0
BPB_SectorsPerTrack: dw 18
BPB_HeadCount: dw 2
BPB_HiddenSectors: dd 0
BPB_TotalSectors32: dd 2880
BPB_FATSize32: dd 23
BPB_ExtendedFlags: dw 0x0000
BPB_FileSystemVersion: dw 0
BPB_RootCluster: dd 2
BPB_FSInfo: dw 3
BPB_BackupBootSector: dw 0
BPB_Reserved: times 12 db 0
BS_DriveNum: db 0x00
BS_Reserved1: db 0x0
BS_BootSignature: db 0x29
BS_VolumeID: dd 0x12345678
BS_VolumeLabel: db "TestOS "
BS_FileSystemType: db "FAT32 "
;-------------------------------------------------------------------------------
_start:
; Initialize segment registers and set up stack at 0x7c00 (grows downwards)
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7a00
sti
; Save drive number in DL
mov [BS_DriveNum], dl
; Copy this boot sector from 0x7c00 to 0x7a00
mov si, 0x7c00
mov di, 0x7a00
mov cx, 512
cld
rep movsb
; Jump to the new location
jmp 0x0000:(_continue)
_continue:
; Reset boot disk (try it 3 times before error message is printed)
mov si, 4
_reset:
mov ah, 0
mov dl, [BS_DriveNum]
int 0x13
; Load second boot sector into memory at 0x7c00 (try it 3 times before error message is printed)
_load:
dec si
je _error
mov ah, 0x02
mov al, 2
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, [BS_DriveNum]
mov bx, 0x7c00
int 0x13
jc _load
mov si, loaded_msg
call print
; Jump to the second boot sector
jmp 0x0000:0x7c00
; End of program
_end:
hlt
jmp _end
_error:
mov si, error_msg
call print
jmp _end
;-------------------------------------------------------------------------------
; Prints a zero-terminated string onto the screen
; SI = string to write
;-------------------------------------------------------------------------------
print:
pusha
.print_lbl:
lodsb
cmp al, 0
je .finished
mov ah, 0x0e
mov bl, 0
int 0x10
jmp .print_lbl
.finished:
popa
ret
;-------------------------------------------------------------------------------
loaded_msg: db "Operating system loaded", 0xa, 0xd, 0x0
error_msg: db "Operating system not found", 0xa, 0xd, "Press Ctrl+Alt+Del to reboot", 0x0
; Fill the rest of the 512 bytes with 0, byte 510 and 511
; contains 0xaa55 (boot signature for BIOS)
times 510 - ($ - $$) db 0
dw 0xaa55
代码使用选项 2:
;-------------------------------------------------------------------------------
; boot.asm - First boot sector
;-------------------------------------------------------------------------------
org 0x00
bits 16
jmp word _start
;-------------------------------------------------------------------------------
; BIOS Parameter Block (FAT32)
;-------------------------------------------------------------------------------
BS_OEMName: db "TestOS "
BPB_BytesPerSector: dw 512
BPB_SectorsPerCluster: db 1
BPB_ReservedSectors: dw 4
BPB_FATCount: db 2
BPB_RootEntryCount: dw 0
BPB_TotalSectors16: dw 0
BPB_Media: db 0xf0
BPB_FATSize16: dw 0
BPB_SectorsPerTrack: dw 18
BPB_HeadCount: dw 2
BPB_HiddenSectors: dd 0
BPB_TotalSectors32: dd 2880
BPB_FATSize32: dd 23
BPB_ExtendedFlags: dw 0x0000
BPB_FileSystemVersion: dw 0
BPB_RootCluster: dd 2
BPB_FSInfo: dw 3
BPB_BackupBootSector: dw 0
BPB_Reserved: times 12 db 0
BS_DriveNum: db 0x00
BS_Reserved1: db 0x0
BS_BootSignature: db 0x29
BS_VolumeID: dd 0x12345678
BS_VolumeLabel: db "TestOS "
BS_FileSystemType: db "FAT32 "
;-------------------------------------------------------------------------------
_start:
; Initialize segment registers and set up stack at 0x7c00 (grows downwards)
cli
mov ax, 0x7c0
mov ds, ax
mov ss, ax
xor ax, ax
mov sp, 0x7a00
sti
; Save drive number in DL
mov [BS_DriveNum], dl
; Copy this boot sector from 0x7c00 to 0x7a00
mov ax, 0x7a0
mov es, ax
xor si, si
xor di, di
mov cx, 512
cld
rep movsb
; Jump to the new location
jmp 0x07a0:(_continue)
_continue:
mov ax, 0x7c0
mov es, ax
mov ax, 0x7a0
mov ds, ax
; Load second boot sector into memory at 0x7c00 (try it 3 times before error message is printed)
mov si, 4
; Reset boot disk
_reset:
mov ah, 0
mov dl, [BS_DriveNum]
int 0x13
_load:
dec si
je _error
mov ah, 0x02
mov al, 2
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, [BS_DriveNum]
xor bx, bx
int 0x13
jc _load
mov si, loaded_msg
call print
; Jump to the second boot sector
jmp 0x0000:0x7c00
; End of program
_end:
hlt
jmp _end
_error:
mov si, error_msg
call print
jmp _end
;-------------------------------------------------------------------------------
; Prints a zero-terminated string onto the screen
; SI = string to write
;-------------------------------------------------------------------------------
print:
pusha
.print_lbl:
lodsb
cmp al, 0
je .finished
mov ah, 0x0e
mov bl, 0
int 0x10
jmp .print_lbl
.finished:
popa
ret
;-------------------------------------------------------------------------------
loaded_msg: db "Operating system loaded", 0xa, 0xd, 0x0
error_msg: db "Operating system not found", 0xa, 0xd, "Press Ctrl+Alt+Del to reboot", 0x0
; Fill the rest of the 512 bytes with 0, byte 510 and 511
; contains 0xaa55 (boot signature for BIOS)
times 510 - ($ - $$) db 0
dw 0xaa55
代码使用选项 3:
BOOT_ORG EQU 0x7c00
;-------------------------------------------------------------------------------
; boot.asm - First boot sector
;-------------------------------------------------------------------------------
org BOOT_ORG
bits 16
jmp word _start
;-------------------------------------------------------------------------------
; BIOS Parameter Block (FAT32)
;-------------------------------------------------------------------------------
BS_OEMName: db "TestOS "
BPB_BytesPerSector: dw 512
BPB_SectorsPerCluster: db 1
BPB_ReservedSectors: dw 4
BPB_FATCount: db 2
BPB_RootEntryCount: dw 0
BPB_TotalSectors16: dw 0
BPB_Media: db 0xf0
BPB_FATSize16: dw 0
BPB_SectorsPerTrack: dw 18
BPB_HeadCount: dw 2
BPB_HiddenSectors: dd 0
BPB_TotalSectors32: dd 2880
BPB_FATSize32: dd 23
BPB_ExtendedFlags: dw 0x0000
BPB_FileSystemVersion: dw 0
BPB_RootCluster: dd 2
BPB_FSInfo: dw 3
BPB_BackupBootSector: dw 0
BPB_Reserved: times 12 db 0
BS_DriveNum: db 0x00
BS_Reserved1: db 0x0
BS_BootSignature: db 0x29
BS_VolumeID: dd 0x12345678
BS_VolumeLabel: db "TestOS "
BS_FileSystemType: db "FAT32 "
;-------------------------------------------------------------------------------
_start:
; Initialize segment registers and set up stack at 0x7c00 (grows downwards)
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7a00
sti
; Save drive number in DL
mov [BS_DriveNum], dl
; Copy this boot sector from 0x7c00 to 0x7a00
mov si, 0x7c00
mov di, 0x7a00
mov cx, 512
cld
rep movsb
; Jump to the new location
jmp 0x0000:_continue
; The code and data past this point will have an origin point (vstart)
; relative to 0x7a00. Align=1 for no padding.
section bootreloc vstart=(($-$$)+0x7a00) align=1
_continue:
; Load second boot sector into memory at 0x7c00 (try it 3 times before error message is printed)
mov si, 4
; Reset boot disk
_reset:
mov ah, 0
mov dl, [BS_DriveNum]
int 0x13
_load:
dec si
jz _error
mov ah, 0x02
mov al, 2
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, [BS_DriveNum]
mov bx, 0x7c00
int 0x13
jc _load
mov si, loaded_msg
call print
; Jump to the second boot sector
jmp 0x0000:0x7c00
; End of program
_end:
hlt
jmp _end
_error:
mov si, error_msg
call print
jmp _end
;-------------------------------------------------------------------------------
; Prints a zero-terminated string onto the screen
; SI = string to write
;-------------------------------------------------------------------------------
print:
pusha
.print_lbl:
lodsb
cmp al, 0
je .finished
mov ah, 0x0e
mov bl, 0
int 0x10
jmp .print_lbl
.finished:
popa
ret
;-------------------------------------------------------------------------------
loaded_msg: db "Operating system loaded", 0xa, 0xd, 0x0
error_msg: db "Operating system not found", 0xa, 0xd, "Press Ctrl+Alt+Del to reboot", 0x0
; Set position to 510 bytes from BOOT_ORG so that bytes 510 and 511
; in te disk image will contain 0xaa55 (boot signature for BIOS)
section bootsig start=(BOOT_ORG+510)
dw 0xaa55