进入32位模式并导入c语言

发布时间 2023-04-25 10:58:03作者: RainbowMagic

bochs 安装

  1. 首先在bochs官网中找到bochs的最新版本的下载地址
    https://bochs.sourceforge.io/getcurrent.html
    img
    img
    img
    我这里是Windows的,直接下载Windows msi,一直点下一步就行了。
  2. 修改配置文件
    在bochs安装目录下有个bochsrc-sample.txt,这个文件bochs配置文件的实例,复制一份修改文件名称为bochsrc
    img
    打开配置文件,我们只需要修改配置文件的几项
    boot: floppy
    将引导设置成软盘引导,将之前的硬盘引导注释掉。
    img
    floppya: type=1_44, 1_44="D:\os\Lyra-os-branch\build\lyra-os.img", status=inserted, write_protected=0
    设置插入软盘大小为1.44M软盘,镜像文件为D:\os\Lyra-os-branch\build\lyra-os.img,状态是已插入,镜像保护已关闭。
    megs: 512
    设置内存大小为512M

启动报错ata0-0: could not open hard drive image file '30M.sample'
需要将#ata0-master: type=disk, mode=flat, path="30M.sample", cylinders=615, heads=6, spt=17注释掉。
非debug模式启动则是bochs -f bochs配置文件
debug模式启动则是bochsdbg -q -f bochs配置文件

制作真正的IPL

在电脑启动的时候,BIOS会将0面0道1扇区的数据结尾是不是aa55,如果是则将该硬盘的一个扇区也就是512字节加载到0x7c00-0x7eff处。如果一个操作系统仅仅一种这512字节肯定是什么都干不了的,所以我们需要在这512字节执行的过程中,将我们的操作系统从硬盘中找出来,并加载到内存中。

    mov AX, 0x0820
    MOV ES, AX
    MOV CH, 0
    MOV DH, 0
    MOV CL, 2

    MOV AH, 0x02
    MOV AL, 1
    MOV BX, 0
    MOV DL, 0x00
    INT 0x13
    JC error

JC指令也是跳转指令,如果进位标志位为1才会进行跳转。

INT 0x13为低级磁盘服务,可以直接调用INT 0x13来对磁盘进行读写。
AH = 实现功能。
AL = 处理对象的扇区数。(1 - 128)
CH = 柱面号 (0 - 1023)
CL = 扇区号 (1 - 17)
DH = 磁头号 (0-15 dec.)
DL = 驱动器号 (0=A:, 1=2nd floppy, 80h=drive 0, 81h=drive 1)
DL = 驱动器号 (0=A:, 1=2nd floppy, 80h=C:, 81h=D:)
ES:BX = 缓冲地址

AH取值:
0x00: 磁盘复位。
0x01: 获取磁盘状态,在返回中具体有些各状态操作码的含义是什么。
0x0x: 读取磁盘。
0x03: 写入磁盘
0x04: 校验磁盘
0x0c: 寻到
除此之外还有很多很多功能,实在懒得写了,具体请看: https://stanislavs.org/helppc/int_13.html
返回:
CF = 0 读取成功
= 1 读取失败
AH = 操作状态码
00 没有错误
01 将错误的命令传递给设备
02 地址标记未找到或坏扇区
03 磁盘写保护错误
04 扇区未找到
05 固定磁盘重置失败
06 磁盘已更改或已删除
07 坏的固定磁盘参数表
08 DMA 超限
09 DMA 跨过64K边界访问
0A 固定磁盘扇区标致错误
0B 坏的磁盘柱面
0C 不支持 track/invalid 媒体
0D 在固定磁盘格式上扇区数目无效
0E 检测到固定磁盘控制的数据地址标记
0F 固定磁盘DMA仲裁水平超出范围
10 磁盘读取时出现ECC/CRC错误
11 可恢复的固定磁盘数据错误,数据被ECC修复
20 控制器错误(软盘的NEC)。
40 搜索失败
80 超时,驱动器未准备好
AA 固定磁盘驱动器未准备好
BB 固定磁盘未定义错误
CC 固定磁盘在所选驱动器上的写入故障
E0 固定磁盘状态错误/错误寄存器=0
FF 感应操作失败

我们要使用的是AH = 0x02读取磁盘的功能,我们要读取的是0柱面、0磁头、2扇区、0磁盘,分别对应这寄存器CH、CL、DH、DL。
img
圆盘中的每一个圆圈都是一个柱面 ,从外到里,柱面0、柱面1、柱面2等等。
磁头则是用于读取柱面上的数据的,磁头有两个一个用于读取正面柱面,一个则是用于读取反面的柱面。
由于单个柱面为单位继续读写的话,读写的数据较大,所以我们需要将它们拼接分割成几个相同大小的空间。软盘将它们平均分为18份,也就是说一个柱面有18各扇区。
软盘柱面正反都有写数据的,一个磁头是读取正面柱面的,一个磁头用于读取反面柱面的,所以需要 * 2 才能算出柱面的真实大小
一个软盘有80个柱面、2个磁头、18个扇区、每个扇区有512B,那么这个磁盘大小空间为:80 * 2 * 18 * 512 = 1440KB

我们需要将从软盘中读取的地方加载到内存一个位置中,在实模式中,CPU的寻址方式是ES:BX,表示ES * 16 + BX来表示内存地址,在最初设计CPU时,8086中ES存储最大为0xffff,BX存储最大为0xffff,那么根据ES * 16 + BX表示最大寻址空间为 0xffff * 0x10 + 0xffff = 0x10FFEF,也就是1,114,095字节,并不到64MB,但这个空间再当时是够用,谁也没办法想到计算机发展速度那么快,到现在内存64GB也是很常见的了。
根据公式 ES = 0x0820, AX = 0,我们将数据存储到的地址是0x8200,由于0x8000 - 0x81ff是留给启动区的,所以我们要使用之后的内存空间来加载数据。