【发布时间】:2016-09-01 21:51:33
【问题描述】:
我正在关注 Nick Blundell 的引导扇区编程教程(https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf 和 https://www.youtube.com/watch?v=YvZhgRO7hL4)。我的代码在我的 qemu 模拟器中运行良好,但是当我在物理机器上运行它时,每当我开始引用段寄存器时它就会崩溃。 我在学校的老师不熟悉低级编程,无法帮助我。这是我的引导加载程序,在这里我用字符串 CRASH 注释了导致它崩溃的行(注意:当我说崩溃时,它实际上只是继续从下一个磁盘加载我的操作系统。我正在从外部加载此代码硬盘):
[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 '0123456789abcdef'
print_newline :
pusha
mov ah, 0x0e
mov al, 0x0d
int 0x10
mov al, 0x0a
int 0x10
popa
ret
【问题讨论】:
-
mov bp, 0xffffmov sp, bp可能是坏的。堆栈由 SS:SP 指向。你不知道 SS 设置在哪里。您应该同时设置 SS 和 SP。 PS:堆栈指针不应该是奇数地址(出于性能原因)。要将堆栈设置在引导加载程序下方,您可以使用xor ax, axmov ss, axmov sp, 0x7c00。xor ax,ax会将 AX 归零(您可以使用更长的指令mov ax, 0x0000 -
实际
mov dx, ds类型的指令不会自行崩溃。它必须是别的东西(在那个 mov 之后做了什么)。 -
真实硬件上的处理器类型是什么? 8086? 80286? 80386?
-
处理器是 Intel Atom(32 位)......我假设模拟器会自动设置我的段寄存器。此代码:
xor ax, axmov ss, axmov ds, axmov sp, 0x7c00mov bp, spjmp $也会导致“崩溃” -
模拟器和真实硬件会在 BIOS 启动期间为自己设置一个 SS:SP 对。但是你不能像现在这样只改变一半。如果您更改 SP,则需要更改 SS,因为您不知道 BIOS 为 SS 使用了什么值。物理内存是通过(segment * 16)+offset计算的。据你所知,你的堆栈可能指向一些潜在的不可写的内存区域。您可能会很幸运,代码可以正常工作。
标签: assembly x86 bootloader osdev