linux0.11的bootsect.s和setup.s

 1、计算机的启动

  1、首先计算机的工作原理可以简单的概述为取指,执行;再取指,再执行;以此类推的过程,cpu就是一个不停取指执行不会休息的机器。
   2、那么x86结构的计算机上电后是是怎么工作的呢?其实上电后(未加载操作系统代码之前)会先执行内存中一段为BIOS固化的区域,这段区域是每次开机都必须执行的,正常情况下不被我们所控,主要作用是对一些硬件环境做出检测,是否有硬件损坏。这段期间cpu处在实模式下工作。在BIOS代码执行完毕后,cpu会去磁盘的0磁道0扇区读取512字节到内存地址的0x7c00处,然后设置cs:ip = 0x7c00,开始取指,执行。。。这512个字节就是今天的重点,操作系统的引导代码bootsect.s就放在其中。
   3、bootsect.s就是一个操作系统的引导代码,一个操作系统的起步就从这里开始。因此bootsect.s重要性无可厚非。
2、 bootsect.s
  bootsect.s的作用:
  1、bootsect.s在执行时,首先将自身代码内存位置0x7c00开始的512个字节 挪到0x90000开始的内存地址处,然后载入载入setup.s代码块到0x90200位置开始的 4*512字节(这是setup.s)的大小。
    mov ax,#BOOTSEG        !BOOTSEG=0x7c0
    mov ds,ax
    mov ax,#SETUPSEG       !SETUPSEG=0x9000
    mov es,ax
    mov cx,#256
    sub si,si
    sub di,di
    rep
    movs              ! ds:si -->  es:di 
    jmpi load_setup,SETUPSEG     !jmpi是段间跳转,具体跳转的地址为9000:load_setup 
     load_setup:   

    load_setup:
    mov dx,#0x0000                  
    mov cx,#0x0002    !cl表示从第二个扇区开始读
    mov bx,#0x0200      !bx表示段内偏移地址 ,读到0x90200
    mov ax,#0x0200+SETUPLEN
    int 0x13                           !0x13号中断开始读磁盘

    jnc ok_load_setup          !读取成功后跳转
    mov dx,#0x0000
    mov ax,#0x0000
    int 0x13
    jmp load_setup
  ok_load_setup:
    jmpi 0,SETUP   !SETUP=0x9020  最后执行段间跳转指令,cs:ip-->9020:0

  2、载入setup程序后bootsect继续执行,先向屏幕打印提示system is loading... 在此的提示就和window开机的窗口是一个原理。最后bootsect在将system模块读入后,完成使命,将执行权交到setup模块。

    mov ah,#0x03    !功能号ah=0x03
    xor bh,bh    !页号,应该是屏幕位置的页号
    int 0x10      !读取光标所在的位置 返回参数保存在dx寄存器中
    mov cx,#36     !设置字符串长度 
    mov bx,#0x0007       !bl = 0x07 表示字符属性为normal
    mov bp,#msg1     !设置字符串偏移
    mov ax,#0x07c0  !7c00是bootsect模块所在首地址
    mov es,ax      !设置字符串基地址  es:bp 表示要显示字符串的内存地址
    mov ax,#0x1301      !ah = 0x13 表示显示字符功能号,al = 0x01 表示光标的属性在bl保存。
    int 0x10      !开启中断,开始从内存中读字符到屏幕中

3、setup.s

  setup.s的功能:setup的主要功能是首先获得光标,内存,显卡,磁盘等参数存放在0x90000为起始地址的空间中,然后将system模块从起始地址0x10000的所有代码,挪到0x0000(内存的起始地址处,之后system就一直存在于此处)。然后setup会初始化gdt表,idt表等等,最后用一个很酷的指令开启32位寻址方式,进入保护模式(在bootsect和setup执行的过程中cpu一直处于实模式,16位地址模式,最多能寻址1M的空间)。保护模式可以寻址4G的内存空间。

    mov ax,#0x0001

     mov cr1,ax    !等价于lmsw ax      将cr0寄存器最后一位置1,便进入了保护模式

     jmpi 0,8

    

                            这两幅图来自linux0.11内核完全注释v3.0版

4、具体实验(用代码实践实践)

      

      截图所示是,操作系统的第二个实验,改写bootsect.s 和setup.s从新编译后,实现开机引导启动,获取硬件参数,显示到屏幕上。

实验具体代码:

SETUPLEN=2
SETUPSEG=0x9000
SETUP=0x9020
BOOTSEG=0x7c0
entry _start
_start:
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#36
mov bx,#0x0007
mov bp,#msg1
mov ax,#0x07c0
mov es,ax
mov ax,#0x1301
int 0x10

mov ax,#BOOTSEG
mov ds,ax
mov ax,#SETUPSEG
mov es,ax
mov cx,#256
sub si,si
sub di,di
rep
movs
jmpi load_setup,SETUPSEG

load_setup:
mov dx,#0x0000
mov cx,#0x0002
mov bx,#0x0200
mov ax,#0x0200+SETUPLEN
int 0x13
jnc ok_load_setup
mov dx,#0x0000
mov ax,#0x0000
int 0x13
jmp load_setup
ok_load_setup:
jmpi 0,SETUP
msg1:
.byte 13,10
.ascii "Hello OS world, my name is til"
.byte 13,10,13,10
.org 510
boot_flag:
.word 0xAA55
-------------------------------------------------以上是2019.11.9实验二6.8bootsect.s正确代码

INITSEG = 0x9000
entry _start
_start:
! Print "NOW we are in SETUP"
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#25
mov bx,#0x0007
mov bp,#msg2
mov ax,cs
mov es,ax
mov ax,#0x1301
int 0x10

mov ax,cs
mov es,ax
! init ss:sp
mov ax,#INITSEG
mov ss,ax
mov sp,#0xFF00

! Get Params
mov ax,#INITSEG
mov ds,ax
mov ah,#0x03
xor bh,bh
int 0x10
mov [0],dx
mov ah,#0x88
int 0x15
mov [2],ax
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0004
mov cx,#0x10
rep
movsb
! Be Ready to Print
mov ax,cs
mov es,ax
mov ax,#INITSEG
mov ds,ax

! Cursor Position
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#18
mov bx,#0x0007
mov bp,#msg_cursor
mov ax,#0x1301
int 0x10
mov dx,[0]
call print_hex
! Memory Size
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#14
mov bx,#0x0007
mov bp,#msg_memory
mov ax,#0x1301
int 0x10
mov dx,[2]
call print_hex
! Add KB
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#2
mov bx,#0x0007
mov bp,#msg_kb
mov ax,#0x1301
int 0x10
! Cyles
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#7
mov bx,#0x0007
mov bp,#msg_cyles
mov ax,#0x1301
int 0x10
mov dx,[4]
call print_hex
! Heads
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#8
mov bx,#0x0007
mov bp,#msg_heads
mov ax,#0x1301
int 0x10
mov dx,[6]
call print_hex
! Secotrs
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#10
mov bx,#0x0007
mov bp,#msg_sectors
mov ax,#0x1301
int 0x10
mov dx,[12]
call print_hex
inf_loop:
jmp inf_loop

print_hex:
mov cx,#4

print_digit:
rol dx,#4        !循环左移命令,最高位的4bit放在最低位的4bit上,因为4bit是一个16进制字符
mov ax,#0xe0f      !0x10号中断,功能号ah=0x0e表示显示al所对应ascii码的字符到屏幕上。这里的低16位是掩码
           !特别注意,区别上面功能号为0x13是显示es:bp内存地址的字符到屏幕上
and al,dl        !将dl的低4位通过and操作放到al的低4位
add al,#0x30      !al = al + 0x30 因为0x30~0x39为数字
cmp al,#0x3a         !判断al中存放是否为数字
jl outp          !如果为数字跳转
add al,#0x07      !否则+7表示为一个字母 因为字母a~f的ascii码为 0x41~0x46
outp:
int 0x10        !将al中的内容以ascii码形式输出到屏幕上
loop print_digit      !循环四次,把dx的每四位都拿出来输出一次
ret !四次结束后返回。

print_nl:

mov ax,#0xe0d ! CR
int 0x10
mov al,#0xa ! LF
int 0x10
ret
msg2:
.byte 13,10
.ascii "NOW we are in SETUP"
.byte 13,10,13,10
msg_cursor:
.byte 13,10
.ascii "Cursor position:"
msg_memory:
.byte 13,10
.ascii "Memory Size:"
msg_cyles:
.byte 13,10
.ascii "Cyls:"
msg_heads:
.byte 13,10
.ascii "Heads:"
msg_sectors:
.byte 13,10
.ascii "Sectors:"
msg_kb:
.ascii "KB"
.org 510
boot_flag:
.word 0xAA55
----------------------------------------------以上是2019.11.9实验二6.8 setup.s正确代码

  

原文地址:https://www.cnblogs.com/Ccluck-tian/p/11827500.html

时间: 2024-10-10 06:17:54

linux0.11的bootsect.s和setup.s的相关文章

Linux-0.11源代码阅读一 加载操作系统

x86系列CPU可以在16位实模式和32位保护模式下运行,实模式的特点是地址总线只有20位,也就是只有1MB的寻址空间,为了兼容老的CPU,Intel x86系列CPU包括最新的CPU在上电时都运行在16位的实模式下,同时在硬件上强行将CS置成0xF000,IP置成0xFFF0,那么CS:IP就指向0xFFFF0这个地址,也就是上电瞬间代码从该处开始执行,而BIOS恰恰就存储在这个地方,可以想象一下,如果连BIOS都没有将会是一个什么结果. BIOS程序被存储在计算机主板上的一块ROM芯片里,首

linux0.11学习笔记(1)

发布软件包包含内容: bootimage.Z - 具有美国键盘代码的压缩启动映像文件: rootimage.Z - 以1200kB 压缩的根文件系统映像文件: linux-0.11.tar.Z- 内核源代码文件: as86.tar.Z - linux bruce evans'二进制执行文件: 是16 位的汇编程序和装入程序: INSTALL-0.11 - 更新过的安装信息文件. 不足之处:不包括有关进程等待队列.虚拟文件系统.TCP/IP网络等方面的一些当前非常重要的代码. 目录: Linux/

Linux-0.11源代码阅读二 实模式到保护模式

bootsect部分已经执行完成,程序也跳转到setup部分: start: ! ok, the read went well so we get current cursor position and save it for ! posterity. mov ax,#INITSEG ! this is done in bootsect already, but... mov ds,ax mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 ! sa

Linux0.11内核剖析–内核体系结构 ©Fanwu

Linux0.11内核剖析–内核体系结构 ©Fanwu <Linux内核完全注释>下载:http://files.cnblogs.com/files/HanBlogs/linux-kernel.pdf(进入pdf后要点击右下角保存喔^_^) 一个完整可用的操作系统主要由 4 部分组成:硬件.操作系统内核.操作系统服务和用户应用程序,如下图所示: 用户应用程序是指那些字处理程序. Internet 浏览器程序或用户自行编制的各种应用程序: 操作系统服务程序是指那些向用户所提供的服务被看作是操作系

一站式linux0.11内核head.s代码段图表详解

阅读本文章需要的基础: 计算机组成原理:针对8086,80386CPU架构的计算机硬件体系要有清楚的认知,我们都知道操作系统是用来管理硬件的,那我们就要对本版本的操作系统所依赖的硬件体系有系统的了解,有了系统的了解后才能全面的管理它,我们对8086,80386CPU架构的计算机硬件体系如果有非常深刻的认识,我们看源代码内核的时候,就可以更可能的以一种开发者的角度去思考代码的作用,先从全局的角度去思考问题,而不是采用一种众人摸象的思维从头看到末尾. 计算机编程C语言基础:linux内核基本都是用C

Linux0.11系统中堆栈的使用方法

Linux 0.11系统中共使用了四种堆栈 一.系统引导初始化临时使用的堆栈. 二.进入保护模式后提供内核程序始化使用的堆栈,该堆栈也是后来任务0使用的用户态堆栈. 三.每个任务通过系统调用,执行内核程序时使用的堆栈,称之为任务的内核态堆栈,每个任务都有自己独立的内核态堆栈. 四.任务在用户态执行的堆栈,位于任务(进程 )逻辑地址空间近末端处使用多个栈或在不同情况下使用不同栈的主要原因. 一.由于从实模式进入保护模式,使得CPU对内存寻址访问方式发生了变化,因此需要重新设置堆栈区域. 二.为了解

《Linux0.11内核完全注释》读书笔记之内核启动方式总结

Linux0.11启动方式 BIOS启动 当PC电源打开后,80X86结构的CPU将自动进入实模式,并从0xFFFF0开始自动执行程序, 这通常是ROM-BIOS中的地址.PC机的BIOS将执行某些系统检测,并在物理地址0处开始初 始化中断向量.此后将可启动设备的第一个扇区读入内存绝对地址0x7C00处,并跳转到这 个地方. bootsect.s/setup.s bootsect.s Linux最前面的部分是boot/bootsect.s,它将由BIOS读入到内存绝对地址0x7C00处, 当它被

linux0.11编译

Ubuntu15.10邂逅linux0.11 编译环境 Ubuntu 15.10 gcc 5.2.1 问题集锦 1. as86 -0 -a -o boot/bootsect.o boot/bootsect.s make: as86:命令未找到 Makefile:92: recipe for target 'boot/bootsect' failed make: * [boot/bootsect] Error 127 #解决:下载bin86包 sudo aptitude install bin86

linux0.11 源代码阅读记录

*/--> pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;}