【操作系统实践 第一章 主引导程序】

BIOS程序

OS是固定在ROM中的程序,计算机通电之后,CPU默认去执行BIOS程序。BIOS程序是固定的,几乎不会改动的,其工作主要就是检测硬件、建立中断程序、加载操作系统。

我们不用太关注BIOS程序的实现原理,只需要知道它就从主引导扇区加载512字节的数据到物理内存0x7c00处,然后将处理器的执行权交给主引导程序。

主引导扇区

现在我们知道了BIOS的工作原理,那么我们自己编写的操作系统,BIOS就是会加载我们的操作系统,然后将处理器的执行权给操作系统,这样操作系统就接管了计算机。

我们编写的第一个程序是存放在主引导扇区中的,因此我们需要知道主引导扇区是什么。主引导扇区就是硬盘中的第一个扇区,每个扇区的大小为512字节,而主引导扇区的标志为0x55、0xaa。我们编写主引导程序,大小必须是512字节,然后将其放到硬盘中,然后再执行这个程序。

内存分段

最开始的计算机是没有操作系的,大佬编写程序,然后排队去执行这个程序,那时候的程序访问地址是绝对的物理地址的,如果这个地址被别人用了,那么就一定要等别人用完了自己才能开始使用。就是当计算机有多个程序在执行,而它们使用了相同的地址,那么这时候着两个程序是不能同时执行的。

后来,为了让计算机可以同时运行多个程序,引入了分段机制,程序员在程序编写的地址只是物理地址,CPU在寻址的时候通过段地址:偏移地址计算,最终得到物理地址。
正是因为有了分段机制,程序在使用内存的时候,可以给段A给程序A使用,段B给程序B使用,就算它们在程序中的地址是相同的,因为段地址不同,它们最终计算出来的物理地址也不一样,所以它们可以同时执行。

我们在编写程序的时候,必须要声明段地址,段地址要使用段寄存器来存放,最常用的段寄存器就是DS、CS、SS等。

INT 0x10中断

在我们编写的主引导程序中,我们会调用BIOS程序提供的INT 0x10中断功能,只要是为了清屏、获取光标和显示字符。其中AH存放的是其功能号,而不同功能需要使用到的寄存器不一样,我们需要参考手册。
● 清屏
○ AH = 0x06
○ AL = 上卷行数(我们使用0)
○ BH = 行属性(这里的BX寄存器我们使用0x700)
○ (CH、CL)左上角度坐标(0,0)
○ (DH、DL)右下脚坐标(80,25)-> 0x184f
● 获取光标
○ AH = 0x03
○ BH = 0(待获取光标页号)
● 打印字符
○ ES:BP表示的是字符串的首地址(此时ES和CS指向同一个段)
○ AH = 0x13(表示的是子功能号)
○ AL = 0x01(表示的是光标的方式,我们这里写0x01就可以了)
○ BH = 0x00(表示的是当前的页号,我们这里使用的是0)
○ BL = 0x02(表示的是字符属性,这里不一定是0x02)

第一版本代码

    org 0x7c00

    ;---------- 初始化段寄存器 ----------
    mov ax, cs
    mov ds, ax 
    mov es, ax 
    mov ss, ax 
    mov sp, 0x7c00

    ;---------- 清理屏幕 ----------
    mov ah, 0x06
    mov al, 0x00
    mov bx, 0x700
    mov dx, 0x184f
    int 0x10

    ;---------- 获取光标 ----------
    mov ah, 0x03
    mov bh, 0x00
    int 0x10

    ;---------- 显示字符串 ----------
    mov ax, message
    mov bp, ax 

    mov ah, 0x13
    mov al, 0x01
    mov bh, 0x00
    mov bl, 0x02
    mov cx, 13
    int 0x10

    jmp $ 

message db "hello mbr !!!"
times 510-($-$$) db 0
db 0x55, 0xaa 

显存显示字符

我们知道实模式下只有1MB的内存空间可以使用,这块空间中不同的区域有不同的功能的,上面我们是通过调用BIOS的中断程序来显示字符,其实还有一种方法可以实现字符的显示。内存中的0xB8000~0xBFFFF是用于访问显存的,就是我们只需要将我们的字符一个一个放到这个区域中,就可以在显存中显示了。

从0xB8000开始,每个字符占用两个字节空间,低字节用于显示字符,高字节用于显示字符的属性。比如,我们要显示"Hello World!!!",我们只需要将一个一个字符逐个放到0xB8000开始的内存空间就可以了。

第二版本代码

    org 0x7c00

    ;初始化段寄存器
    mov ax, cs
    mov ds, ax 
    mov es, ax 
    mov ss, ax 
    mov sp, 0x7c00
    mov ax, 0xb800
    mov gs, ax

    ;清理屏幕
    mov ah, 0x06
    mov al, 0x00
    mov bx, 0x700
    mov dx, 0x184f
    int 0x10

    ;显示字符
    mov byte [gs:0x00], 'H'
    mov byte [gs:0x01], 0x02
    mov byte [gs:0x02], 'e'
    mov byte [gs:0x03], 0x02
    mov byte [gs:0x04], 'l'
    mov byte [gs:0x05], 0x02
    mov byte [gs:0x06], 'l'
    mov byte [gs:0x07], 0x02
    mov byte [gs:0x08], 'o'
    mov byte [gs:0x09], 0x02

    jmp $ 
times 510-($-$$) db 0
db 0x55, 0xaa ```

# 字符串转移

```bash
    org 0x7c00

    ;初始化段寄存器
    mov ax, cs
    mov ds, ax 
    mov es, ax 
    mov ss, ax 
    mov sp, 0x7c00
    mov ax, 0xb800
    mov gs, ax

    ;清理屏幕
    mov ah, 0x06
    mov al, 0x00
    mov bx, 0x700
    mov dx, 0x184f
    int 0x10

    mov ax, message
    mov si, ax 
    mov ax, 0
    mov di, ax 
    mov cx, current - message
    
show:
    mov al, [si]
    mov byte [gs:di],al
    inc di
    mov byte [gs:di], 0x02
    inc di 
    inc si
    loop show  

    jmp $
message db "Hello World"
current: 
    times 510-($-$$) db 0
    db 0x55, 0xaa 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值