Я следую инструкциям Ник Бланделл для программирования загрузочного сектора (https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf и https://www.youtube.com/watch?v=YvZhgRO7hL4). Мой код очень хорошо работает в моем эмуляторе qemu, однако, когда я запускаю его на физической машине, он будет сбой, когда я начну ссылаться на сегментные регистры. Мои учителя в школе не знакомы с программированием на низком уровне и не могут мне помочь. Вот мой загрузчик, здесь я аннотировал строки, которые приводят его к сбою со строкой CRASH (обратите внимание: когда я говорю об аварии, на самом деле он просто загружает мою ОС со следующего диска. Я загружаю этот код из внешнего HDD):Почему мой загрузчик сбой после добавления этой строки?
[bits 16]
[org 0x7c00]
mov bp, 0xffff
mov sp, bp
mov ax, 0x0000
mov ds, ax
;; mov es, ax ;; CRASH
;; mov ss, ax ;; CRASH
mov si, BOOT_MSG
call print_string
call print_newline
mov si, INIT_SEG_MSG
call print_string
call print_newline
;; mov dx, ds ;; CRASH
;; call print_hex
;; call print_newline
;;mov dx, cs ;; CRASH
;;call print_hex
;;call print_newline
;;mov dx, es ;; CRASH
;;call print_hex
;;call print_newline
;;mov dx, ss ;; CRASH
;;call print_hex
;;call print_newline
;; mov dl, 0x80 ;; disk where kernel is
;; mov cl, 3 ;; start sect
;; mov al, 1 ;; num sect
;; mov bx, 0x7ef0 ;; RAM addr
;; call load_kernel
;; mov si, KERN_MSG
;; call print_string
;; call print_newline
;; call switch_to_pm
jmp $
%include "print.asm"
%include "print_hex.asm"
%include "disk.asm"
%include "pm.asm"
[bits 32]
pm :
mov esi, PM_MSG
call print_string_pm
jmp 0x7ef0
jmp $
[bits 16]
BOOT_MSG : db 'booted 16-bit to 0x7c00',0
KERN_MSG : db 'loaded kernel to es 0x7ef0',0
PM_MSG : db 'switched to 32-bit mode',0
INIT_SEG_MSG : db 'init segment registers',0
times 510-($-$$) db 0
dw 0xaa55 `
Уверен, что у меня есть фундаментальное недоразумение, любая помощь будет оценена по достоинству. Вот мои печатные процедуры:
print_string :
push ax
_loop :
lodsb
cmp al, 0
je _end
mov ah, 0x0e
int 0x10
jmp _loop
_end :
pop ax
ret
print_hex :
mov si, HEX_TEMPLATE
mov bx, dx
shr bx, 12
mov bx, [bx+HEXABET]
mov [HEX_TEMPLATE+2], bl
mov bx, dx ;; bx -> 0x1234
shr bx, 8 ;; bx -> 0x0012
and bx, 0x000f ;; bx -> 0x0002
mov bx, [bx+HEXABET]
mov [HEX_TEMPLATE+3], bl
mov bx, dx
shr bx, 4
and bx, 0x00f
mov bx, [bx+HEXABET]
mov [HEX_TEMPLATE+4], bl
mov bx, dx
and bx, 0x0f
mov bx, [bx+HEXABET]
mov [HEX_TEMPLATE+5], bl
call print_string
ret
HEX_TEMPLATE : db '0x???? ',0
HEXABET : db 'abcdef'
print_newline :
pusha
mov ah, 0x0e
mov al, 0x0d
int 0x10
mov al, 0x0a
int 0x10
popa
ret
'mov bp, 0xffff'' mov sp, bp' потенциально опасно. На стек указывается SS: SP. Вы не знаете, к чему настроен _SS_. Вы должны установить как SS, так и SP. PS: Указатель стека не должен быть нечетным номером (по соображениям производительности). Чтобы установить стек чуть ниже загрузчика, вы можете использовать 'xor ax, ax'' mov ss, ax'' mov sp, 0x7c00'. 'xor ax, ax' будет нулевым _AX_ (вы могли бы использовать более длинную инструкцию' mov ax, 0x0000' –
Фактические инструкции типа 'mov dx, ds' не будут разбиваться сами по себе. Это должно быть что-то другое (что-то сделано после что mov). –
Какой процессор находится на вашем реальном оборудовании? 8086? 80286? 80386? –