手写操作系统 02 突破512字节

122 阅读2分钟

简介

假高大上,所谓突破512字节,就是读取硬盘,然后跳到第二块扇间
  1. 第一个扇区是boot
  2. 读取硬盘
  3. 第二个扇区我们写setup(用户读取硬盘,启动保护模式,跳转到内核kernel)
  4. 写入镜像文件,就结束了
问题:既然要做第二个扇区,我们应该思考,扇区加载到哪块内存

3a220744462e4b14ba204be10cab13d8.png 有两个地方可以选择,0x7e00和0x500 这个两个地方 哪选哪个呢 随便,博主也不知道选哪个,如果有大佬知道,欢迎指导

不说废话,上代码

[org 0x7c00]
[SECTION .DATA]
BOOT_MAIN_ADDR EQU 0x500

[SECTION .TEXT]
[BITS 16]
global _start
call clear_screen

_start:
    ```
    mov ax,0
    mov ss,ax
    mov ds,ax
    mov es,ax
    mov fs,ax
    mov gs,ax
    mov si,ax

    ;清屏
    mov ax,3
    int 10h

    mov si,jmp_to_setup
    call print
    
    call read_fd
    
    jmp BOOT_MAIN_ADDR
    
    jmp $

clear_screen:
    mov ax,3
    int 10h


print:
    mov ah,0x0e
    mov bh,0
    mov bl,0x10
.loop:
    mov al,[si]
    cmp al,0
    jz .done
    int 10h
    
    inc si
    jmp .loop
.done:
    ret

read_fd:
    xor ax,ax
    xor dx,dx
    
    mov dx,0x1f2
    mov al,1
    out dx,al
    
    ;0x1f3
    inc dx
    mov al,2
    out dx,al
    
    ;0x1f4
    inc dx
    mov al,0
    out dx,al
    
    ;0x1f5
    inc dx
    mov al,0
    out dx,al
    
    ;0x1f6
    inc dx
    and al,0b11100000
    out dx,al
    
    ;0x1f7
    inc dx
    mov al,0x20
    out dx,al
.read_check:
    nop
    mov dx,0x1f7
    in al,dx
    and al,0x88
    cmp al,0x08
    jnz .read_check
    
    mov dx,0x1f0
    mov ecx,256
    ;硬盘的数据加载到BOOT_MAIN_ADDR
    mov edi,BOOT_MAIN_ADDR
.read_data:
    in ax,dx
    mov [edi],ax
    add edi,2
    loop .read_data
    ret
    


jmp_to_setup:
    db "jump to setup...",10,13,0
    

times 510-($-$$) db 0
dw 0xaa55
  1. 0x1f0 读写数据的位置

  2. 0x1f1 错误信息的位置

  3. 0x1f2 读取几个扇间

  4. 0x1f3 读取硬盘起始地址的low 8位

  5. 0x1f4 读取硬盘起始地址的mid 8位

  6. 0x1f5 读取硬盘起始地址的hid 8位

    解析 0x1f6 1110 0000

    1. 第七位和第五位固定 1
    2. 第六位是chs还是lba读取方式 0就是chs读取 1就是lba读取
    3. 第四位是主盘还是从盘
    4. 0-3位是读取硬盘起始24-27位
问题:

我要从第5块扇间开始读取,连续读取2块

  1. 读取两块 解析成汇编 mov al,0x1f2
  2. 从第五块开始读取 0000000000000000000000000101

5的28位地址

  1. 0x1f3 00000101
  2. 0x1f4 00000000
  3. 0x1f5 00000000
  4. 0x1f6 1110 0000

0x1f7 mov al 0x20

检测

read_check:

    in ax,dx
    and al,0x88
    cmp al,0x08
    jnz read_check

读取到内存哪里 mov edi,boot_main_start

清空ecx,要不然容易读取很大

xor ecx,ecx

读取多少次2B

mov ecx,256

read_data:

in ax,dx

mov [edi],ax

add edi,2

loop .read_data

ret


问题: and al,0b11100000 这里很奇怪