起来,不愿作板儿砖的计算机
"pull oneself up by one's bootstraps"拉着自己的鞋带站起来
BIOS
BIOS做的事情
- Power is turned on.
- The CPU hands control over to the BIOS.
- The BIOS runs a program called Power-On Self Test, which determines how much memory the computer has and then confirms that critical low-level hardware is operating correctly. Any errors are indicated by sequences of audible beeps. After this, the BIOS disables all configurable devices.
- The BIOS identifies all of the computer's peripheral devices, such as hard drives and expansion cards. It first looks for plug-and-play devices and assigns a number to each, but it doesn't enable the devices at this time.
- The BIOS locates the primary boot or initial program load (IPL) device. This is usually a storage device such as a hard drive, floppy drive or CD-ROM that holds the operating system, but it can be a network card connected to a server. The BIOS also locates all of the system's secondary IPL devices.
- The BIOS builds a system resource table, assigning conflict-free resources according to which devices it found and the configuration data stored in nonvolatile RAM.
- It selects and enables the primary input (keyboard) and output (monitor) devices, so that if trouble occurs during the boot process, the BIOS can display a recovery screen and allow the user to select a stored configuration of system settings that are known to work. The BIOS captured these settings the last time the computer booted successfully, and it stores them in nonvolatile RAM.
- It scans for non-plug-and-play devices, including the Peripheral Component Interconnect (PCI) bus, and adds data from their ROMs to its resource table.
- The BIOS resolves device conflicts and configures the chosen boot device.
- It enables plug-and-play devices by calling their option ROMs with appropriate parameters.
- It starts the bootstrap loader. If, for some reason, the default IPL fails to load the operating system, the BIOS tries the next IPL device in the list.
- The IPL device loads the operating system into memory.
- The BIOS hands over control to the operating system, which may make other resource assignments.
1.上电
2.CPU将控制交给BIOS
3.BIOS开始上电自检,用来检查计算机内存大小,检查底层硬件是否正常运作.
只要有错就用蜂鸣器发出相应的叫声.
此后,BIOS禁用所有可配置设备(刚才检查的时候算是暂时启用了一下)
我装在commando上的kali物理机每次开机都会用最大声音"Bee"一下,不太聪明的亚子
4.BIOS识别计算机的所有外设,比如硬件驱动器和拓展卡(比如独立网卡独立显卡).
BIOS首先搜索所有即插即用式设备并为每个设备编号,但是此时并不将这些设备使能
5.BIOS定位主引导程序或者初始化加载程序设备.这种设备通常是一个存储设备比如硬盘,软盘,或者光驱,该设备上应当编程有操作系统,该设备甚至还可以是连接到一台服务器的网卡(这个有点离谱了)
6.BIOS 建立一张系统资源表,根据它找到的设备和存储在非易失性 RAM 中的配置数据分配无冲突资源。
7.BIOS使能基本输入(键盘)和输出(显示器)设备,如此当此后的启动过程中万一发生错误,BIOS可以打印打印恢复选项屏幕,并且让用户选择一个系统设定,然后BIOS遵旨继续执行.
BIOS会保存最后一次计算机成功启动时的设定,用那一次的设定进行恢复,这些设置被保存在非易失性RAM中
8.BIOS扫描所有非即插即用式设备,包括外设总线,并将这些设备的ROM中的数据添加到刚才建立的资源表中
9.BIOS解决设备冲突,确定boot所在的设备
10.BIOS通过使用适当参数,调用即插即用式设备的选项ROM,使能这些设备
11.BIOS启动bootstrap loader.
如果默认的IPL(InitialProgramLoader)(第9步设置的设备)不能装载操作系统,则BIOS尝试列表中的下一个IPL设备
12.IPL设备将操作系统装载进入内存
13.控制权交给操作系统,操作系统将进行其他资源分配
到此计算机启动完毕,BIOS完成使命
BIOS设置
Main视图
在我的ubuntu10.04 虚拟机上,开机的时候根据提示按下F2就可以进入BIOS选择阶段
可见BIOS这么小的系统也已经图形化了
在Main视图下,可以修改系统日期时间
Legacy Diskette
设置软驱,都2202年了,不会有人还在用软驱吧,不管他了
Primary/Second Master/Slave
Primary Master/Slave不是"主要大师/奴隶",是设置主IDE的主从通道
IDE是啥?Integrated Drive Electronics,"把控制器和盘体集成的硬盘驱动器"
我不想下到硬件看看接口是什么样的了,就认为IDE是接硬盘的
如果IDE硬盘接到IDE通道的主通道(Primary)则BIOS将其作为引导盘
Keyboard Features
"键盘特性"
NumLock
里面有一个NumLock,数字锁,也就是键盘上最右边的数字小键盘锁,Off则开机自动关闭,不让用数字键,On则开机自动开启.即使这里是Off,也可以在开机时自己按键盘上的NumLock改变状态
Keyboard auto-repeat delay: [1/2 sec]
考虑这么一长串字符你会怎么输入aaaaaaaaaaaaaaaaaaa
,是不是按住a一直不放.
有没有注意过,但是按一下a,只会输出一个a,即使手稍微慢一点,也是只会输出一个a,并没有趁机写好几个a,从单输入第一个a到计算机认为需要连续获取输入之间的时间就是这个设置,
这里设为1/2秒,即按下a之后不松开,过半秒之后就获取一长串输入
Keyboard auto-repeat rate: [30/sec]
这个是啥呢?在键盘开始一长串输入后,每秒内输入几个a呢?100个?10个?1000个?
如果是1000,那么一旦Keyboard auto-repeat delay开关被打开,则眨眼间写入了百八十个a,写太多了,又要长按Backspace退格删除,Keyboard auto-repeat delay开关又被打开,呼哧一下删了百八十个a,甚至之前写的东西也退掉了.
显然1000这个数灵敏度太高,在我的windows上大约是20个左右,确切是多少我也不知道,重新开机看看吗,那个时候又没法截图
在这个ubuntu虚拟机上可以看见是30个
这里三个设置是根据用户习惯设置的,为人性化设置的
Memory
然后展示了两个内存
就让看看,根本不让改
两个内存分别是啥呢?
去中文站点儿查,就给说"System Memory是系统内存",这傻子都会翻译还tm用你说,什么系统的内存啊?
Boot-time Diagnositc Screen
启动时诊断屏幕,这是个啥呢?
给他改成Enable然后重启看看,开机的时候会有一两秒的这个页面
没有错误的就"Passed"或者"initialized"
Advanced视图
"高级"
Multiprocessor Specification
"多处理器规范"
参考
MultiProcessor Specification - Wikipedia
MultiProcessor Specification (mit.edu)
The MultiProcessor Specification (MPS) for the x86 architecture is an open standard describing enhancements to both operating systems and firmware, which will allow them to work with x86-compatible processors in a multi-processor configuration. MPS covers Advanced Programmable Interrupt Controller (APIC) architectures.
Version 1.1 of the specification was released on April 11, 1994. Version 1.4 of the specification was released on July 1, 1995, which added extended configuration tables to improve support for multiple PCI bus configurations and improve expandability.
The Linux kernel and FreeBSD are known to support the Intel MPS. Windows NT are known to support MPS 1.1 and Windows 2000 or higher are known to support MPS 1.4. OS/2 are known to support MPS 1.1 only. Mac OS X are known to support MPS 1.4 only.
针对 x86架构的 MultiProcessor 规范(MPS)是一个开放标准,描述了对操作系统和固件的增强,这将允许它们在多处理器配置中与 x86兼容的处理器一起工作。
1.1版本于1994年4月11日发布。1.4版本于1995年7月1日发布,它添加了扩展配置表,以改进对多个 PCI 总线配置的支持,并提高可扩展性。
Linux内核和FreeBSD都是支持英特尔MPS的,
WindowsNT支持1.1版本
Windows2000以及更高版本系统支持1.4版本
多处理器规定,推测和解决多处理器对总线的竞争等等事务有关,还需要进一步阅读intel官方文件
Installed O/S
计算机启动到此时,并没有装载操作系统,如果有多系统的话,是时候做出选择了
Reset Configuration Data:
重设,在BIOS上做出的修改全都改回去?
如果真的是这个功能,那么Exit是干啥用的
Cache Memory
内存的高速缓存
第一个选项是选择启动还是关闭内存到CPU之间的高速缓存
第二个选项是系统总线的高速缓存,
...
I/O Device Configuration
"输入输出设备配置"
Serial port:串行通信接口,通过该接口,信息只能按顺序,一个一个比特传输
比如
Parallel port:并行通信接口,一次性并行传送多个比特
比如
Floppy disk controller,软盘控制器
I/O Device Configuration就是修改这些接口是否使能,信息传送方向等
Large Disk Access Mode
大硬盘访问模式
关于硬盘模式
参考BIOS设置硬盘工作模式 - 木子杰软件教程 (muzijie.com)
NORMAL普通模式是最早的IDE方式。在此方式下对硬盘访问时,BIOS和IDE控制器对参数不作任何转换。
该模式支持的最大柱面数为1024,最大磁头数为16,最大扇区数为63,每扇区字节数为 512。因此支持最大硬盘容量为:\(512×63×16×1024=528MB\)。
在此模式下即使硬盘的实际物理容量更大,但可访问的硬盘空间也只能是528MB。
LBA(Logical Block Addressing)逻辑块寻址模式。
这种模式所管理的硬盘空间突破了528KB 的瓶颈,可达8.4GB。
在LBA模式下,设置的柱面、磁头、扇区等参数并不是实际硬盘的物理参数。
在访问硬盘时,由IDE控制器把由柱面、磁头、扇区等参数确定的逻辑地址转换为实际硬盘的物理地址。
在LBA模式下,可设置的最大磁头数为255,其余参数与普通模式相同。
由此可计算出可访问的硬盘容量为:\(512×63×255×1024=8.4GB\)。
LARGE大硬盘模式。当硬盘的柱面超过1024而又不为LBA支持时可采用此种模式。
LARGE模式采取的方法是把柱面数除以2,把磁头数乘以2,其结果总容量不变。
例如,在NORMAL模式下柱面数为1220,磁头数为16,进入LARGE模式则柱面数为610,磁头数为32。
这样在DOS看来柱面数小于1024,即可正常工作。目前基本上只有LBA有实际意义了。
Local Bus IDE adapter
局部总线IDE适配器
随着CPU的飞速发展, 总线的低传输速率与微处理器的高处理速度不能同步,
造成硬盘、图形卡和其它高速外设只能通过一个狭窄而缓慢的瓶颈发送和接收数据,
从而严重影响了CPU高性能的充分发挥, 工业界因此又发展了局域总线(Local Bus)的新技术.
局域总线是在CPU总线与ISA或EISA总线之间新增加的一级总线.
它独立于CPU的结构, 与CPU的时钟频率无关, 使总线形成了一种独特的中间缓冲器.
一些高速外设, 如网卡和硬盘适配器等, 可以从ISA总线上卸下,
通过局域总线直接挂接到CPU总线上, 从而解决了低速总线在高速微处理器和高速外设之间形成的瓶颈.
什么是总线、总线的类型、局部总线、局部总线类型和什么是接口方式?什么是IDE?什么是SCSI?
Advanced Chipset Control
"高级芯片控制"
我是真的一点儿看不懂了
Security视图
设置密码用的
Boot
用+或者-调整设备顺序
这里就是"9.BIOS解决设备冲突,确定boot所在的设备"需要设置的
如果使用U盘作为安装盘,则BOOT中USB串行通用接口设置到最前
在物理机上如果U盘设置到磁盘的后面,BIOS会从磁盘启动,如果磁盘中之前有装好的操作系统,则BIOS将会唤醒那个操作系统
如果磁盘中没有操作系统则BIOS重新尝试从U盘启动
主引导记录MBR
在BIOS boot视图下,我们设置了启动顺序
现在,BIOS按照该顺序给控制权
控制交给第一个存储设备,CPU读取该设备最前面512字节
如果该设备的最后两个字节为0x55 AA
则表明这个设备可以用于启动操作系统.
否则这个设备白搭,控制交给下一个设备
磁盘上的主引导记录
整个磁盘只有一个MBR(master boot record)主引导记录,一个分区表(分区表是MBR的一部分)
最开始的218个字节就是Bootstrap code area
后面有多个磁盘分区,每个分区在分区表中都有一条记录,记录该分区的开始与结束
这里"分区"在我们小打小闹儿的笔记本子上就是指卷(简单卷)
比如我的电脑512G的固态硬盘被分成三个卷
MOS上关于这部分的描述十分滴珍贵,写的是汉字但是就是不说人话
从"表中的一个分区被标记为活动分区"这句开始,我就不知道它在说什么了
活动分区是什么,不给说,查了百科才知道
活动分区是计算机系统分区,启动操作系统的文件都装在这个分区,Windows 系统下一般被默认为C盘。
在我的linux虚拟机上观察磁盘的前512个字节
使用dd命令将磁盘的前512个字节备份到虚拟机和Executor本机的共享文件夹下面,然后在本机上用010editor打开刚才导出的备份文件
最后两个字节是0x 55 AA
表明该512个字节为MBR
从右侧的Hex视图可以看出有一些有意义的字节比如
GRUB,Hard Disk.Read.Error等等
猜测MBR在执行的时候会说一些话,可能就会说这里的ASCII编码
MBR的前466个字节是机器码,boot loader,启动引导程序,在我的虚拟机上即grub程序
第447到510字节是分区表,作用是将硬盘分成不同卷
511到512是标志主引导记录的魔数(0x55 AA)
在MOS给出的磁盘文件系统布局图上,可以发现每个磁盘分区最开始都有一个引导块,这个引导块中也可以有grub程序
主引导块之所以叫做"主",是因为它是BIOS默认调用的引导块,并且主引导块可以选择让权,即把引导工作让给其他磁盘分区中的引导块完成
一般windows系统的主引导块没有这个作用,linux有,而安装多系统的时候主引导块会相互覆盖
因此应该首先安装windows系统然后安装linux系统,如此主引导块就可以选择让权或者直接引导了
Grub
一是满足我对MBR干了什么的好奇心,而是复习一下计组8086上的汇编语言,我们对Grub进行反汇编分析
我太想知道这短短的466字节机器码,都干了什么了,他们是不是汇编语言或者C语言编译成的机器码呢?
两个阶段
第一阶段:
boot loader的主程序需要写在主引导分区或者其他磁盘分区的引导块里.
但引导块太小了,只能放下boot loader的最小主程序,相关配置在第二阶段完成
第二阶段:
grub的相关配置都在/boot/grub
下面放着
该目录下面是grub配置文件grub.cfg以及各种文件系统定义
grub的配置文件不光有
grub.cfg
redhat,ubuntu等等各种系统的grub配置文件叫法不一样
在我的ubuntu10.04虚拟机上配置文件是grub.cfg
反汇编分析
查阅了万能的网友的博客之后,linux上的nasm可以反编译
用我本机上的kali子系统反编译一下就得到了非常像计组课本上的8086汇编语言
1 | ┌──(root㉿Executor)-[/mnt/e/share] |
然后怎么分析?一共223行的汇编指令,属实高估自己的逆向能力了,与其摸着石头过河,不如先了解MBR有什么行为,然后看反汇编去取证
1 | 00000000 EB63 jmp short 0x65 |
如果使用ida反汇编分析
将mbr.bak改成mbr.exe之后使用ida打开,ida默认Segment bitness为32位,需要改成16位
一开始ida会把所有指令当作数据,只需要按一下c就可以变为指令
ida提供了交叉引用跳转提示和注释,他真的,我哭死
以下反汇编分析过程参考了
和鸟哥的Linux私房菜第19章
首先记住,BIOS将MBR中的Grub加载到主存的0x7c00处,段寄存器cs存放的是0x7c00
00000000 EB63 jmp short 0x65
第一条指令,可以看出其反汇编的格式为
内存偏移量,机器码,汇编指令
关于8086内存寻址的实现:
段寄存器对内存分段实现,8086上的跳转指令有段跳转和跨段跳转两种
CPU当前执行的指令是由
CS:IP
两个寄存器共同决定的,物理地址=段寄存器*16+偏移地址, \[ Addr=CS\times 16+IP \] 实际上就是CS的二进制表示左移4位,十六进制表示左移一位,然后加上IP如果CS保持不变则为段内跳转,如果CS改变就是跨段跳转了
段内跳转:
jmp short artx
artx就是要跳转到的绝对地址
artx是计算得到的,怎么算的呢?
在执行本条指令的时候,IP已经指向下一条指令的地址,
在实际的机器码指令中保存的是相对偏移量DISP,用这个相对偏移量加上更新了的IP得到的就是要跳转到的绝对地址
short表示为一个8位带符号数(范围\([-128,127]\)),意思是限制相对偏移量DISP的范围
在执行本条指令00000000 EB63 jmp short 0x65
时,IP=0x2
,
机器码EB63
告诉我们相对偏移量DISP=0x63
,
IP=IP+DISP=0x2+0x63=0x65
至于为什么上来就要跳转到中间,越过好多字节,这个问题在
00000096 BE057C mov si,0x7c05
我们会恍然大悟,现在看来是越过了好多"指令"没有执行,实际上不是"指令",是反汇编器将数据也反汇编成指令了
由于该跳转无条件执行,我们跟随该跳转,看看发生了什么
00000065 FA cli
关于处理器控制指令
CLI之后,IF置0,CPU不允许中断
信号量的机制应该也是这样
此处的CLI指令和后面0000007D FB sti
相互匹配
进行了一个CPU的中断关开
00000066 90 nop
空操作指令 NOP 执行该指令并不产生任何结果,仅仅消耗 3 个时钟周期的时间,常用于程序的延时等。
00000067 90 nop
同样啥也不干,耗时
00000068 F6C280 test dl,0x80
测试一下dl
是否为0x80
如果dl==0x80
则ZF=1
否则ZF=0
,设置标志位之后方便后续的条件转移等
回顾一下grub干了啥
1
2
3
4
5
6
7
8
9
10
11
12
13 1 将程序代码由0:7C00H移动到0:0600H(注,BIOS把MBR放在0:7C00H处)
2 搜索可引导分区,即80H标志
成功:goto 3
失败:跳入ROM BASIC
无效分区表:goto 5
3 读引导扇区
失败:goto 5
成功:goto 4
4 验证引导扇区最后是否为55AAH
失败:goto 5
成功:goto 6
5 打印错误进入无穷循环
6 跳到0:7C00H进行下一步启动工作80H是可引导分区的标志
硬盘的驱动器号从0x80开始编号,这里测试dl是不是80开头的,目的是判断是否是硬盘驱动
奇怪的是,在此之前的指令中并没有设置dl值的指令,因此dl此时为0,本次测试必然不通过
0000006B 7502 jnz 0x6f
关于条件跳转指令
条件转移指令的目的地址必须在现行的代码段(CS)内,并且以 当前指令指针寄存器 IP 内容为基准,转移范围内在+127~-128 的范围之内。
如果刚才判断的dl是0x80
则跳转0x6f
,
我们按照某些工作都没做,dl还没有被置为0x80,暂且不跟随跳转,顺序执行
0000006D B280 mov dl,0x80
说曹操,曹操到,现在将dl置为0x80标志某些工作已经进行了
0000006F EA747C0000 jmp 0x0:0x7c74
绝对跳转,跳转到0x7c74
,也就是0x74
位置,笑死,就在下一行
00000074 31C0 xor ax,ax
ax寄存器置零,没有用mov ax,0
是因为mov指令编码长,用xor指令优化
00000076 8ED8 mov ds,ax
0->ax->ds
ds段寄存器置0,
00000078 8ED0 mov ss,ax
ss寄存器置0
ss为stack segment,堆栈段寄存器,栈顶指针的段地址在ss寄存器中,段内偏移量在sp中,ss:sp指向栈顶
0000007A BC0020 mov sp,0x2000
本步和上一步正式建立了栈空间
0000007D FB sti
关于处理器控制指令
标志位指令,STI是开中断标志,该指令执行之后IF=1,意思是允许CPU发生中断了,
本指令和00000065 FA cli
之间的指令会被CPU一直执行不被中断,这保证了各种寄存器和堆栈等一直有效
0000007E A0647C mov al,[0x7c64]
一个直接寻址,将内存上0x7c64
这个单元中的东西放在al
寄存器中
0x7c64
所指位置代表启动盘,内核存放其中
这个单元放了啥呢? 00000064 FF db 0xff
0xff
表示使用启动盘
00000081 3CFF cmp al,0xff
蜜汁操作,刚刚把M[0x7c64]=0xff
放进al,就要检查al是不是0xff
猜测是后来M[0x7c64]
会有改变,现在是第一次执行,尚且没变
这应该是一个指针
00000083 7402 jz 0x87
如果刚才的检查通过,则跳转0x87
由于0x87
和0x83
之间(即刚才的检查没通过时),只有一条指令,我们不跟随跳转
这里检查我们是否有强制磁盘引用
00000085 88C2 mov dl,al
0x81
处的检查没有通过,即al
中不是0xff
,是多少现在不知道,先放在dl
中
在此之前涉及到dl
寄存器的有一个0000006D B280 mov dl,0x80
dl置0x80是可引导分区的标志,现在把他改了,推测为后面引导失败埋下伏笔
首次执行,本条指令不会被执行
00000087 52 push dx
dx寄存器中的东西压栈
dx中是啥呢?dh高位啃腚为0,低位有两种情况
如果00000081 3CFF cmp al,0xff
处的判断通过,则dl=0x80
否则就不是第一次执行到这里了,M[0x7c64]
已经发生过改变
我们按照第一次执行的逻辑,dx就是0xff
此时栈中状态
00000088 BB1704 mov bx,0x417
0x417->bx
0000008B 802703 and byte [bx],0x3
关于属性运算符
bx在上一条指令中已经置为0x417
了
本条指令的意思是,首先进行一个寄存器间接寻址,取M[R[bx]]=M[0x417]
取出该内存单元的最低字节的内容,看看最低位是不是两个1,如果是则置标志位ZF=1
0000008E 7406 jz 0x96
如果刚才的判断通过,则跳转0x96
跳转越过了0x90,0x93
两条指令,这是一个函数调用
00000090 BE887D mov si,0x7d88
把0x7d88
放在si寄存器,作为串操作的源头
而0x7d88
上放的是啥呢?
0x7d88
相对于本文件基地址的偏移量为0x7d88-0x7c00=0x188
去这个地方看一下
1 | 00000188 47 inc di |
都是指令?这就奇怪了,串操作的源头是一些指令,而不是一个连续的数组.
目前我们只是看出了串操作的一点雏形,将"源"放在si寄存器中,但是用串操作干了什么,尚不可知,
我们暂且保持懵逼的状态,继续向后看,我保证后面有一刻,会恍然大悟
00000093 E81C01 call 0x1b2
调用位于0x1b2
的函数
我们跟随该函数
进入循环
该调用指令,实际上进入了一个循环,但是现在看不出来
000001B2 AC lodsb
关于串装入指令
说了个什么事情呢?
1
2 mov al, [esi] ;将字节送入AL
inc esi ;指向下一个字节
在调用函数之前,si<-0x7d88
mov al, [esi]
执行之后,M[0x7d88]=M[0x188]->al
inc esi ;
执行之后,0x7d89->si
000001B3 3C00 cmp al,0x0
比较al是不是0
000001B5 75F4 jnz 0x1ab
如果al不是0则跳转0x1ab
000001AB BB0100 mov bx,0x1
1->bx
,给后面的int指令设置参数
000001AE B40E mov ah,0xe
0xe->ah
,给后面的int指令设置参数
000001B0 CD10 int 0x10
在0x1AE
中ah已经被置为0xe
,那么此中断就触发了屏幕输出,输出的是啥呢?
要显示的字符在AL上
可以看出来,从0x1AB
到0x1B5
是一个循环,循环打印字符到屏幕,循环停止的条件是碰见\0
结束标志
字符来源是0x1B2
的lodsb
,是从0x93
处的调用指令00000093 E81C01 call 0x1b2
转移过来的
lodsb
操作串的来源是00000090 BE887D mov si,0x7d88
,即内存中0x7d88
这个位置
现在我们必须要考虑清楚串操作的源头为啥是一伙子指令了
1 | 00000188 47 inc di |
观察机器码,0x47,0x52,0x55,0x42,0x00,0x20
(最后小端模式拆开)
好像前面几个都是ASCII可打印字符,尝试打印一下
竟然打印出了"GRUB"字样,这绝对不是巧合,就应该是这个字符串
原来是nasm软件无法区分指令和数据,将数据也反汇编成指令了
那么0x188到0x18c
对应G,R,U,B,\0
0x18d
上放了一个20不应该和0x18c
合起来分析
这意味着后面的反汇编很可能都是错误的,暂且不管后面的错误,我们刚才调用函数打印grub字符串的逻辑是没有错误的
在一开始我们使用010editor观察时,
后面还有好多具有实际意义的字符串
Error的ASCII编码为0x45 72 72 6f 72
确实后面的"指令"中,有这个字符串
1 | 000001A3 45 inc bp |
由此可见这一大块都是字符串
退出循环
实际上"循环"就是指循环打印0x188
上存好的grub
字符串
跳出循环的条件是
1 | 000001B2 AC lodsb |
这里al为0,即指向grub\0
最后这个\0
跳出循环即执行000001B7 C3 ret
000001B7 C3 ret
函数调用返回,返回到00000093 E81C01 call 0x1b2
的下一句00000096 BE057C mov si,0x7c05
00000096 BE057C mov si,0x7c05
0x7c05
作为串的源头,0x7c05
上是什么呢?
1 | 00000003 108ED0BC adc [bp-0x4330],cl |
M[0x3]=BC
M[0x4]=D0
M[0x5]=8E
M[0x6]=10
M[0x7]=00
00000099 F6C280 test dl,0x80
检查dl上是否还是0x80
0000009C 7448 jz 0xe6
如果dl上是0x80则跳转0xe6,如果不是则继续执行
不跟随跳转,继续执行
0000009E B441 mov ah,0x41
ah高位置0x41,是为了给int 0x13
指令设置参数
000000A0 BBAA55 mov bx,0x55aa
0x55aa->bx
,0x55aa
是主引导记录的魔数,这里应该是要进行某些判断了
000000A3 CD13 int 0x13
000000A5 5A pop dx
恢复dx=0x80
000000A6 52 push dx
0x80
压栈
这两步显得很迷,退出来又放进去
%dl 可能已被 INT 13 破坏,AH=41H。 例如,在 AST BIOS 1.04 中会发生这种情况。所以通过重复出入栈来纠正。
000000A7 723D jc 0xe6
如果标志位CF=1则跳转
哪里置的标志位呢?
jc指令与上面的int 13H ah=41H中断例程形成配合。后者的作用是判断 BIOS 是否支持扩展int13中断,如果支持,则CF=0,否则CF=1,那么jc指令就可以根据 BIOS 是否支持扩展int13中断来执行不同位置的“子程序指令”。
一般现在新的支持LBA模式的主板和Win98自带的DOS7操作系统是支持扩展INT 13的。
000000A9 81FB55AA cmp bx,0xaa55
显然之前bx置过0xaa55,此处零标志置1
000000AD 7537 jnz 0xe6
此时标志位ZF不等于0,所以jnz 0xd8不进行跳转。
谨慎起见,这条指令和上一条指令配合使用,继jc 0xd8之后,再次对int 13H ah=41H中断指令的结果进行确认。确认BIOS支持扩展int13。
0xd8 处的指令是 CHS 寻址模式的,即是说如果不支持 LBA 寻址模式,则使用 CHS。
000000AF 83E101 and cx,byte +0x1
000000B2 7432 jz 0xe6
不跳转
000000B4 31C0 xor ax,ax
ax寄存器置0
000000B6 894404 mov [si+0x4],ax
此前si寄存器被置为0x7c05,现在将0放到0x7c09,0x7c0A上
000000B9 40 inc ax
ax=0x1
000000BA 8844FF mov [si-0x1],al
si-0x1指向0x7c04,将al的第字节0x1放进去
000000BD 894402 mov [si+0x2],ax
1放到0x7c07
000000C0 C7041000 mov word [si],0x10
0x10看成一个双字(高八位全0)放到0x7c05,0x7c06
0x7c06应该为0
为啥这里要用一个"WORD",前面都没用?
因为这里直接把一个立即数放到内存上,没有经过寄存器,将寄存器搬到内存时,寄存器规格决定占用内存上几个单元
现在立即数0x10可以作为一个字节,可以作为一个字,一个双字等等,要用word规定一下0x10作为什么传送
我太难了, 这暗无天日的反汇编分析什么时候是个头啊,不分析了放一个大佬的博客吧
MBR引导程序源码理解_背风衣人的博客-CSDN博客_mbr启动代码
Kernel
不管Grub干了啥,总之,它最后加载了Kernel并把控制交给了Kernel
从哪里加载的kernel呢?在硬盘中,文件系统的/boot/
下面,vmlinuz文件,比如
问题是,现在的SATA硬盘驱动都是以模块方式添加的设备,在操作系统启起来之前,必然不可能载入模块
这个问题是用Initial RamDisk技术解决的
台湾人把它翻译成"虚拟文件系统",实际上和VFS不是一个东西
到此,操作系统就起来了,后面操作系统(kernel)会检查各种硬件,然后启动各种服务