我正在创建自定义mbr,类似mbr-lovenote,但是我无法创建将复制第9个扇区的代码 -(位于原始mbr) 到第一扇区,我已经尝试从mbr-lovenote中获取一些代码并对其进行修改,但是我发现该代码仅将扇区加载到内存中并跳转到该扇区,但是我必须复制它。我编写了代码,该代码将从 PhysicalDrive0 的第一扇区加载,但是我不知道为什么它不起作用。
;---create buffer
buffer db 512
;---read sector - 9th
mov ax, buffer ;ES: BX must point to the buffer
mov es, ax ;
mov bx, buffer ;
mov dl,0 ;drive number
mov dh,0 ;head number
mov ch,0 ;track number
mov cl,9 ;sector number
mov al,1 ;number of sectors to read
mov ah,2 ;read function number
int 13h
;---write sector - 1th
mov ax, buffer ;ES: BX must point to the buffer
mov es, ax ;
mov bx, buffer ;
mov dl,0 ;drive number
mov dh,0 ;head number
mov ch,0 ;track number
mov cl,1 ;sector number
mov al,1 ;number of sectors to write
mov ah,3 ;write function number
int 13h
;---fake signature
times 510 - ($-$$) db 0
dw 0xaa55
答案 0 :(得分:2)
您没有提供一个完整的示例,有迹象表明您可能不知道实模式20-bit segment:offset addressing的工作方式。实模式下的每个内存位置均由一个16位段和一个16位偏移量组成。两者结合起来可使用以下公式计算20位物理地址:PhysicalAddress =(Segment << 4)+ Offset。左移4等于乘以16。
引导加载程序已加载到内存中的物理地址0x07c00。您必须选择一个ORG并在引导程序中设置段,以便它们引用物理地址0x07c00。一个以上的20位segment:offset地址可以指向相同的物理地址。引导加载程序的2个常见选项是使用ORG 0x7c00
,将段设置为0x0000((0x0000 << 4)+ 0x7c00 = 0x07c00),或者使用ORG 0x0000
和0x07c0((0x07c0 << 4 )+ 0x0000 = 0x07c00))。
在此Stackoverflow answer中,我有一些常规的引导程序提示。如果您可能正在编写引导加载程序以在FDD模式下的USB驱动器上运行,则您还需要阅读我的Stackoverflow answer,有关使用代表软盘的BIOS数据区(BDA)。
此示例是一个简单的引导加载程序,其基于您的代码的BDA将扇区9复制到扇区1(MBR),然后使用int 0x19
重新引导。该代码还将引导加载程序之后的内存(@ 0x0000:0x7e00)用于临时存储,以进行扇区复制。我还提供了一个放置在扇区9中的测试引导程序,该程序在运行时显示一条消息。
boot.asm :
org 0x7c00
bits 16
boot:
jmp main
TIMES 3-($-$$) DB 0x90 ; Support 2 or 3 byte encoded JMPs before BPB.
; Use a BIOS Parameter Block if you intend to use this on USB in FDD mode
; Dos 4.0 EBPB 1.44MB floppy
OEMname: db "mkfs.fat" ; mkfs.fat is what OEMname mkdosfs uses
bytesPerSector: dw 512
sectPerCluster: db 1
reservedSectors: dw 1
numFAT: db 2
numRootDirEntries: dw 224
numSectors: dw 2880
mediaType: db 0xf0
numFATsectors: dw 9
sectorsPerTrack: dw 18
numHeads: dw 2
numHiddenSectors: dd 0
numSectorsHuge: dd 0
driveNum: db 0
reserved: db 0
signature: db 0x29
volumeID: dd 0x2d7e5a1a
volumeLabel: db "NO NAME "
fileSysType: db "FAT12 "
main:
; BIOS passes our boot drive number in DL
; Setup segments
xor ax, ax ; AX=0
mov ds, ax ; DS=ES=0 because we use an org of 0x7c00
; segment<<4+offset = 0x0000<<4+0x7c00 = 0x07c00
mov es, ax
mov ss, ax
mov sp, 0x7c00 ; SS:SP= 0x0000:0x7c00 stack just below bootloader
;---read sector - 9th
mov bx, buffer ; ES: BX point to buffer (ES set to zero previously)
; mov dl,0 ; use boot drive passed to bootloader by BIOS in DL
mov dh,0 ; head number
mov ch,0 ; track number
mov cl,9 ; sector number
mov al,1 ; number of sectors to read
mov ah,2 ; read function number
int 13h
;---write sector - 1th
; The following commented lines aren't required. Int AH=13h/AH=2 only
; destroys AX and the following registers remain unchanged from the
; read disk BIOS call
; mov bx, buffer ; ES: BX must point to the buffer
; mov dl,0 ; use boot drive passed to bootloader by BIOS in DL
; mov dh,0 ; head number
; mov ch,0 ; track number
mov cl,1 ; sector number
mov al,1 ; number of sectors to write
mov ah,3 ; write function number
int 13h
mov si, message
call print_string ; Print a banner to the console
int 19h ; Warm reboot, should run bootloader that was in sector 9
; Function: print_string
; Display a string to the console on display page 0
;
; Inputs: SI = Offset of address to print
; Clobbers: AX, BX, SI
print_string: ; Routine: output string in SI to screen
mov ah, 0eh ; BIOS tty Print
xor bx, bx ; Set display page to 0 (BL)
jmp .getch
.repeat:
int 10h ; print character
.getch:
lodsb ; Get character from string
test al,al ; Have we reached end of string?
jnz .repeat ; if not process next character
.end:
ret
message: db "Running original bootloader...", 0x0a, 0x0d, 0
times 510 - ($-$$) db 0
dw 0xaa55 ; Boot signature
; This buffer is right after the bootloader and will be at offset 0x7e00.
; 0x0000:0x7e00 is the memory location starting right after the 512 byte
; bootloader loaded into memory by the BIOS
buffer:
sector9.asm :
org 0x7c00
bits 16
boot:
jmp main
TIMES 3-($-$$) DB 0x90 ; Support 2 or 3 byte encoded JMPs before BPB.
; Use a BIOS Parameter Block if you intend to use this on USB in FDD mode
; Dos 4.0 EBPB 1.44MB floppy
OEMname: db "mkfs.fat" ; mkfs.fat is what OEMname mkdosfs uses
bytesPerSector: dw 512
sectPerCluster: db 1
reservedSectors: dw 1
numFAT: db 2
numRootDirEntries: dw 224
numSectors: dw 2880
mediaType: db 0xf0
numFATsectors: dw 9
sectorsPerTrack: dw 18
numHeads: dw 2
numHiddenSectors: dd 0
numSectorsHuge: dd 0
driveNum: db 0
reserved: db 0
signature: db 0x29
volumeID: dd 0x2d7e5a1a
volumeLabel: db "NO NAME "
fileSysType: db "FAT12 "
main:
; Setup segments
xor ax, ax ; AX=0
mov ds, ax ; DS=ES=0 because we use an org of 0x7c00
; segment<<4+offset = 0x0000<<4+0x7c00 = 0x07c00
mov ss, ax
mov sp, 0x7c00 ; SS:SP= 0x0000:0x7c00 stack just below bootloader
mov si, message
call print_string ; Print a banner to the console
cli
.endloop: ; Infinite loop to end bootloader
hlt
jmp .endloop
; Function: print_string
; Display a string to the console on display page 0
;
; Inputs: SI = Offset of address to print
; Clobbers: AX, BX, SI
print_string: ; Routine: output string in SI to screen
mov ah, 0eh ; BIOS tty Print
xor bx, bx ; Set display page to 0 (BL)
jmp .getch
.repeat:
int 10h ; print character
.getch:
lodsb ; Get character from string
test al,al ; Have we reached end of string?
jnz .repeat ; if not process next character
.end:
ret
message: db "Running sector 9 bootloader...", 0x0a, 0x0d, 0
times 510 - ($-$$) db 0
dw 0xaa55 ; boot signature
要构建1.44MiB软盘映像并将主引导程序放置在扇区1中,将辅助引导程序放置在扇区9中,如果您在具有dd
命令的系统上运行,则可以使用以下命令:>
nasm -f bin boot.asm -o boot.bin
nasm -f bin sector9.asm -o sector9.bin
dd if=/dev/zero of=disk.img bs=1024 count=1440
dd if=boot.bin of=disk.img conv=notrunc seek=0
dd if=sector9.bin of=disk.img conv=notrunc seek=8
您可以使用QEMU来运行以下代码:
qemu-system-i386 -fda disk.img
如果您是在仿真器或虚拟机(例如QEMU)中运行此程序,则应显示以下内容:
发生的事情是,扇区9已由boot.bin
中的原始引导程序复制到扇区1,然后计算机重新引导。重新引导后,它在sector9.bin
中运行了引导加载程序代码,该代码已从扇区9复制到MBR。它应该打印:
正在运行原始的引导程序...
然后应打印:
正在运行扇区9引导加载程序...
注意:您将需要确保磁盘不受写保护,并且所用的任何BIOS都没有使用 MBR安全性。 MBR安全性防止BIOS调用覆盖启动驱动器上的MBR(扇区1)。
答案 1 :(得分:0)
OP(@WobbyChip)编写了此解决方案,以更新他们的问题。
SectorCopy.asm ->感谢 Michael Petch --->使用此代码复制扇区。
org 0x7c00
bits 16
SectorCopy:
; Setup segments
xor ax, ax ; AX=0
mov ds, ax ; DS=ES=0 because we use an org of 0x7c00 - Segment<<4+offset = 0x0000<<4+0x7c00 = 0x07c00
mov es, ax
mov ss, ax
mov sp, 0x7c00 ; SS:SP= 0x0000:0x7c00 stack just below bootloader
;---read sector - 9th
mov bx, buffer ; ES: BX must point to the buffer
; mov dl,0 ; use boot drive passed to bootloader by BIOS in DL
mov dh,0 ; head number
mov ch,0 ; track number
mov cl,9 ; sector number - (9th)
mov al,1 ; number of sectors to read
mov ah,2 ; read function number
int 13h
;---write sector - 1th
mov bx, buffer ; ES: BX must point to the buffer
; mov dl,0 ; use boot drive passed to bootloader by BIOS in DL
mov dh,0 ; head number
mov ch,0 ; track number
mov cl,1 ; sector number - (1th)
mov al,1 ; number of sectors to write
mov ah,3 ; write function number
int 13h
times 510 - ($-$$) db 0
dw 0xaa55 ; Boot signature
buffer: