win7重写mbr-(win7重制电脑)

来源:191路由网 2022-12-27 21:06:57

(win7重制电脑)

我们在这一节之前MBR在此基础上,做一个稍微大一点的改进,经过这个改进,我们的MBR可读硬盘。听起来这是一个大的手术。我们应该使用我们以前学到的所有知识。其实没那么大,只是加了一个读写磁盘的函数,哈哈。带着兴奋和不安的心情,让我们开始吧。

改造不是改,改造前要有计划,对以后的程序布局要有计划,心里有数。先说说现在的想法。

我们的MBR受512字节大小的限制,在这么小的空间里,内核无法准备好环境,内核无法成功加载到内存并运行。因此,我们应该在另一个程序中完成初始化环境和加载核心的任务,这个程序被称为loader,即加载器。Loader将在下一节实现。问题来了,loader在哪里?如何跳过去执行?这就是新款MBR简而言之,它负责硬盘的使命loader加载到内存中,并将接力棒交给它。

由于MBR它占据了硬盘的第0个扇区(逻辑LBA如果是物理的话,扇区从0开始编号CHS方法,风扇区域从1开始编号),第一个风扇区域是免费的,可以使用,但太近总是感觉有点坚定,所以把loader放在第二扇区。MBR读出第二扇区。读出来放在哪里?原则上就是找个空闲的地方,0x500~0x7BFF和0x7E00~9FBFF两个内存区域都可以。

是的,容小弟分析一下:

首先,loader定义一些数据结构(如GDT全局描述符表,不懂也没关系,以后再说),这些数据结构未来的核心还是要用的,所以loader内存加载后不能覆盖。

其次,随着我们不断增加功能,核心必须越来越大,其内存地址将发展到越来越高的地方,这将不可避免地超过可用区域的上限。让我们尽力loader把它放在低处,给核心留出更多的空间。

所以,我将loader加载地址为0x900。为什么不是0x多省空间500。还是预留一定的空间吧,彼此隔开一点心才踏实,不差这个空间,哈哈,完全是个人喜好,大家随意。

按照上面提到的规划,下面的代码是新头换面的新款MBR。代码量增加到126行,让我们谈谈细节:

1 ;主引导程序 2 ;------------------------------------------------------------ 3 %include \\"boot.inc\\" 4 SECTION MBR vstart=0x7c00 5 mov ax,cs 6 mov ds,ax 7 mov es,ax 8 mov ss,ax 9 mov fs,ax 10 mov sp,0x7c00 11 mov ax,0xb800 12 mov gs,ax 13 14 ; 清屏 15 ;利用0x06号功能,上卷全行,可清屏。 16 ; ----------------------------------------------------------- 17 ;INT 0x10 功能号:0x06 功能描述:卷窗 18 ;------------------------------------------------------ 19 ;输入: 20 ;AH 功能号= 0x06 21 ;AL = 如果是0,表示全部) 22 ;BH = 上卷行属性 23 ;(CL,CH) = 窗口左上角(X,Y)位置 24 ;(DL,DH) = 窗口右下角(X,Y)位置 25 ;无返回值: 26 mov ax, 0600h 27 mov bx, 0700h 28 mov cx, 0 ; 左上角: (0, 0) 29 mov dx, 184fh ; 右下角: (80,25), 30 ; 因为VGA在文本模式下,一行只能容纳80个字符,共25行。 31 ; 下标从0开始,所以0x18=24,0x4f=79 32 int 10h ; int 10h 33 34 ; 输出字符串:MBR 35 mov byte[gs:0x00],'1' 36 mov byte[gs:0x01],0xA4 37 38 mov byte[gs:0x02],' ' 39 mov byte[gs:0x03],0xA4 40 41 mov byte[gs:0x04],'M' 42 mov byte[gs:0x05],0xA4 ;A绿色背景闪烁,前景红色 43 44 mov byte[gs:0x06],'B' 45 mov byte[gs:0x07],0xA4 46 47 mov byte[gs:0x08],'R' 48 mov byte[gs:0x09],0xA4 49 50 mov eax,LOADER_START_SECTOR ; 起始扇区lba地址 51 mov bx,LOADER_BASE_ADDR ; 写入的地址 52 mov cx,1 ; 待读扇区数 53 call rd_disk_m_16 ; 以下读取程序的开始部分(一个扇区) 54 55 jmp LOADER_BASE_ADDR 56 57 ;------------------------------------------------------------------------------- 58 ;电脑功能:读取硬盘n扇区 59 rd_disk_m_16: 60 ;------------------------------------------------------------------------------- 61 ; eax=LBA扇区号 62 ; bx=将数据写入的内存地址 63 ; cx=读入的扇区数 64 mov esi,eax ;备份eax 65 mov di,cx ;备份cx 66 ;读写硬盘: 67 ;第一步:设置要读取的扇区数 68 mov dx,0x1f2 69 mov al,cl 70 out dx,al ;读取的扇区数 71 72 mov eax,esi ;恢复ax 73 74 ;第2步:将LBA地址存入0x1f3 ~ 0x1f6 75 76 ;LBA7~0写入口0x1f3 77 mov dx,0x1f3 78 out dx,al 79 80 ;LBA地址15~8x1f4 81 mov cl,8 82 shr eax,cl 83 mov dx,0x1f4 84 out dx,al 85 86 ;LBA地址23~16x1f5 87 shr eax,cl 88 mov dx,0x1f5 89 out dx,al 90 91 shr eax,cl 92 and al,0x0f ;lba第24~27位 93 or al,0xe0 ; 7~4位为1110,表示lba模式 94 mov dx,0x1f6 95 out dx,al 96 97 ;第3步:向0x1f7端口写入阅读命令,0x20 98 mov dx,0x1f7 99 mov al,0x20100 out dx,al101102 ;第四步:检测硬盘状态103 .not_ready:104 ;同一个端口,写入命令字,读入硬盘状态105 nop106 in al,dx107 and al,0x88 ;第四名为1,表示硬盘控制器已准备好数据传输, ;第七名1表示硬盘忙108 cmp al,0x08109 jnz .not_ready ;若未准备好,继续等待。110111 ;第5步:从0x1f0端口读数据112 mov ax, di113 mov dx, 256114 mul dx115 mov cx, ax ; di为了读取扇区数,一个扇区有512字节,每次读一个字,116 ; 共需di*512/2次,所以di*256117 mov dx, 0x1f0118 .go_on_read:119 in ax,dx120 mov[bx],ax121 add bx,2122 loop .go_on_read123 ret124125 times 510-($-$$) db 0126 db 0x55,0xaa

程序开始的%include \\"boot.inc\\",这个%include是nasm编译器中的预处理指令是让编译器在编译前处理指令boot.inc文件包含在内。应该有任何编译器include其他可以包含其他文件的预处理指令。不要认为底层汇编语言应该简单到贫穷。哈哈,这与语言无关。编译器应该添加以便于开发人员管理代码。boot.inc内容很简单,目前只有两句话,文件内容如下:

1 ;------------- loader和kernel ----------2 LOADER_BASE_ADDR equ 0x9003 LOADER_START_SECTOR equ 0x2

boot.inc是我们的配置文件,目前,我们在其中写下了加载器的配置信息,未来将在此添加更多的配置信息。你看到的这两句话也是预处理命令,是的nasm与C语言中的宏相同。你看到的这两句话也是预处理命令,是的nasm提供的宏和C语言中的宏是一回事。nasm语法是:红名 equ 电脑 C语言中的宏是由#define实现指令。所以LOADER_BASE_ADDR和LOADER_START_SECTOR是两个红名。

LOADER_BASE_ADDR是定义了loader内存中的位置,MBR要把loader读完后把硬盘放在这里。如前所述,其值为0x900,说明将来loader内存地址0x900处。

LOADER_START_SECTOR是定义了loader逻辑扇区地址在硬盘上,即LBA地址。我之前跟你解释过,等于0x2,说明loader放在第二个扇区。

接下来的4~48行和上一版没什么区别,不用说。

50~52行是函数rd_disk_m_16传递参数。在此,汇编语言中定义的函数(或例程),proc),由于汇编语言可以直接操作寄存器,可以使用寄存器或堆栈传输参数。由于寄存器不能直接在c语言中操作,我们将体验如何用寄存器传输参数的函数。此外,使用寄存器传输参数,没有固定形式,原则上使用寄存器,只要根据实际应用,不要覆盖有用的寄存器值,如果真的需要使用寄存器,只要提前备份寄存器,如备份到其他寄存器或进入堆栈。我们选择使用这个函数需要三个参数eax,bx,cx寄存器传输参数。

在寄存器eax中间是待读入扇区的起始地址,赋值后eax为定义的宏LOADER_START_SECTOR,即0x2。

寄存器cx是读入的扇区数,cx其值为1。读取多少扇区取决于实际文件的大小。因为将来会写一篇简单的文章loader,它的大小肯定不会超过512字节,所以这里读到的扇区数可以放在1。

数据从硬盘读取后放在内存中的地方,这需要寄存器bx来指定。在这里,bx寄存器值为LOADER_BASE_ADDR,即0x900。函数名rd_disk_m_意思是在16位模式下读硬盘。这个函数是我们本节的重点,大家一定要赢。

第64行的“mov esi,eax”是把eax中等值先备份到esi中。因为al在out使用指令会影响eax的低8位。

第65行是备份读取的扇区数di寄存器,di寄存器是16位,和cx大小一致。cx读取数据时会使用该值,因此在此提前备份。

第67~70行,根据我们操作硬盘的约定,先选择一个通道,往sector count将扇区数写在寄存器中。将数据写入端口通常是使用的out指令,注意out指令中dx用于存储端口号的寄存器。

属于我们的虚拟硬盘ata0,是Primar y通


电脑
点击展开全文

相关阅读

win764不识别u盘-()

()小编和大家分享的是win7系统计算机无法读取u盘解决方案教程,使用win在7系统过程中,当您想使用U盘时,当计算机无法读取U盘时,请参考以下内容yy解决方法。最近有位win7系统用户在电脑中使用u盘时,发现u盘显示不出来,所以很苦恼,那么电脑读不出u盘呢?小编整理了这个问题win7系统计算机无法读取u盘解决方案教...

2022-12-27

win7重写mbr-(win7重制电脑)

(win7重制电脑)我们在这一节之前MBR在此基础上,做一个稍微大一点的改进,经过这个改进,我们的MBR可读硬盘。听起来这是一个大的手术。我们应该使用我们以前学到的所有知识。其实没那么大,只是加了一个读写磁盘的函数,哈哈。带着兴奋和不安的心...

2022-12-27

win10怎么改账号密码-(win10怎么修改账号密码)

(win10如何修改账号密码?很多小伙伴用windows10操作系统已经有一段时间了,其操作和部分功能的使用仍然不重要。比如在XP、Win7上常用的“控制面板很难找到,首先要清楚windows10也是有“控制面板”的。在Windows设置界面中输入“控制面板可以调出我们常用的控制面板”。今天主要给大家讲讲Windows出于安全考虑,小编建议您定期修改...

2022-12-27

win7电脑每次开机要重新设置时间-(win7电脑每次开机要重新设置时间吗)

(win7电脑每次开机都要重新设置时间吗?当我们的电脑使用很长一段时间后,有些会出现这样一个问题,当电脑启动系统时间将回到几年前,校准时间下次启动它回到几年前,造成这个问题有两个主要原因,一个是系统设置问题,另一个是主板电池没有电,具体如下。方法同步设置系统时间的方法1,打开控制面板->日期和时间(或在弹出的小窗口中点击屏幕右下角的时间->点击更改日期和时间设置)->点击I...

2022-12-27

u盘启动盘还可以用吗-(u盘启动盘还可以用吗知乎)

(u启动盘还能用吗?很多小伙伴在重新安装电脑系统时都会使用u盘系统盘进行操作,那么u盘启动盘重新安装系统后还能继续使用吗?答案当然是肯定的,只要我们格式化。更系统的教程是在小白系统中重新安装官方网站系统:win10专业版电脑:联想Ideapad电脑700-15ISK-ISE1.首先,我们将u盘启动盘插入电脑,然后右键...

2022-12-27

191路由网 - 192.168.1.1,192.168.0.1无线路由器设置教程

版权声明:本站的文章和图片来自互联网收集,仅做分享之用如有侵权请联系站长,我们将在24小时内删除