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
(адрес виртуальной памяти). Вы можете использовать директиву segment
с опцией start
(адрес загрузки памяти), чтобы изменить смещение файла, в котором находится подпись загрузки.
Другие проблемы в вашем коде:
- Как указывал @RossRidge, если после операции на диске возникает ошибка (установлен флаг переноса), она попадает в бесконечный цикл, потому что вы используете регистр CX , который также используется при выполнении Int 13h / AH = 02h. Вы также используете CX для счетчика попыток сброса диска и работы диска.
- Как правило, вы можете не проверять наличие ошибок при сбросе диска Int 13h / AH = 0 и удалять цикл повторной попытки для этой операции. Вам следует только перезагрузить диск, если предыдущая операция не удалась. Повторная попытка работы с диском три раза была нормальной на реальном оборудовании.
- Когда ваш код успешно читает новый код и данные в 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