如何将第 9 扇区复制到第 1 扇区?
How to copy 9th sector to 1st sector?
我正在创建自定义 mbr,类似于 mbr-lovenote and i can't create code that will copy 9th sector - (there is located original mbr) to 1st sector, i already tried take some code from 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
您没有提供最小的完整示例,并且有迹象表明您可能不知道实模式 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)).
我在这个 . If you are potentially writing your bootloader to run on a USB drive in FDD mode you will also want to read my 中有一些关于使用表示软盘的 BIOS 数据区 (BDA) 的一般引导加载程序提示。
此示例是一个简单的引导加载程序,带有基于您的代码的 BDA,用于将扇区 9 复制到扇区 1 (MBR),然后使用 int 0x19
重新启动。该代码还使用内存中引导加载程序之后的内存(@ 0x0000:0x7e00)作为临时存储来执行扇区复制。我还提供了一个测试引导加载程序,它被放置在扇区 9 中,当 运行ning 时显示一条消息。
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。它应该打印:
Running original bootloader...
稍后应该打印:
Running sector 9 bootloader...
注意:您需要确保您的磁盘没有写保护,并且您使用的任何 BIOS 都没有使用 MBR 安全性。 MBR 安全性 防止 BIOS 调用覆盖引导驱动器上的 MBR(扇区 1)。
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:
我正在创建自定义 mbr,类似于 mbr-lovenote and i can't create code that will copy 9th sector - (there is located original mbr) to 1st sector, i already tried take some code from 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
您没有提供最小的完整示例,并且有迹象表明您可能不知道实模式 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)).
我在这个
此示例是一个简单的引导加载程序,带有基于您的代码的 BDA,用于将扇区 9 复制到扇区 1 (MBR),然后使用 int 0x19
重新启动。该代码还使用内存中引导加载程序之后的内存(@ 0x0000:0x7e00)作为临时存储来执行扇区复制。我还提供了一个测试引导加载程序,它被放置在扇区 9 中,当 运行ning 时显示一条消息。
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。它应该打印:
Running original bootloader...
稍后应该打印:
Running sector 9 bootloader...
注意:您需要确保您的磁盘没有写保护,并且您使用的任何 BIOS 都没有使用 MBR 安全性。 MBR 安全性 防止 BIOS 调用覆盖引导驱动器上的 MBR(扇区 1)。
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: