setup.asm

来源:互联网 发布:广州网络教育 编辑:程序博客网 时间:2024/04/30 10:26

 %include "protect.inc" ; 常量, 宏, 以及一些说明

org  0x0500

; 实模式

 jmp SetUp_seg

;------------------------------------------------------------------------------------------
times  0x10-($-$$) db 0
KernelSize equ 512

; 此处地址: $ -> 0x500

MCRNumberDW:   dd 0
MemChkBuf: times 256 db 0
MemSizeDW:   dd 0

MemInfo1  db "________________________Memory  Allocation_______________________"
MemInfoLen1 equ $ - MemInfo1
MemInfo2  db " BaseAddrLow   BaseAddrHigh   LengthLow     LengthHigh     Type"
MemInfoLen2 equ $ - MemInfo2
;
SetupMessage db "Running Setup ... "
SMLength equ $ - SetupMessage

KernelAddr equ 12*1024  ;将kernel加载到这里( 物理地址:12*1024 )
CylindTotalNum equ 80  ;软盘正反面都面有80个柱面
SectorTotalNum  equ 18  ;软盘的每个磁道有18个扇区
SectorByte equ 512  ;软盘的每个扇区有512 byte

DriveNo  db 0
HeadNo  db 0
CylindNo db 0
SectorNo db 1
SectorNum db 0
LoadSeg  dd 0

;------------------------------------------------------------------------------------------

PrintBlank:
 push ax
 push bx
 mov bx, 000Ch
 mov al, ' '
 mov ah, 0Eh
 int 10h
 pop bx
 pop ax
 ret
;------------------------------
PrintRL:
 push ax
 push bx
 push cx
 push dx
 mov ah, 03h
 int 10h
 inc dh
 mov dl, 0
 dec ah
 int 10h 
 pop dx
 pop cx
 pop bx
 pop ax
 ret
;------------------------------ 

PrintMesg:    ; 输出字符串函数
 push bx
 push es
 mov ax, 00h
 mov es, ax
 mov ax, 1301h  ; AH = 13,  AL = 01h
 mov bx, 000Ch  ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
 int 10h   ; 10h 号中断
 pop es
 pop bx
 ret
;------------------------------
PrintHex:    ; 以十六进制的形式输出 AL
 push bx
 push cx
 push dx
 mov cx, 2
 mov dh, al   ; 用 dh 保存 al 的值
 shr al, 4   ; 先输出高位
 mov ah, 0Eh
   .hex1:
 and al, 0Fh
 add al, '0'
 cmp al, '9'
 jbe .hex2
 add al, 7   ; al 中的值大于 9 ,此时 al 已经 加了48
   .hex2:
 mov bx, 000Ch  ; 字符属性
 int 10h
 mov al, dh
 dec cx
 jnz .hex1
 pop dx
 pop cx
 pop bx
 ret
;-------------------
ReadFloppy:
 push es
.1 
 mov ax, word [LoadSeg]
 mov es, ax
 mov bx, 0
 mov ah, 02h
 mov al, [SectorNum]
 mov dl, [DriveNo]
 mov dh, [HeadNo]
 mov ch, [CylindNo]
 mov cl, [SectorNo]
 int 13h
 jc .1

 pop es
 ret
;----------------------------------------------------------------------------


SetUp_seg:
 mov ax, cs
 mov ds, ax
 mov es, ax
 mov ax, 8fc0h
 mov ss, ax
 mov sp, 0FFFFh

 mov dx, 0200h  ; dh -> 行号  dl -> 列号
 mov bp, SetupMessage ; ES:BP = 串地址(ES == 0000h)
 mov cx, SMLength
 call PrintMesg

 ; 调用int 15h 中断获得内存使用情况,保存到 MemChkBu 中
 mov ebx, 0
 mov di, MemChkBuf
Chk_loop:
 mov eax, 0E820h
 mov ecx, 20
 mov edx, 0534D4150h
 int 15h
 jc Chk_fail
 add di, 20
 inc dword [MCRNumberDW]
 cmp ebx, 0
 jne Chk_loop
 jmp Mem_display
Chk_fail:
 mov byte [MCRNumberDW], 0

 ; 显示内存可用情况
Mem_display:
; mov al ,byte [MCRNumberDW]    ;memory info 个数
; call  PrintHex
 call PrintRL

 mov dx, 0300h  ; dh -> 行号  dl -> 列号
 mov bp, MemInfo1  ; ES:BP = 串地址(ES == 0000h)
 mov cx, MemInfoLen1
 call PrintMesg
 mov dx, 0500h  ; dh -> 行号  dl -> 列号
 mov bp, MemInfo2  ; ES:BP = 串地址(ES == 0000h)
 mov cx, MemInfoLen2
 call PrintMesg

 mov dx, 0
 mov dl, byte [MCRNumberDW]
 cmp dl , 0
 je Read_floppy
 mov si, MemChkBuf
 add si,4
  Mem_L1:
 call PrintRL
 call PrintBlank
 call PrintBlank
 mov cx, 0
  Mem_L2:
 dec si
 mov al, byte [si] 
 call PrintHex 
 inc cx
 test cx, 0003h
 jne Mem_L2

 add si,8
 call PrintBlank
 call PrintBlank
 call PrintBlank
 call PrintBlank
 call PrintBlank
 call PrintBlank
 cmp cx, 14h
 jne Mem_L2
 dec dx
 jnz Mem_L1

 ;从软盘加载Kernel模块; 读内核到内存中 12*1024 处
Read_floppy:
 mov [LoadSeg], word (KernelAddr-4*1024)/16
 mov [SectorNum],byte 60   ;  13
 mov [SectorNo],byte 6
 call ReadFloppy
 ;软盘控制寄存器的I/O地址为3F0 - 3F7
 mov dl, 0  ; 停止驱动器
 mov dx, 0x3f2
 mov al, 0x0c
 out dx, al
  
 ;关中断
 cli

 ;将在 Gdtr 放置的GDT 表入口(32位基址 + 16位界限)加载到----> gdtr(共48位)中
 lgdt [Gdtr]

 ; 将GDT前八项到物理地址 0x000000 ,共 4 * 8byte = 32 byte
 mov esi, Gdt_begin
 mov edi, 0h
 mov ecx, 10*8
 cld
 rep movsb

 ;打开地址线 A20
 in al, 92h
 or al, 02h
 out 92h, al

 ;准备切换到保护模式
 mov eax, cr0
 or eax, 1
 mov cr0, eax

 ; 将 Sel_code 装入 cs , 并入跳转到 KCode
 jmp  dword Sel_Kenel:KCode_start

 

;  保护模式

[bits 32]

KCode_start :
 ;初始化堆栈段 SS、SP 和 DS、ES
 mov ax, Sel_KData     ; Sel_KData 基址为 0000h
 mov  ds, ax
 mov  es, ax
 mov ss, ax
 mov esp, 140*1024-4
 
 ; 下面显示一个字符串:  Running in Protect Mode now
 mov  ah, 0Ch     ; 0000: 黑底    1100: 红字
 mov esi, PMMessage     ; 源数据偏移
 mov edi, (80 * 12 + 0) * 2    ; 目的数据偏移。屏幕第 3 行, 第 0 列。
 cld
PM_loop:
 lodsb
 test al, al
 jz PM_end
 mov [0xB8000+edi], ax
 add edi, 2
 jmp PM_loop
PM_end:        ; 显示完毕

 ;-----------------------------------------
 
 lidt [Idtr]

 call  SetupPageTbl     ; 建立页表
 
 mov  eax, cr4
 or  eax, 20h
 mov  cr4, eax 

 mov  eax, PagePDPEBase     ;PageDirBase
 mov  cr3, eax
 mov  eax, cr0
 or  eax, 80000000h
 mov  cr0, eax
 
 jmp dword Sel_Kenel:KernelAddr

Stop :
 jmp  $      ; 死循环

;
;------------------------------------------------------------------------------------------------------
; _________ 内存各段定义 _________
;
GDTBase  equ  0
GDTLen  equ  2*1024
;
IDTBase  equ  2*1024
IDTLen  equ  2*1024
;
PagePDPEBase equ  1024
PagePDEBase equ  4*1024
PagePTEBase equ  8*1024
;
PageNum  equ 1     ; 页表个数,暂时为 1 个 (指向前4M内存),此处最多设为(640k-64k*2)/4k-1 = 127

;


; _________ GDT 定义 _________
;                                  段基址, 段界限,   属性
Gdt_begin :
  Descriptor  0,    0,   0                             ;0x0 空描述符
DesKCode   :  Descriptor  0, 0FFFFFh, Des_DPL0+Des_CR  + Des_32 + Des_G ;0x8 (内核)非一致代码段, 32
DesKData   : Descriptor  0, 0FFFFFh, Des_DPL0+Des_DRW + Des_32 + Des_G ;0x10

Gdt_end
;
Gdtr :
  dw  GDTLen     ; gdt的长度
  dd  GDTBase     ; gdt的物理地址

Idtr :
  dw IDTLen-1    ; idt的长度
  dd IDTBase     ; idt的物理地址

Sel_Kenel   equ   DesKCode    - Gdt_begin
Sel_KData   equ   DesKData    - Gdt_begin    ; 数据段描述符
Sel_stack equ   DesKData    - Gdt_begin    ; 堆栈段描述符

;
PMMessage db "Running  in  ProtectMode",0

;----------------------------------------------------------------------------------------------------
; 初始化页表

SetupPageTbl:

 mov dword [PagePDPEBase+4] , dword 0x0 
 mov dword [PagePDPEBase], PagePDEBase | PG_P  | PG_USU | PG_RWW 
 mov dword [PagePDEBase+4] , dword 0x0
 mov dword [PagePDEBase] , PagePTEBase | PG_P  | PG_USU | PG_RWW
 
 mov ecx, 512           ; 每个页表有 1024 项, 每项 4 byte
 mov edi, PagePTEBase    ; 此段首地址为 PagePTEBase
 xor eax, eax
 mov eax, PG_P | PG_USU | PG_RWW
.PageTbl:
 mov [es:edi], eax
 add edi,4
 mov [es:edi],  dword 0x0
 add edi,4
 add eax, 4096     ; 每一页指向 4K 的空间
 loop .PageTbl
 
 call deleteHole
 
 ret
 
deleteHole:
 mov esi,  PagePTEBase + 35*8   ;// 140k 对应的页表项  140 = 4k + 4k + 4k + 128k
 mov edi,  PagePTEBase + 160*8  ;// 640k 对应的页表项
 mov ecx, (1024-640)/4
.1 
 mov eax, dword [esi]
 mov ebx, dword [edi]
 mov  dword [esi], ebx
 mov  dword [edi], eax
 add edi,8
 add esi,8
 loop .1
 ret
 
;------------------------------

times  2048-($-$$) db 0

原创粉丝点击