操作系统真象还原——3.完善MBR

第3章 完善MBR

  1. 编译器的工作就是给各个符号进行编址,地址通常是相对于基址的偏移量

  2. 地址 = 上一个内容的基址 + 上一个内容的大小

  3. section是伪指令,cpu不执行,起到划分代码逻辑的作用

  4. vstart的作用是为section内的数据指定一个虚拟的起始地址,具体物理地址由程序加载器决定

  5. vstrat和org功能相同,告诉编译器后面数据的起始地址,但不改变内部数据的偏移地址

  6. 实模式是指8086CPU工作的配套环境,包含了CPU

  7. CPU的组成和功能

    • 控制单元:CPU将要做的事情
    • 存储单元:存储待处理的数据,即指令中的操作数
    • 运算单元:负责算数和逻辑运算
  8. 高速缓存程序员不可见

  9. 缓存解决了速度不匹配缓存之间的数据传输问题

  10. 操作系统初次访问内存的地址,使用的是程序初始化的寄存器的值

  11. 段基址寄存器:指定了内存中一段连续区域的起始地址

  12. 代码段:指令连续排放在一起的内存区域,使用CS寄存器指定其初始地址

  13. 数据段:数据(指令操作数)排放在一起的内存区域,使用DS寄存器指定其初始地址

  14. flags寄存器表示指令存储过程中的细节和影响

  15. 通常,cx寄存器用作循环的次数控制,bx寄存器用于存储起始地址

  16. 通用寄存器的介绍

    寄存器助记名功能描述
    ax累加器accumulator使用频度最高,常用于算数逻辑运算和外设的输入输出数据
    bx基址寄存器base常用来存储一片连续内存区域的基址
    cx计数器counter计数,常用于循环指令的循环次数
    dx数据寄存器data常用于保存外设控制器的端口号地址,也可用于存储数据
    si源变址寄存器source index常用于存储字符串操作中的数据源地址
    di目的变址寄存器
    destination index
    常用于存储字符串操作中的数据目的地址
    sp栈指针寄存器
    stack pointer
    用于指向栈顶,push和pop两个对栈操作的指令会修改sp的值
    bp基址指针base pointer将栈中的数据当成普通数据进行读取
  17. 8086开始支持了段的访问基址,大大加强了灵活性

  18. mov [bx],0x5表示将立即数0x5存入ds : bx指向的内存

  19. 段基址*16 + 偏移地址 的寻址方式将16位寄存器拓展成20位寻址方式,如果超出了20位最大寻址空间0xFFFFF,则称为高端内存区HMA,不使用和处理

  20. 寻址方式

    • 寄存器寻址:指令读写操作数都在寄存器中
    • 立即数寻址:立即数常用于进行赋初值
    • 内存寻址
      • 直接寻址:将直接在操作数中给出的数字作为内存地址
      • 基址寻址
      • 变址寻址
      • 基址变址寻址
  21. 栈的访问方式

    • ss : sp:按照栈的访问规则进行访问,sp始终指向栈顶
    • ss : bp:按照数据段的访问规则进行访问
    • 调用call指令时,会在栈中保留IP寄存器的值。如果是跨段访问则CS和IP的值都要保留
  22. ret指令:将当前栈顶内容弹出,并用它为IP寄存器赋值

  23. retf ( return far )指令:是从栈顶取得4 字节,栈顶处的2 字节用来替换IP寄存器,另外的2 字节用来替换CS寄存器

  24. jmp是直接跳转,call保留了当前跳转的信息,可以调用ret返回

  25. I/O接口功能:

    • 设置数据缓冲,解决CPU和外设速度不匹配
    • 设置信号的电平转换电路,CPU只能使用TTl电平
    • 设置数据格式转换,CPU只能处理数字信号
    • 设置时序控制电路来同步CPU和外部设备
    • 提供地址译码:只能有一个端口和CPU 数据交换,这就需要IO 接口提供地址译码电路,使CPU 可以选中某个端口,使其可以访问数据总线
  26. 北桥用于连接高速设备,如内存,现在一般集成到cpu中
    南桥通常用于连接低俗I/O设备

  27. I/O接口通过寄存器的方式同CPU通信,这些寄存器称为端口

  28. IA32 体系系统中,用于存储端口号的寄存器是16 位的,所以最大有65536 个端口,即0~65535

  29. 显卡的工作是不断读取显存的内容并发送到显示器上

  30. 直接操作显卡的MBR

; 主引导程序MBR
; SECTION是伪指令,cpu不运行,只是方便程序员规划程序分段使用
; `vstart=0x7c00`表示在程序编译时将起始地址编译为0x7c00
; SS存放栈顶的段地址,SP存放栈顶的偏移地址。在任何时刻 ,SS:SP都是指向栈顶元素 
; CS存放内存中代码段入口的段基址,CS:IP表示下一条要运行的指令内存地址   
    
; 初始化部分
SECTION MBR vstart=0x7c00 ; =前后不能有空格
	mov ax,cs			; 由于BIOS是通过`jmp 0:Ox7c00`转到MBR的,故cs此时为0
    mov ds,ax			; 段寄存器不能使用立即数进行赋值,可以使用通用寄存器ax
    mov es,ax
    mov ss,ax
    mov fs,ax
	mov sp,0x7c00
    mov ax,0xb800
    mov gs,ax
        
; 使用10号中断的0x06功能号,进行窗口上卷清屏,避免BIOS检测信息影响显示
	mov ax,0600h		; ah存放将要调用的中断子功能号
    mov bx,0700h
    mov cx,0			; (CL,CH)=窗口左上角的(X,Y)位置
    mov dx,184fh		; (DL,DH)=窗口右下角的(X,Y)位置(80,25)
    int 10h				; 调用中断
; 输出背景色是绿色,前景色是红色,并且跳动的字符串为“1 MBR”
    mov byte [gs:0x00],'1' 	;把字符1的ASCII写入以gs:0x00为起始,大小为1字节的内存
    mov byte [gs:0x01],0xA4	; A表示绿色背景闪烁,4表示前景色为红色
    
    mov byte [gs:0x02],' '
    mov byte [gs:0x03],0xA4
    
    mov byte [gs:0x04],'M'
    mov byte [gs:0x05],0xA4
    
    mov byte [gs:0x06],'B'
    mov byte [gs:0x07],0xA4
    
    mov byte [gs:0x08],'R'
    mov byte [gs:0x09],0xA4
    
; $表示本行指令所在的地址,$$表示本section的起始地址,$-$$表示执行代码行到段首的偏移量
	jmp $					; 在本行代码死循环
    times 510-($-$$) db 0	; 将剩余字节用0进行填充
    db 0x55,0xaa			; 最后两个字节填充MBR的标识

image-20220124213835910

  1. 现在通常使用LBA48(Logical Block Address),即使用48位比特描述一个扇区地址,最大寻址范围是 $2^{48} $bit = 128PB
  2. 数据传送方式
    • 无条件传送方式:数据随时为CPU的读取准备好,eg:寄存器,内存
    • 查询传送方式:需要先获取硬盘工作状态,判断后在进行读取操作,常用于低速设备
    • 中断传送方式:数据源设备准备好数据后通知CPU来取
    • DMA工作方式:数据原设备和内存可以直接进行大数据传输
    • I/O处理机传送方式:专用于数据处理的中央处理器,完全解放CPU
; 主引导程序MBR
; SECTION是伪指令,cpu不运行,只是方便程序员规划程序分段使用
; `vstart=0x7c00`表示在程序编译时将起始地址编译为0x7c00
; SS存放栈顶的段地址,SP存放栈顶的偏移地址。在任何时刻 ,SS:SP都是指向栈顶元素 
; CS存放内存中代码段入口的段基址,CS:IP表示下一条要运行的指令内存地址   
    
; 初始化部分
%include "boot.inc"
SECTION MBR vstart=0x7c00 ; =前后不能有空格
	mov ax,cs			; 由于BIOS是通过`jmp 0:Ox7c00`转到MBR的,故cs此时为0
    mov ds,ax			; 段寄存器不能使用立即数进行赋值,可以使用通用寄存器ax
    mov es,ax
    mov ss,ax
    mov fs,ax
	mov sp,0x7c00
    mov ax,0xb800
    mov gs,ax
        
; 使用10号中断的0x06功能号,进行窗口上卷清屏,避免BIOS检测信息影响显示
	mov ax,0600h		; ah存放将要调用的中断子功能号
    mov bx,0700h
    mov cx,0			; (CL,CH)=窗口左上角的(X,Y)位置
    mov dx,184fh		; (DL,DH)=窗口右下角的(X,Y)位置(80,25)
    int 10h				; 调用中断
; 输出背景色是绿色,前景色是红色,并且跳动的字符串为“1 MBR”
    mov byte [gs:0x00],'1'
    mov byte [gs:0x01],0xA4; A表示绿色背景闪烁,4表示前景色为红色
    
    mov byte [gs:0x02],' '
    mov byte [gs:0x03],0xA4
    
    mov byte [gs:0x04],'M'
    mov byte [gs:0x05],0xA4
    
    mov byte [gs:0x06],'B'
    mov byte [gs:0x07],0xA4
    
    mov byte [gs:0x08],'R'
    mov byte [gs:0x09],0xA4
; 硬盘扇区的写入
 	mov eax,LOADER_START_SECTOR	; 起始扇区lba地址
    mov bx,LOADER_BASE_ADDR		; 写入的地址
    mov cx,1					; 待读入的扇区数
    call rd_disk_m_16			; 以下读取程序的起始部分(一个扇区)
    
    jmp LOADER_BASE_ADDR
        
; 功能:读取硬盘的n个扇区,在16位模式下
 rd_disk_m_16:
    mov esi,eax					; 备份eax
    mov di,cx					; 备份cx
        
	; 读写硬盘
    ; 第一步:设置要读取的扇区数
    mov dx,0x1f2				; 存储端口号
    mov al,cl
    out dx,al					; 读取的扇区数(out指令用于向端口写数据)
    mov eax,esi					; 恢复ax
    ; 第二步:将LBA地址存入端口0x1f3 ~ 0x1f6
    ; LBA地址的0~7位写入端口0x1f3
    mov dx,0x1f3
    out dx,al
    ; LBA地址15~8位写入端口0x1f4
    mov cl,8
    shr eax,cl
    mov dx,0x1f4
	out dx,al
    ; LBA地址23~16位写入端口0x1f5
    shr eax,cl
    mov dx,0x1f5
    out dx,al
    shr eax,cl
    and al,0x0f		; lab第24~27位
    or al,0xe0		; 设置7-4位为1110,表示lba模式
    mov dx,0x1f6
    out dx,al
    ; 第三步:向0x1f7端口写入读命令0x20
    mov dx,0x1f7
	mov al,0x20
	out dx,al
	; 第四步:检测硬盘状态
 .not_ready: 		; 同一端口写时表示写入命令字,读时表示读入硬盘状态
	nop
	in al,dx	
	and al,0x88		;4位为1表示硬盘控制器已准备好数据传输,第7位为1表示硬盘忙
	cmp al,0x08
	jnz .not_ready	; 若未准备好,继续等待
	;5步:从0x1f0端口读数据
    ; di为要读取的扇区数,一个扇区有512字节,每读取一个字,共需di*512/2次
	mov ax,di
    mov dx,256
	mul dx
	mov cx,ax
    mov dx,0x1f0
 .go_on_read:
	in ax,dx
	mov [bx],ax
	add bx,2
	loop .go_on_read
	ret    
; $表示本行指令所在的地址,$$表示本section的起始地址,$-$$表示执行代码行到段首的偏移量
    times 510-($-$$) db 0	; 将剩余字节用0进行填充
    db 0x55,0xaa			; 最后两个字节填充MBR的标识
; 内核加载器loader
%include "boot.inc"
section loader vstart=LOADER_BASE_ADDR
; 输出背景色是绿色,前景色是红色,并且跳动的字符串为“2 LOADER”
    mov byte [gs:0x00],'2'
    mov byte [gs:0x01],0xA4; A表示绿色背景闪烁,4表示前景色为红色
    
    mov byte [gs:0x02],' '
    mov byte [gs:0x03],0xA4
    
    mov byte [gs:0x04],'L'
    mov byte [gs:0x05],0xA4
    
    mov byte [gs:0x06],'O'
    mov byte [gs:0x07],0xA4
    
    mov byte [gs:0x08],'D'
    mov byte [gs:0x09],0xA4
    
    mov byte [gs:0x0a],'E'
    mov byte [gs:0x0b],0xA4
    
    mov byte [gs:0x0c],'R'
    mov byte [gs:0x0d],0xA4
    
    jmp $			; 通过死循环使程序悬停在此
; 在bochs/include目录下的文件boot.inc,是自己编写的头文件
LOADER_BASE_ADDR equ Ox900	
LOADER_START_SECTOR equ Ox2

脚本文件:

#!/bin/bash
rm -rf ./hd.img
bin/bximage -hd -mode="flat" -size=60 -q hd.img
echo "disk creat success!!"
nasm -I include/ -o mbr.bin mbr.s
dd if=mbr.bin of=hd.img bs=512 count=1 conv=notrunc
echo "disk write success!!"
nasm -I include/ -o loader.bin loader.s
dd if=loader.bin of=hd.img bs=512 count=1 seek=2 conv=notrunc
bin/bochs -f bochsrc

成功截图:

image-20220215174717365
!!"
nasm -I include/ -o mbr.bin mbr.s
dd if=mbr.bin of=hd.img bs=512 count=1 conv=notrunc
echo “disk write success!!”
nasm -I include/ -o loader.bin loader.s
dd if=loader.bin of=hd.img bs=512 count=1 seek=2 conv=notrunc
bin/bochs -f bochsrc




成功截图:

[外链图片转存中...(img-lREavuw2-1644923609430)]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逆羽飘扬

如果有用,请支持一下。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值