对于一个项目,我想直接从DOS调用第一个硬盘上的MBR。我编写了一个小的汇编程序,它将MBR加载到内存中0:7c00h,远远超过它。我把我的util放在(DOS)可启动软盘上。我正在尝试启动的磁盘(HD0,0x80)上有一个TrueCrypt启动加载程序。当我在此设置中运行该工具时,它会显示TrueCrypt屏幕,但输入密码后会崩溃系统。当我在普通的WinXP机器上运行我的小功能(w00t.com)时,它似乎立即崩溃。
显然我忘记了BIOS通常会做的一些关键事情,我猜这是微不足道的。有更好的裸机DOS和BIOS经验的人可以帮助我吗?
继承我的代码:
.MODEL tiny
.386
_TEXT SEGMENT USE16
INCLUDE BootDefs.i
ORG 100h
start:
; http://vxheavens.com/lib/vbw05.html
; Before DOS has booted the BIOS stores the amount of usable lower memory
; in a word located at 0:413h in memory. We going to erase this value because
; we have booted dos before loading the bootsector, and dos is fat (and ugly).
; fake free memory
;push ds
;push 0
;pop ds
;mov ax, TC_BOOT_LOADER_SEGMENT / 1024 * 16 + TC_BOOT_MEMORY_REQUIRED
;mov word ptr ds:[413h], ax ;ax = memory in K
;pop ds
;lea si, memory_patched_msg
;call print
;mov ax, cs
mov ax, 0
mov es, ax
; read first sector to es:7c00h (== cs:7c00)
mov dl, 80h
mov cl, 1
mov al, 1
mov bx, 7c00h ;load sector to es:bx
call read_sectors
lea si, mbr_loaded_msg
call print
lea si, jmp_to_mbr_msg
call print
;Set BIOS default values in environment
cli
mov dl, 80h ;(drive C)
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0ffffh
sti
push es
push 7c00h
retf ;Jump to MBR code at 0:7c00h
; Print string
print:
xor bx, bx
mov ah, 0eh
cld
@@: lodsb
test al, al
jz print_end
int 10h
jmp @B
print_end:
ret
; Read sectors of the first cylinder
read_sectors:
mov ch, 0 ; Cylinder
mov dh, 0 ; Head
; DL = drive number passed from BIOS
mov ah, 2
int 13h
jnc read_ok
lea si, disk_error_msg
call print
read_ok:
ret
memory_patched_msg db 'Memory patched', 13, 10, 7, 0
mbr_loaded_msg db 'MBR loaded', 13, 10, 7, 0
jmp_to_mbr_msg db 'Jumping to MBR code', 13, 10, 7, 0
disk_error_msg db 'Disk error', 13, 10, 7, 0
_TEXT ENDS
END start
答案 0 :(得分:2)
已编辑 - 新答案:
好的,好像我第一次误解了你的问题。我能给出的唯一进一步建议是:检查您是否未加载HIMEM.SYS
和/或EMM386.EXE
(也未加载任何其他内存管理器)。当引导程序执行时,CPU 必须处于实模式。
看看拉尔夫·布朗的中断名单。如果我没记错的话,那里有关于启动过程的某些技术信息。它可能会给你一个提示。
查看其他加载器实用程序的源代码,例如loadlin
。 (它与您的实用程序完全不同,但可能会给您一些见解。)
上一个回答:
在引导加载程序中 ORG 100h
真的是正确的做法吗?
我认为这只与DOS .com
可执行文件有关,因为DOS将使用程序段前缀(PSP)初始化前256个字节。如果您编写引导加载程序,则没有DOS,也没有PSP这样的东西。我想这必须是ORG 0
。
答案 1 :(得分:2)
好的,我的DOS知识非常生疏,我没有时间测试/验证我的答案,但我想你的问题如下:
启动DOS或任何其他操作系统时,它们将更改中断表。 DOS将更改中断表,例如 - 中断20可用于向DOS“内核”发送命令。他们通过保存原始中断处理程序,用自己的处理程序替换它来执行此操作,然后作为默认回退,如果他们不知道如何处理中断,则链接到原始中断处理程序。这样他们就可以为已经存在的bios功能“添加”新功能,并且在DOS下运行的每个程序都可以通过设置一些寄存器然后调用中断来使用系统调用。
但是,当你启动一个新的操作系统时,这个新的操作系统将假设a)所有中断都由bios处理,b)所有内存都是空闲/未使用的,除非该bios使用该内存。
因此新操作系统将覆盖旧操作系统当前使用的内存,然后它会在某个时刻调用其中一个中断,并在无效内存中执行某些内容,并且您的计算机将崩溃。
所以,将你的中断表重置为原始的bios版本,你应该没事......
答案 2 :(得分:0)
我不认为这是一个启动加载程序,它是加载启动扇区并尝试执行它的.com文件。所以它在DOS初始化后运行。