⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setup.asm

📁 一个用于学习的操作系统
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;调用:ah=eh;     al=要写的字符;--------------------------------------------------------print_msg:          push ax    mov  ah, 0ehdisp_next_ch:            lodsb                               ; `LODSB' loads a byte from `[DS:SI]' or `[DS:ESI]' into `AL'    cmp  al, 0    jz   quit    int  10h                            ; 利用BIOS int 10h中断ah=0eh功能进行打印字符    jmp  disp_next_chquit:       pop  ax      ret;--------------------------------------------------------;清屏;调用:ah=7;      al=向下滚动的行数;      bh=空白顶行所使用的属性;      ch=滚动的顶行;      cl=滚动的左边列;      dh=滚动的底行;      dl=滚动的右边列;--------------------------------------------------------cls:     mov ax, 0x0700        mov bh, 0x07                        ;     mov cx, 0x0000    mov dx, 0x174f                      ; 利用BIOS int 10h中断ah=07h功能进行清屏    int 0x10    ret    ;--------------------------------------------------------    ;  read_kernel_to_memory : 读指定的扇区到内存中 ;  Input parameters: ;              es:bx = 待写的内存地址;              ch = 磁道号 ;              cl = 开始的扇区号;              dh = 磁头号;              dl = 驱动器号;              [kernel_sectors] = 待读的扇区数;--------------------------------------------------------    read_kernel_to_memory:readon:    call read_one_sector            ; 每个磁道有512*18=9k字节    dec word [kernel_sectors]       ; 每读一个扇区后,待读内核扇区数减一,读到0为止    jz read_kernel_ok               ; 读取内核完成    cmp bx, 0      je got_64k                      ; 完成64k读写后,下移64k进行写next_sector:    cmp cl, SECTOR_SPER_TRACK - 1   ; 是否是磁道的最后一个扇区    ja read_next_track              ; 如果读到最后一个扇区,就开始读下一个磁道     inc cl                          ; 设置读取第cl个扇区    jmp readon                      ; 又开始读扇区got_64k:     push ax    mov ax, es    add ax, 0x1000                  ; 设置ES为下个64k的边界    mov es, ax    pop ax    jmp next_sector    read_next_track:    mov cl, 1    inc dh                          ; 下一个磁头    and dh, 0x01                    cmp dh, 0                       jnz same_track                  ; 如果磁头号为奇数,则读同一磁道第1磁头    inc ch                          ; 跳到下个磁道same_track:     jmp readon          read_kernel_ok:     ret                             ;读内核完成read_one_sector:     mov ax, 0x0201    ;mov ah, 2                       ; 利用BIOS int 13h的功能2读取磁盘    ;mov al, 1                       ; 每次读取一个扇区    ;mov dl, [boot_drv]              call read_data_from_floppy             call print_dot                  ;     add bx, 512                     ; 读内核的内存指针往后移动512字节,每一扇区为512字节,当读完64k后,bx会溢出恢复为0    ret;-------------------------------------------------------    ; 打印'.'(0x2e):;-------------------------------------------------------    print_dot:        push ax        mov ax, 0x0e2e        int 0x10        pop ax        ret         ;-------------------------------------------------------    ; read_data_from_floppy: ;          从软驱中读取,如果出错则重试3次,超过3次则死机ayed.    ;-------------------------------------------------------read_data_from_floppy:        push ax      push bx      push cx      push dx      int 0x13                    ; 读取    jnc read_ok    xor ax, ax      xor dx, dx      int 0x13                    ; 如果读失败,则软驱重启    dec byte [retries]    jz .load_error              ; 死机    pop dx      pop cx      pop bx      pop ax      jmp read_data_from_floppy.load_error      mov si, err_msg    call print_msg    jmp $                        ; 打印出错信息后死机read_ok:        mov byte [retries], 3        ; 恢复重试次数    pop dx      pop cx      pop bx      add sp, 2                    ; 保存ax    ret ;---------------------------------------------------------------------------    [BITS 32]go_pm:     mov ax, KERNEL_DS       mov ds, ax            mov es, ax        mov ss, ax            mov fs, ax         mov gs, ax                  ; 重新设置段寄存器    mov esp, 0x9FFFF            ; 重新初始化堆栈指针;移动内核到1M处move_kernel_high_mem:    mov edi, 0x100000    mov esi, 0x10000    mov ecx, 512 * 1024    rep movsb;清空原先存放内核的内存    mov cx, 0                   ;    mov ebx, PAGE_DIR           ;clear_page_table:    mov dword [ebx], 0          ;        add ebx, 4                  ;    inc cx;    cmp cx, 10240               ;      jne clear_page_table        ;          ;在0x10000处建立页目录,16M;PAGE_OFFSET >> 20得到一个page_dir_entry, 这个20最好注释一下, ;PAGE_OFFSET >> 22得到page dir index, 然后在乘以4, 所以右移20位,而不是22位     mov cx, 0                   ;    mov ebx, PAGE_DIR + (PAGE_OFFSET >> 20)           ;    mov eax, PAGE_0_ADDR + 7;create_page_table:    mov dword [ebx], eax        ;        add eax, PAGE_SIZE          ;            add ebx, 4                  ;    inc cx;        cmp cx, [PARAM_ADDR + 2]    ;      jne create_page_table       ;  ;建立线性地址与物理地址相同的页目录,一定要建立,;不然当开启分页时后马上就会出错,;等进入start_kernel之后就要取消此页映射;不然如果有编码错误,且落在低地址区,就麻烦了!!!;这里只映射0--4M    mov cx, 0                   ;    mov ebx, PAGE_DIR           ;    mov eax, PAGE_0_ADDR + 7    ;    mov dword [ebx], eax        ;    ;建立页表    mov edi, PAGE_3_ADDR + 4092 ;    mov eax, 0x00fff007        stdl1:        stosd        sub eax, 0x1000    jge l1    ;准备开启分页    ;设置页目录地址    mov eax, PAGE_DIR    mov cr3, eax    ;开启分页    mov eax, cr0    or eax, 0x80000000    mov cr0, eax    lgdt [gdtr]    ; 完成分页之后,还需得加载GDT,因为内核在0xC0000000处         mov esp, 0xC00A0000;high_init:    ; 将要进入c编写的代码,此处还没有开中断,等到全部加载后便可开中断    jmp KERNEL_CS: 0xC0100000    ; jmp to kernel     ;---------------------------------------------------------------------------; 以下定义数据;---------------------------------;加载到gdtr寄存器中,由于gdt_table会移动到线性地址0x00000800处,所以gdtr得基地址为0x00000800;---------------------------------tmpgdtr:    dw 0x01FF            ; gdt_table的16位界限    dd 0x00000800        ; 32位基地址, 此处为线性地址0x00000800gdtr:    dw 0x01FF            ; gdt_table的16位界限    dd 0xC0000800        ; 32位基地址, 此处为虚拟地址地址0xC0000800    ; 中断描述符表暂时还没有用idtr:    dw 0    dd 0x1000 ;---------------------------------;gdt段描述表 (每段占8bytes);---------------------------------gdt_tablegdt_null                ;     dd 0                ;     dd 0                ;     k_code_gdt              ; 内核代码段描述符    dw 0x0ffff          ; 段限为4GB    dw 0x0000           ; 段基址(0-15) L    db 0x00             ; 段基址(16-23) M    db 0x09a            ; 可读可执行代码段,ring0,尚未受到访问    db 0x0cf            ; 粒度为4k, 32位指令,四个段都在内存,段限为4GB    db 0x00             ; 段基址(24-31)H    k_data_gdt              ; 内核数据段描述符    dw 0x0ffff          ; 段限为4GB    dw 0x0000           ; 段基址(0-15) L    db 0x00             ; 段基址(16-23) M    db 0x092            ; 可读可写数据段,ring0,尚未受到访问    db 0x0cf            ; 粒度为4k, 段限为4GB    db 0x00             ; 段基址(24-31)H    u_code_gdt              ; 用户代码段描述符    dw 0x0ffff          ; 段限为4GB                                          dw 0x0000           ; 段基址(0-15) L                                     db 0x00             ; 段基址(16-23) M                                    db 0x0fa            ; 可读可执行代码段,ring3,尚未受到访问                db 0x0cf            ; 粒度为4k, 32位指令,四个段都在内存,段限为4GB        db 0x00             ; 段基址(24-31)H                                     u_data_gdt              ; 用户数据段描述符    dw 0x0ffff          ; 段限为4GB                                             dw 0x0000           ; 段基址(0-15) L                                        db 0x00             ; 段基址(16-23) M                                       db 0x0f2            ; 可读可写数据段,ring3,尚未受到访问                     db 0x0cf            ; 粒度为4k, 段限为4GB                                   db 0x00             ; 段基址(24-31)H                                        gdt_no_use              ;    dd 0                ;    dd 0                ;gdt_end                 ;null_sel    equ gdt_null - gdt_table        ;KERNEL_CS   equ k_code_gdt - gdt_table      ; KERNEL_CS =   8hKERNEL_DS   equ k_data_gdt - gdt_table      ; KERNEL_DS =   10h       USER_CS     equ u_code_gdt - gdt_table      ; USER_CS   =   18hUSER_DS     equ u_data_gdt - gdt_table      ; USER_DS   =   20h      boot_msg    db  "Starting Fairy Sky", 0err_msg     db  10, 13, "Kernel loading error!", 0   mem_too_small db 10, 13, "Memory is too small, die!", 0get_mem_size_err_msg db 10, 13, "Get memory failed, die!", 0boot_drv    db  0                            ; 启动驱动器号retries     db  3                            ; 启动时读磁盘失败的重试次数kernel_sectors    dw  523                    ; 内核所占的扇区数,变量times 1024 - ($ - $$)  db  0	             ; 填充两个扇区;;引导到此结束

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -