linux0.11 of bootsect.s and setup.s

 1, start the computer

   1, the first computer works can be simply summarized as fetch, execute; and then fetch, then perform; so of course, cpu is a non-stop execution does not fetch the rest of the machine.
   2, then after power x86 computer architecture that is how it works? In fact, after power-on (not before loading the operating system code) will be executed first memory section of the BIOS solidified, this area is each boot to be executed, under normal circumstances is not controlled by us, the main role for some hardware environment made to detect whether there is hardware damage. Cpu work in real mode during this period. After the BIOS code is completed, cpu disk will go to 0 track 0 to 512 bytes 0x7c00 sector read at the memory address, then set cs: ip = 0x7c00, start fetch, execute. . . This 512-byte is today the focus of the operating system boot code bootsect.s to put them.
   3, bootsect.s is an operating system boot code, an operating system is started from here. Hence the importance of bootsect.s understandable.
2, bootsect.s
  effect of bootsect.s:
  . 1, bootsect.s when executed, the first memory location 0x7c00 its own code starting address 512 bytes of memory beginning moved 0x90000, then gets loaded setup.s 512 * 4 block to 0x90200 bytes starting position (which is setup.S) size.
    AX mov, # 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 inter-segment jump, jump a specific address for 9000: load_setup 
     load_setup:   

    load_setup:
    MOV DX, 0x0000 #                  
    MOV CX, 0x0002 # represents Cl starts reading from the second sector!
    MOV BX, 0x0200 # BX represents the segment offset address, read 0x90200!
    MOV AX, 0x0200 # SETUPLEN +
    int 0x13! No. start reading the disk interrupt 0x13

    ! jnc ok_load_setup After reading success jump
    mov dx, # 0x0000
    mov AX, # 0x0000
    int 0x13
    jmp load_setup
  ok_load_setup:
    JMPI 0, the SETUP! SETUP = 0x9020 period between the last branch instruction executed, 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正确代码

 

 

  

Guess you like

Origin www.cnblogs.com/Ccluck-tian/p/11827500.html