zoukankan      html  css  js  c++  java
  • 自制操作系统-使用汇编显示 hello world

    Windows (开机)读软盘第一个扇区的读法的具体表格

    Hello World汇编版

    就是将16进制编写的代码使用汇编语言编写出来

    ; cherry-os
    ORG 0x7c00 ;指定程序装载的位置
    
    ;下面用于描述FAT12格式的软盘
    JMP entry
    DB 0x90
    DB "CHRRYIPL" ;启动区的名称可以是任意的字符串,但长度必须是8字节
    DW 512; 每一个扇区的大小,必须是512字节
    DB 1 ;簇的大小(必须为1个扇区)
    DW 1 ;FAT的起始位置(一般从第一个扇区开始)
    DB 2 ;FAT的个数 必须是2
    DW 224;根目录的大小 一般是224项
    DW 2880; 该磁盘的大小 必须是2880扇区
    DB 0xf0;磁盘的种类 必须是0xf0
    DW 9;FAT的长度 必须是9扇区
    DW 18;1个磁道(track) 有几个扇区 必须是18
    DW 2; 磁头个数 必须是2
    DD 0; 不使用分区,必须是0
    DD 2880; 重写一次磁盘大小
    DB 0,0,0x29 ;扩展引导标记 固定0x29
    DD 0xffffffff ;卷列序号
    DB "CHERRY-OS  " ;磁盘的名称(11个字节)
    DB "FAT12   " ;磁盘的格式名称(8字节)
    TIMES 18 DB 0; 先空出18字节 这里与原文写法不同
    
    ;程序核心
    entry:
        MOV AX,0  ;初始化寄存器
        MOV SS,AX
        MOV SP,0x7c00
        MOV DS,AX
        MOV ES,AX
        MOV SI,msg
    putloop:
        MOV AL,[SI]
        ADD SI,1
        CMP AL,0
        JE fin
        MOV AH,0x0e ;显示一个文字
        MOV BX,15 ;指定字符的颜色
        INT 0x10 ;调用显卡BIOS
        JMP putloop
    fin:
        HLT ;CPU停止,等待指令
        JMP fin ;无限循环
    msg:
        DB 0x0a , 0x0a ;换行两次
        DB "hello, cherryOS"
        DB 0x0a
        DB 0
        
        TIMES 0x1fe-($-$$) DB 0 ;填写0x00,直到0x001fe
        
        DB 0x55, 0xaa

    将这个文件保存为cherryOS.asm,使用nasm生成cherryOS.img

    nasm cherryOS.asm -o cherryOS.img

    使用QEMU运行我们的系统

    qemu-system-i386 cherryOS.img

    效果图:

    代码说明

    书中使用的是NASK,我们使用的是NASM,部分语法不同,这里总结一下。

    1
    2
    3
    4
    5
    NASK代码 NASM代码
    JMP entry -> JMP SHORT entry
    RESB <填充字节数> -> TIMES <填充字节数> DB <填充数据>
    RESB 0x7dfe-$ -> TIMES 0x1fe-($-$$) DB 0
    ALIGNB 16 -> ALIGN 16, DB 0

    下面对一个语句做专门说明

    1
    TIMES 0x1fe-($-$$) DB 0

    这一句其中出现了$与$$这样的符号。
    $ 是当前位置
    $$ 是段开始位置
    $ - $$ 是当前位置在段内的偏移
    比如我们前面输入了130个字节,那么$ - $$就是130,使用0x1fe-($ - $$)就可以计算出到达0x1fe还需要多少个字节。
    这样就保证了我们循环填充后所停在的位置是0x1fe

    上面的代码中出现了FAT12格式,IPL这样的词语。这里简要说明。

    FAT12: Windows MS-DOS所采用的软盘格式。后面我们将使用FAT32作为我们系统的格式。
    启动区: 软盘的第一个扇区成为启动区。
    扇区: 计算机读写软盘的过程中不是一个字节一个字节的读写,而是以512字节为一个单位进行读写的。因此,软盘的512个字节就是一个扇区。扇区就是最小的读写单元。
    IPL:initial program loader的缩写。启动程序加载器,启动区只有区区512字节,实在是太小了。所以我们需要一个专门的程序IPL去启动操作系统
    bootsrap:鞋带。操作系统的启动就是操作系统的一个自救过程,我们一般将操作系统的启动机制叫做bootstrap。

    几个语句:
    ORG:这个指令将告诉编译器,在代码开始执行的时候,这些代码将被装载到哪个地址中,比如我们在这里指定的地址是0x7c00。(为什么是0x7c00,IBM的大佬们当年规定的就是这个数字,我也没办法)
    JMP:JMP,跳转,转到对应的语句。
    MOV:这个不多说了,相当于赋值语句。MOV AX,0 就是将0赋值给AX
    HLT:让CPU停止动作的指令,并不是完全的停止,只是让CPU进入等待状态。
    INT:BIOS中断指令,这里我们用到INT0x10调用显卡,更多的有关BIOS的中断可以自行百度。

    四个代码块:
    entry:程序的开始,主要用来初始化寄存器和将msg的地址放入SI
    putloop:用于显示一个字符,整个流程就是这个代码段所表示的过程,AH默认0x0e,AL表示字符,BH默认为0,BL表示颜色。具体参考INT0x10中断内容。
    fin:让CPU进行等待。这个代码段要在代码中看,我们是这么写的CMP AL,0 JE fin。JE表示 jump if equal。所以这句话的意思是,如果AL==0 那么跳转到fin。也就是说我们msg中的信息显示完成后,就让CPU进入无限等待状态。
    msg:用于显示我们的内容

    几个寄存器:
    虽然这都是基础了,但是还是写一下,省的大家百度了
    AX 累加寄存器 BX 基址寄存器 CX计数寄存器 DX数据寄存器
    SP 栈指针寄存器 BP 基址指针寄存器 SI 源变址寄存器 DI 目的变址寄存器
    ES 附加段寄存器 CS 代码段寄存器 SS 堆栈段寄存器 DS 数据段寄存器
    L与H:H表示高位,L表示地位,AL表示AX寄存器低位,AH表示AX寄存器的高位

    整体流程:

      • 首先进入entry,entry中完成了对寄存器的初始化,并且将msg的地址放到SI中,此时可以将SI理解成一个在msg数据中滑动的指针。
      • msg内部是我们需要显示的字符串
      • 进入putloop,这个循环用于将msg的字符一个一个打印出来。如果AH = 0时,进入fin。
      • 进入fin,程序变为无限等待状态。

    参考:

    http://blackblog.tech/2018/07/18/CreateOSDay2/

  • 相关阅读:
    剑指 Offer 59
    665. 非递减数列
    1423. 可获得的最大点数(滑动窗口)
    1208. 尽可能使字符串相等(双指针、滑动窗口)
    643. 子数组最大平均数 I(滑动窗口)
    剑指 Offer 52. 两个链表的第一个公共节点
    295. 数据流的中位数
    888. 公平的糖果棒交换(数组、哈希表)
    Seaborn绘图工具
    Office Politics
  • 原文地址:https://www.cnblogs.com/sea-stream/p/10850361.html
Copyright © 2011-2022 走看看