2 Star 5 Fork 4

稀风 / KOS

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
loader5.asm 6.18 KB
一键复制 编辑 原始数据 按行查看 历史
稀风 提交于 2022-11-26 20:05 . 修改代码注释中的错误
org 0x900
jmp CODE16_START
; 段属性的一些定义,暂时定义一些目前用得到的属性
DA_32 equ 0x4000 ; D/B = 1
DA_DR equ 0x90 ; 数据,只读
DA_DRW equ 0x92 ; 数据,可读/写
DA_DRWA equ 0x93 ; 数据,可读/写,已访问
DA_C equ 0x98 ; 代码,仅执行
DA_CR equ 0x9A ; 代码,可执行,可读
DA_CCO equ 0x9C ; 代码,一致性段,仅执行
DA_CCOR equ 0x9E ; 代码,一致性段,可执行,可读,已访问
; 段选择符属性定义
SA_RPL0 equ 0 ; RPL = 0
SA_RPL1 equ 1 ; RPL = 1
SA_RPL2 equ 2 ; RPL = 2
SA_RPL3 equ 3 ; RPL = 3
SA_TIG equ 0 ; TI = 0, GDT
SA_TIL equ 4 ; TI = 1, LDT
; 段描述符定义
%macro Descriptor 3 ; 有三个参数:段基址、段界限、段属性
dw %2 & 0xFFFF ; 段界限 1 (2 字节)
dw %1 & 0xFFFF ; 段基址 1 (2 字节)
db (%1 >> 16) & 0xFF ; 段基址 2 (1 字节)
dw ((%2 >> 8) & 0xF00) | (%3 & 0xF0FF) ; 段属性 1 + 段界限 2 + 段属性 2 (2 字节)
db (%1 >> 24) & 0xFF ; 段基址 3 (1 字节)
%endmacro ; 共 8 个字节
; 全局描述符表定义
; 段基址 段界限 段属性
GDT_BASE : Descriptor 0, 0, 0
CODE32_DESC : Descriptor 0, CODE32_SEG_LEN - 1, DA_C + DA_32
VIDEO_DESC : Descriptor 0xB8000, 0xBFFFF - 0xB8000, DA_DRWA + DA_32
DATA_DESC : Descriptor 0, DATA_SEG_LEN - 1, DA_DR + DA_32
STACK32_DESC : Descriptor 0, TOP_OF_STACK32, DA_DRW + DA_32
; ...
GDT_LEN equ $ - GDT_BASE ; GDT 长度 = 当前地址 - GDT_BASE 地址
GDT_PTR :
dw GDT_LEN - 1
dd GDT_BASE
; 段选择符定义,RPL = 0; TI = 0
CODE32_SELECTOR equ (0x0001 << 3) + SA_RPL0 + SA_TIG
VIDEO_SELECTOR equ (0x0002 << 3) + SA_RPL0 + SA_TIG
DATA_SELECTOR equ (0x0003 << 3) + SA_RPL0 + SA_TIG
STACK32_SELECTOR equ (0x0004 << 3) + SA_RPL0 + SA_TIG
msg db "Loader..." ; 使用 db 定义数据
msgLen equ $-msg ; 字符串 msg 长度
[bits 16]
CODE16_START :
xor ax, ax ; xor 指令与 and or 指令类似,两个操作数的每一对对应位都应用如下操作原则:
; 如果两个位的值相同(同为 0 或同为 1),则结果位等于 0;否则结果位等于 1
; xor ax, ax 等于 ax = 0
mov ss, ax ; 栈段 ss = 0
mov ds, ax ; 数据段 ds = 0
mov es, ax ; 附加数据段 es = 0
mov sp, 0x900 ; 设置栈,跟 0x7c00 一样,0x900 地址以下也有一段安全可用内存
; 设置光标位置 (dl, dh)
mov ah, 0x02 ; AH 功能号 = 0x02,设置光标
mov dh, 0x01 ; 设置光标行号
mov dl, 0x00 ; 设置光标列号
mov bh, 0x00 ; 页码
int 0x10
; 打印 msg
mov ax, msg
mov cx, msgLen
call print
; 初始化段描述符中的段基址
mov esi, CODE32_START
mov edi, CODE32_DESC
call InitDescItem
mov esi, DATA_SEGMENT
mov edi, DATA_DESC
call InitDescItem
mov esi, STACK32_SEGMENT
mov edi, STACK32_DESC
call InitDescItem
; 打开 A20 地址线
in al, 0x92
or al, 0000_0010B
out 0x92, al
; 加载描述符表
;mov eax, 0
;mov ax, ds
;shl eax, 4
;add eax, GDT_BASE
;mov dword [GDT_PTR + 2], eax
lgdt [GDT_PTR]
; 通知 CPU 进入保护模式,即将 CR0 寄存器的 PE(bit0) 位置 1
mov eax, cr0
or eax, 0x01
mov cr0, eax
; 刷新流水线
; 跳转到 32 位代码段继续执行
jmp dword CODE32_SELECTOR:0
; 参数: esi --> 代码段标签
; 参数: edi --> 段描述符标签
InitDescItem:
push eax
mov eax, 0
mov ax, cs
shl eax, 4
add eax, esi
mov word [edi + 2], ax
shr eax, 16
mov byte [edi + 4], al
mov byte [edi + 7], ah
pop eax
ret
; 打印字符串
; ax : 输入参数,字符串地址
; cx : 输入参数,字符串长度
print:
; 入栈
push ax
push bp
push bx
mov bp, ax ; 保存字符串地址
mov ax, 0x1301 ; 子功能号 0x13 是写字符串
mov bx, 000fh ; 页号位 0,黑底白字
int 0x10
; 出栈
pop bx
pop bp
pop ax
ret
[bits 32]
CODE32_START :
; 设置栈寄存器
mov ax, STACK32_SELECTOR
mov ss, ax
mov eax, TOP_OF_STACK32
mov esp, eax
; 设置显存段
mov ax, VIDEO_SELECTOR
mov gs, ax
; 设置数据段
mov ax, DATA_SELECTOR
mov ds, ax
mov ebp, msg2Offset
mov bl, 0x0F ; 打印属性,黑底白字
; 坐标 (0, 2)
mov dl, 0x00
mov dh, 0x02
call print_str_32
jmp $
; 使用显存方式打印字符串
; ds:ebp --> 打印的数据起始地址(相对于段基址的偏移地址)
; bl --> 打印属性
; dx --> 打印起始坐标 (dl, dh)
print_str_32:
push ebp
push eax
push edi
push cx
push dx
; 循环
s:
mov cl, [ds:ebp] ; 取地址 ds:ebp 中的数据存到 cl 寄存器
cmp cl, 0 ; 比较 cl 是否为 0
je end ; 若为 0 ,就结束打印
; 根据坐标 (dl, dh) 计算出偏移量,存入 eax 中
; (80 * dh + dl)*2 ; 每行最多显示 80 个字符
mov eax, 80
mul dh
add al, dl
shl eax, 1 ; eax = eax*2
mov edi, eax ; edi :显存中的偏移量
mov ah, bl ; 显示属性
mov al, cl ; 要打印的字符
mov [gs:edi], ax ; 显示数据放入显存
inc ebp ; 自增
inc dl ; 自增
jmp s ; 循环
; 打印结束
end:
pop dx
pop cx
pop edi
pop eax
pop ebp
ret
CODE32_SEG_LEN equ $-CODE32_START
DATA_SEGMENT:
msg2 db "Enter protection", 0 ; 以 0 为字符串结束标志
msg2Offset equ msg2 - DATA_SEGMENT ; msg2 在数据段 DATA_SEGMENT 中的偏移量
DATA_SEG_LEN equ $ - DATA_SEGMENT
STACK32_SEGMENT:
times 1024 * 4 db 0 ; 开辟 4K 的内存空间当做栈
STACK32_SEG_LEN equ $ - STACK32_SEGMENT
TOP_OF_STACK32 equ STACK32_SEG_LEN - 1 ; 栈顶
1
https://gitee.com/thin-wind/KOS.git
git@gitee.com:thin-wind/KOS.git
thin-wind
KOS
KOS
main

搜索帮助