07.保护模式下字符显示
发布日期:2021-06-29 10:21:25 浏览次数:3 分类:技术文章

本文共 3196 字,大约阅读时间需要 10 分钟。

简介

上一博文我们实现了从实模式到保护模式的切换并在屏幕上显示了简单的字符,对于保护模式给我们带来的寻址范围的变化体会可能不深入,很难体会在保护模式下的地址寻址变化。

目标

在保护模式下将一段字符串复制到1M以外的地址空间,并将字符从该地址空间显示到屏幕上。

1、kernel.s 文件如下

;全局描述符结构 8字节    ; byte7 byte6 byte5 byte4 byte3 byte2 byte1 byte0    ; byte6低四位和 byte1 byte0 表示段偏移上限    ; byte7 byte4 byte3 byte2 表示段基址        ;定义全局描述符数据结构    ;3 表示有3个参数分别用 %1、%2、%3引用参数    ;%1:段基址     %2:段偏移上限  %3:段属性    %macro GDescriptor  3        dw %2 & 0xffff        dw %1 & 0xffff        db (%1>>16) & 0xff         dw ((%2>>8) & 0x0f00) | (%3 & 0xf0ff)        db (%1>>24) & 0xff     %endmacro    DA_32       EQU 0x4000   ; 32 位段    DA_CODE     EQU 0x98     ; 只执行代码段属性值    DA_RW       EQU 0x92     ; 可读写数据段属性值    org 0x9000     jmp entry        [SECTION .gdt]    ;定义全局描述符                            段基址           段偏移上限       段属性    LABEL_GDT:           GDescriptor         0,             0,             0    LABEL_DESC_CODE:     GDescriptor         0,             SegCodeLen-1,  DA_CODE+DA_32     LABEL_DESC_VIDEO:    GDescriptor         0xb8000,       0xffff,        DA_RW    LABEL_DESC_7M:       GDescriptor         0x0700000,     0xffff,        DA_RW    ;gdt 表大小    GdtLen  equ     $-LABEL_GDT    ;gdt表偏移上限和基地址    GdtPtr  dw      GdtLen-1            dd      0    ;cpu开机进入实模式时使用的段寄存器 cs,ds,es,ss 和偏移地址组成内存地址,内存地址=段寄存器 * 16 + 偏移地址     ;保护模式中段寄存器保存的是gdt 描述表中各个描述符的偏移,也叫选择子        SelectorCode32  EQU     LABEL_DESC_CODE-LABEL_GDT    SelectorVideo   EQU     LABEL_DESC_VIDEO-LABEL_GDT    Selector7M      EQU     LABEL_DESC_7M-LABEL_GDT    [SECTION .s16]    [BITS 16]entry:    mov ax,cs     mov ds,ax    mov es,ax    mov ss,ax    mov sp,0x100     ;设置LABEL_DESC_CODE描述符段基址    mov eax,0     mov ax,cs     shl eax,4    add eax,SEG_CODE32    mov word [LABEL_DESC_CODE+2],ax    shr eax,16    mov [LABEL_DESC_CODE+4],al    mov [LABEL_DESC_CODE+7],ah    mov eax,0    mov ax,ds    shl eax,4     add eax,LABEL_GDT    mov dword [GdtPtr+2],eax    ;设置GDTR 寄存器    lgdt [GdtPtr]    cli     ;关闭可可屏蔽中断,如键盘中断    in al,0x92     or al,0x02    out 0x92,al     mov eax,cr0    or eax,1     mov cr0,eax    jmp dword SelectorCode32:0    [SECTION .s32]    [BITS 32]SEG_CODE32:       mov esi,msg     mov ax,Selector7M    mov es,ax    mov edi,0copy_msg_to_7M:    mov al,[esi]    mov [es:edi],al    inc edi    inc esi    cmp al,0    je  show_char    jmp copy_msg_to_7Mshow_char:    mov ax,SelectorVideo         ;gs 寄存器是80386新增的辅助段寄存器    mov gs,ax    ;在屏幕中间显示字符串,屏幕为每行80个字符,共25行。低字节为ascii字符编码,高字节为字符显示属性    ;可参考 《汇编语言》 王爽,屏幕显示相关章节    ;在屏幕11行20列开始显示字符    mov ax,(80*11+20)    mov ecx,2    mul ecx    mov edi,eax    mov ah,10000110b     mov esi,0     putloop:    mov al,[es:esi]    cmp al,0    je  fin    mov [gs:edi],ax    add edi,2    inc esi     jmp putloopfin:    hlt    jmp finmsg:    db 'message from 0x0500000',0SEG_CODE32_END: nop ;32为模式代码长度SegCodeLen  EQU SEG_CODE32_END-SEG_CODE32

相比于上一博文,该程序代码没有太大的变化。

1)添加了LABEL_DESC_7M段描述符和Selector7M选择子,
2)并将字符串复制到该选择子指向的内存空间,
3)修改字符显示属性为 mov ah,10000110b 实现闪烁功能

boot.s、main.c文件参考上一博文,运行结果如下

在这里插入图片描述

总结

保护模式与实模式对边最大的变化时寻址方式的变化,保护模式下地址=短地址*16+偏移地址,保护模式下地址不再是段地址左移4位(向左移动一位二进制相当于扩大2倍,222*2即16)加上偏移地址,保护模式下寻址都通过寄存器GDT,段寄存器保存的是GDT中段索引。一句话总结就是地址映射方式发生变化。

题外话

博主在编程中特别喜欢使用数学上的映射来概括抽象的东西,y = f(x),一个函数(方法)功能是映射,甚至感觉整个人类科技文明都可以使用映射来描述,道可道,非常道。细细体会

转载地址:https://blog.csdn.net/Zllvincent/article/details/83550490 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:08.C语言绘制系统界面
下一篇:06.实模式进入保护模式

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月21日 00时47分20秒