MacOS环境-手写操作系统-22-突破扇区读取限制

简介: MacOS环境-手写操作系统-22-突破扇区读取限制

突破连续读取72个扇区

1.简介

因为一些特殊的原因 当我们读取超过72个扇区的时候 就会出现错误


但是我们后边的开发 肯定是要超过72个扇区的


2.代码

我们的操作系统加载器 秉承简单够用的原则


只要能把编译好的二进制内核送进内存就可以了


所以加载器的算法是 连续读取软盘扇区 将扇区的内容写入到从0x8000 开始的内存中


以下是我们内核加载器的代码

org  0x7c00;

LoadAddr EQU  08000h   


entry:
    mov  ax, 0
    mov  ss, ax
    mov  ds, ax
    mov  es, ax


    mov          BX, LoadAddr       ; ES:BX 数据存储缓冲区
    mov          CH, 1        ;CH 用来存储柱面号
    mov          DH, 0        ;DH 用来存储磁头号

readFloppy:

    cmp          byte [load_count], 0
    je           beginLoad


    mov          CL, 1        ;CL 用来存储扇区号

    mov          AH, 0x02      ;  AH = 02 表示要做的是读盘操作
    mov          AL,  18        ; AL 表示要练习读取几个扇区
    mov          DL, 0         ;驱动器编号,一般我们只有一个软盘驱动器,所以写死   
                               ;为0
    INT          0x13          ;调用BIOS中断实现磁盘读取功能

    inc          CH
    dec          byte [load_count]
    JC           fin
    add          bx, 512 * 18
    jmp          readFloppy

beginLoad:
    jmp          LoadAddr


load_count db 3 ;连续读取几个柱面

fin:
    HLT
    jmp  fin

load_count 指的是要读取的软盘柱面数


一个1.44M软盘 其中一个磁面有80个柱面 一个柱面有有两面 上面和背面 每面对应一个磁道 一个磁道有18个扇区 一个扇区有512字节


上面代码中


load_cout 的值设置为3 也就是程序要连续读取3个柱面 也就是要将软盘中大约 3* 18 * 512 字节


也就是27k的内容写入地址为08000h的内存中


随着我们开发的操作系统功能越来越强大 其代码量也越来越大 现在内核编译后 已经接近15k了 超过27k是迟早的事情


一旦超过27k 那么我们的软盘在往内存拷贝内核时 就需要连续将4个柱面 也就是72扇区的数据写入到内存中


按照设想 我们只要把上面load_cout的值改成4就可以了


然而一旦改成4 问题就出现了


因为读取4个柱面 也就要连续向内存读入18*4 = 72个扇区的内容


现在大多数BIOS提供的int 013h软盘读取中断功能


一旦发现调用代码要读取的内容有72扇区以上 就会返回失败


如果有同学尝试着把上面代码的load_cout该成4 然后再运行程序 就会发现内核加载失败


也就是int 03h 的中断调用返回失败


这样一来 一旦我们的内核大小超过27k的话 我们现在的加载器就无法正确加载了


为了绕过这个限制


现在我们加载器的做法是


不再一次连续读取18个扇区 而是一次读取一个扇区


把这个扇区的数据先读入一个给定的 大小为512字节的缓冲区内


然后再把该缓冲区的内容 拷贝到指定的内存中 也就是我们要多做一次没有意义的拷贝工作


由于我们的内核要加载到内存08000h


因此 我将08000h前512字节 也就是起始地址为07E00h开始的512字节内存作为软盘一个扇区数据的缓冲区


每次从软盘读入一个扇区数据时 先把数据写入到这个缓冲区 然后再把这个缓冲区的数据拷贝到08000h之后的地址


代码如下

org  0x7c00;

LoadAddr EQU  08000h 
BufferAddr EQU 7E0h

BaseOfStack     equ 07c00h

entry:
    mov  ax, 0
    mov  ss, ax
    mov  ds, ax

    mov  ax, BufferAddr
    mov  es, ax

    mov  ax, 0
    mov  ss, ax
    mov  sp, BaseOfStack
    mov  di, ax
    mov  si, ax


    mov          BX, 0       ; ES:BX 数据存储缓冲区
    mov          CH, 1        ;CH 用来存储柱面号
    mov          DH, 0        ;DH 用来存储磁头号
    mov          CL, 0        ;CL 用来存储扇区号


;每次都把扇区写入地址 07E00处

readFloppy:

    cmp          byte [load_count], 0
    je           beginLoad

    mov          bx, 0
    inc          cl
    mov          AH, 0x02      ;  AH = 02 表示要做的是读盘操作
    mov          AL,  1        ; AL 表示要读取几个扇区
    mov          DL, 0         ;驱动器编号,一般我们只有一个软盘驱动器,所以写死   
                               ;为0
    INT          0x13          ;调用BIOS中断实现磁盘读取功能
    JC           fin


;把刚写入07E00的一个扇区的内容写入从08000h开始的地址

copySector:
    push si
    push di
    push cx

    mov  cx, 0200h  ;缓冲区数据大小,也就是512字节
    mov  di, 0
    mov  si, 0
    mov  ax, word [load_section];es
    mov  ds, ax

copy:
    cmp  cx, 0
    je   copyend

    mov  al, byte [es:si] ;es:si指向07E00
    mov  byte [ds:di], al

    inc  di
    inc  si
    dec  cx
    jmp  copy

copyend:
    pop cx
    pop di
    pop si

    mov bx, ds
    add bx, 020h
    mov ax, 0
    mov ds, ax
    mov word [load_section], bx
    mov bx, 0

    ;end of copySector

    cmp          cl, 18
    jb           readFloppy

    inc          CH
    mov          cl, 0
    dec          byte [load_count]
    jmp          readFloppy

beginLoad:

    mov  ax, 0
    mov  ds, ax

    jmp          LoadAddr


load_count db 10 ;连续读取几个柱面
load_section dw 0800h

fin:

    HLT
    jmp  fin

有了上面改动后 加载代码能读取任意多个扇区数据到内存而不用担心Bochs虚拟机的限制


虽然我用的是Virtual Box 但据说Virtual Box使用的也是Bochs代码


所以当我连续加载扇区超过72时 Virtual Box对代码的数据读取请求也返回识别


使用上面的修改后 数据的读取问题也能得到解决了


3.MessageBox的计数器效果

这里插一个部分 就是实现一个MessageBox的计数器


void CMain(void) {
...

for(;;) {
       char* pStr = intToHexStr(counter);
       counter++;
       boxfill8(shtMsgBox->buf, 160, COL8_C6C6C6, 40, 28, 119, 43);
       showString(shtctl, shtMsgBox, 40, 28, COL8_000000,pStr);

       io_cli();
       if (fifo8_status(&keyinfo) + fifo8_status(&mouseinfo)  == 0) {

           io_sti();
       }
...
}

编译之后运行

但是最终的效果 会出现一直闪烁


相关文章
|
1天前
|
存储 C语言 iOS开发
MacOS环境-手写操作系统-48-让内核从错误中恢复
MacOS环境-手写操作系统-48-让内核从错误中恢复
9 0
|
1天前
|
存储 API C语言
MacOS环境-手写操作系统-46,47-C语言开发应用程序
MacOS环境-手写操作系统-46,47-C语言开发应用程序
8 0
|
1天前
|
编译器 API C语言
MacOS环境-手写操作系统-45-C语言开发应用程序
MacOS环境-手写操作系统-45-C语言开发应用程序
10 0
|
1天前
|
小程序 iOS开发 MacOS
MacOS环境-手写操作系统-44-运行简单的程序
MacOS环境-手写操作系统-44-运行简单的程序
7 0
|
1天前
|
存储 Java iOS开发
MacOS环境-手写操作系统-43-dir命令的实现 和 文件写入
MacOS环境-手写操作系统-43-dir命令的实现 和 文件写入
9 0
|
3月前
|
安全 Linux 网络安全
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
|
3月前
|
Linux 虚拟化 数据安全/隐私保护
部署05-VMwareWorkstation中安装CentOS7 Linux操作系统, VMware部署CentOS系统第一步,下载Linux系统,/不要忘, CentOS -7-x86_64-DVD
部署05-VMwareWorkstation中安装CentOS7 Linux操作系统, VMware部署CentOS系统第一步,下载Linux系统,/不要忘, CentOS -7-x86_64-DVD
|
2月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
|
3月前
|
Linux 测试技术 数据安全/隐私保护
阿里云Linux os copilot 运维助手初体验
阿里云Linux os copilot 初体验
389 1
阿里云Linux os copilot 运维助手初体验
|
3月前
|
弹性计算 运维 自然语言处理
阿里云OS Copilot测评:重塑Linux运维与开发体验的智能革命
阿里云OS Copilot巧妙地将大语言模型的自然语言处理能力与操作系统团队的深厚经验相结合,支持自然语言问答、辅助命令执行等功能,为Linux用户带来了前所未有的智能运维与开发体验。