当我将软件写入MBR时,我的电脑停止运行。我的软件用于挂接INT 13h并在执行INT 13h时执行一些代码。我已经为INT 13h尝试了太多的ISR,但没有成功。这是我的示例来源:
cli
cs
mov si,[4Ch]
cs
mov di,[4Eh]
cs
mov [180h],cx
cs
mov [182h],dx
mov si,0h
mov di,2000h
cs
mov [4Ch],si
cs
mov [4Eh],di
sti
mov si,2000h
mov di,0
mov ds,di
mov es,si
mov si,7C6DH
mov di,0
mov cx,codelastbyte-payload
cld
repz
movsb
mov ax,201h
push cs
pop es
mov bx,7c00h
mov cx,7
mov dx,80h
int 60h
jmp 0:7C00h
payload: ;NEW INT13H
sti
INT 60H
iret
codelastbyte:
有什么问题?
答案 0 :(得分:2)
您没有提供任何背景信息,而且您的代码似乎并不完整。一个明显的错误似乎出现在这些行中:
mov si,[4Ch]
cs
mov di,[4Eh]
cs
mov [180h],cx
cs
mov [182h],dx
看来你真的是指最后4行是 SI 和 DI :
cs
mov [180h],si
cs
mov [182h],di
如果chain loading您无法在代码已执行的区域之上加载新的引导加载程序。您可能会遇到不寻常的行为。您需要将引导加载程序复制到其他位置;继续在新位置执行代码;然后将新的引导加载程序加载到物理地址0x07C00的内存中。
为了便于阅读,最好将段覆盖(在这种情况下为 CS )放在内存操作数内。这段代码:
cs
mov [180h],si
可以写成:
mov [cs:180h],si
以下代码示例:
实现此目的的FASM代码:
RESIDENT_SEG equ 0x2000
BOOT_SEG equ 0x07c0
BOOTCOPY_SEG equ 0x0060
STACK_OFFSET equ 0x7c00
INT13_OFFSET equ 0x13 * 4
org 0x0000
boot_start:
; Set up our own stack just below bootloader @ 0x0000:0x7c00
xor ax, ax
mov ss, ax
mov sp, STACK_OFFSET
; Copy the bootloader code and data from 0x07C0:0x0000 to 0x0060:0x0000
mov ax, BOOT_SEG
mov ds, ax
mov [boot_drive], dl
mov ax, BOOTCOPY_SEG
mov es, ax
cld
xor si, si
mov di, si
mov cx, SIZEOF_BOOT+SIZEOF_PAYLOAD
rep movsb
; Transfer control to copy of bootloader relocated to segment 0x0060
jmp BOOTCOPY_SEG:bootcopy_cont
bootcopy_cont:
; Set DS = ES= 0x0060
push es
pop ds
; ES = 0 to access IVT that begins at 0x0000:0x0000
xor ax, ax
mov es, ax
; Place the original FAR PTR of Int 13 into BX:AX
cli
mov ax, [es:INT13_OFFSET]
mov bx, [es:INT13_OFFSET+2]
; Install our new int 0x13 handler
mov si, int13
mov di, RESIDENT_SEG
mov [es:INT13_OFFSET], si
mov [es:INT13_OFFSET+2], di
; Copy the interrupt handler to 0x2000:0x0000
mov es, di
mov si, payload_boot_offset
xor di, di
mov cx, SIZEOF_PAYLOAD
rep movsb
; Now that interrupt and interrupt data (payload) is copied to 0x2000 segment
; save the orig_int13 to the interrupt data area. AX and BX were set earlier
mov [es:orig_int13], ax
mov [es:orig_int13+2], bx
sti
; Read sector 7(CHS=0,0,7) to 0x07c0:0x0000 (phys address 0x07c00)
mov ax, 201h
mov bp, BOOT_SEG
mov es, bp
xor bx, bx
mov cx, 7
xor dx, dx
mov dl, [boot_drive]
call do_orig_int13
; Jump to newly loaded bootloader
jmp 0:0x7C00
; Function : do_orig_int13
; Return : none
; Clobbers : Same as int 0x13
;
; Description:
; Manually call the original Int 0x13 handler. Int instruction pushes
; the flags and then calls through the interrupt vector table. We
; Do that same process. This avoids having to use Int 0x60. The
; Old interrupt vector was saved to RESIDENT_SEG(0x2000):orig_int13
; earlier.
do_orig_int13:
push ds
push bp
mov bp, RESIDENT_SEG
mov ds, bp
pop bp
pushf
call far [ds:orig_int13]
pop ds
ret
; Boot data
boot_drive: db 0x00
SIZEOF_BOOT = $-$$
payload_boot_offset:
org 0x0000
int13: ;NEW INT 0x13
; Print MDP to upper left corner of screen in magenta on white
push ax
push es
mov ax, 0xb800
mov es, ax
mov word [es:0x0000], (0x75 shl 8) or 'M'
mov word [es:0x0002], (0x75 shl 8) or 'D'
mov word [es:0x0004], (0x75 shl 8) or 'P'
pop es
pop ax
; Do original disk interrupt routine. We jump to it
; instead of using the INT instruction because
; The Int 0x13 original routine sets the flags and we
; want them to be returned to whoever called us.
jmp far [cs:orig_int13]
; The original interrupt handler will do the IRET for us
; Will never return to this point
; Insert data used by the interrupt handler here
orig_int13: dd 0x0000 ; Copy of the original Int 13h handler
SIZEOF_PAYLOAD = $-$$
;Pad first sector with 0, add boot signature to last 2 bytes
times 510-(SIZEOF_BOOT+SIZEOF_PAYLOAD) db 0
dw 0xaa55
; Pad out 5 more sectors with 0
times 512 * 5 db 0x00
; Sector 7 test code
org 0x7c00
sector7:
; Set DS = 0x0000
xor ax, ax
mov ds, ax
; Call Int 0x13 to reset disk. Our interrupt handler should also display MDP
; in upper left corner of the screen. AX set to zero above. Int 0x13/AH=0 is reset.
; DL set by the code that loaded this bootloader just like the BIOS would have done.
int 0x13
cli
; Infinite loop to end the code
.endloop:
hlt
jmp .endloop
; Pad out remainder of sector 7
times 512-($-$$) db 0x00
; Pad out remaining bytes to create a 1.44MiB floppy image
times (2880-7)*512 db 0x00
您可以使用以下命令将其组合成软盘映像:
fasm bootload.asm disk.img
使用以下命令运行:
qemu-system-i386 -fda disk.img
输出看起来类似于:
注意:
MDP
白色洋红色,然后将控制传递给原始处理程序。