NASM,如何直接写入硬盘并在实模式下读取
Posted
技术标签:
【中文标题】NASM,如何直接写入硬盘并在实模式下读取【英文标题】:NASM, how to write straight to the hard disk and read from it in Real Mode 【发布时间】:2018-10-14 09:04:57 【问题描述】:在最新版本的 Ubuntu 上,x64。
我基本上想知道操作系统如何能够在从闪存驱动器启动时将自己安装在计算机上,但我想在实模式而不是保护模式或长模式下执行此操作。像 MS-DOS 这样的旧操作系统肯定曾经这样做过。
对于实模式,是否有中断?或者我需要先切换到保护模式或长模式,然后才能将数据直接写入硬盘和/或从同一区域读取数据?
为具有 2 阶段引导加载程序的小型实模式操作系统执行此操作:
org 0x7C00
mov ah, 0
int 13h
mov dx, 0
mov ah, 2
mov al, 10h
mov dl, 0x80
mov ch, 0
mov dh, 0
mov cl, 2
mov bx, stage2
int 0x13
jmp stage2
times 510-($-$$) db 0
dw 0xAA55
msg db "!!"
%include "read.s" ;read.s does not exist yet, as I do not know how to read from an address on the hard disk
%include "write.s" ;write.s does not exist yet, as I do not know how to write to an address on the hard disk
stage2:
call ReadStr ;always reads from the same address, if the message is there, sets bl to 0x01. Otherwise, sets bl to 0x00.
cmp bl, 0x00
je load
mov ah, 0eh
mov al, "#" ;tiny message to tell me that the string is already at the address
mov bx, 0
int 10h
jmp $
load:
mov ax, [msg]
call LoadStr ;loads the message to the same address that ReadStr reads from
mov ah, 0eh
mov al, "$" ;tiny message to tell me that the string does not already exist at the address
mov bx, 0
int 10h
jmp $
这里的想法是,我第一次启动引导加载程序时,它应该打印'$',但我第二次启动它时,它应该打印'#',因为数据已经存在于特定地址的硬盘上.但我不知道如何实现 read.s 和 write.s。理想情况下(主要目标),操作系统将在我第一次在闪存驱动器上启动引导加载程序时自行安装在计算机上。我需要先设置长模式才能做到这一点,还是在 Bios 中可以?
【问题讨论】:
如果从实模式访问硬盘,请查看扩展磁盘读取int 13h/ah=42h 和扩展磁盘写入int 13h/ah=43h。可以在此处找到与磁盘访问相关的 BIOS 中断列表:ctyme.com/intr/int-13.htm。如果您的 BIOS 设置为启动 USB HDD(而不是 USB FDD),则它应该像硬盘一样用于您的目的。 所以对于int 13h/ah=43h(扩展写入),驱动器号(dl),我是否应该将其设置为0x80,因为我正在写入硬盘? 当 BIOS 将控制权转移到您的引导加载程序(从第一个扇区读取)时,它会将 DL 设置为正在引导的设备的驱动器号。您应该将该值用于磁盘读取和写入启动的媒体。 您不会读取字符串本身。您一次读取数据的扇区。它可能包含字符串或二进制数据等。读取例程将指定数量的扇区读取到内存中。您必须以您认为合适的方式解释该数据。 扩展磁盘读取适用于更高容量的介质(硬盘驱动器、闪存、CD-ROM)。在没有专门的特殊 BIOS 转换的情况下,常规磁盘读取具有大小限制(由于如何实现柱面扇区寻址而受到限制)。通过定期阅读和仪式,您可能只能看到部分媒体。如今,常规磁盘读/写几乎都用于软盘驱动器媒体。软盘驱动器(或软盘驱动器模拟设备)。软盘驱动器通常不支持扩展磁盘读/写。 【参考方案1】:有一些工作;第一次启动它会打印“!#”,但之后每次启动时,它都会打印“##”,因为闪存驱动器的第二个扇区已被闪存驱动器的第三个扇区覆盖。唯一缺少的是如何使用硬盘驱动器而不是闪存驱动器来做到这一点,但至少我现在知道如何重写闪存驱动器,因此可以以某种方式模拟内存存储,即使是以一种低效的方式。下一步是找出如何将可引导扇区注入到实际计算机的内存中,以便我可以利用 RAM 的原始能力来存储和操作数据。
org 0x7C00
stage1:
mov ah, 2
mov cl, 2
mov bx, stage2
int 13h
call stage2
mov ah, 2
mov cl, 3
mov bx, stage2
int 13h
mov ah, 3
mov cl, 2
mov bx, stage2
int 13h
mov ah, 2
mov cl, 2
mov bx, stage2
int 13h
call stage2
jmp $
times 510-($-$$) db 0
dw 0xAA55
stage2:
mov ah, 0eh
mov al, "!"
mov bx, 0
int 10h
ret
times 1024-($-$$) db 0
stage3:
mov ah, 0eh
mov al, "#"
mov bx, 0
int 10h
ret
times 1536-($-$$) db 0
【讨论】:
【参考方案2】:您的答案在https://en.wikipedia.org/wiki/INT_13H,您应该将 dl 更改为驱动程序的数量,然后对该驱动程序进行操作:
mov dl,[that_driver_number]
注意:当 bios 想要运行引导加载程序时,将 dl 设置为引导加载程序驱动程序(例如,如果 cd 驱动程序 1 上的引导加载程序,它设置为 E0)同样当你没有改变它时,你的操作发生在你的引导程序上 例如,此代码应将您的引导加载程序复制到硬盘上
【讨论】:
以上是关于NASM,如何直接写入硬盘并在实模式下读取的主要内容,如果未能解决你的问题,请参考以下文章
如何从 servlet-filter 写入文件并在 Eclipse 中读取它?