自己动手写操作系统第二章 pmtest1.asm分析
来源:互联网 发布:java 函数式编程 编辑:程序博客网 时间:2024/06/08 19:38
"pm.inc"
;描述符
;Usage:Descrptor Base,Limit,Attr
; Base :dd
; Limit:dd (Low 20 bits available)
; Attr:dw (lower 4 bits of higher byte are always 0)
DA_C EQU 98h ; 存在的只执行代码段属性值
DA_DRW EQU 92h ; 存在的可读写数据段属性值
DA_32 EQU 4000h ; 32 位段
%macro Descriptor 3
dw %2 &0FFFFh ;段界限1
dw %1 & 0FFFFh ;段基址1
db (%1 >> 16) & 0FFh;段基址2
dw ((%2 >> 8) & 0F00h) |(%3 & 0F0FFh)
;属性1+段界限2+属性2
db (%1 >> 24) & 0FFh;段基址3
%endmacro ;共8字节
%include "pm.inc"
org 0100h
;ORG 0100h的实际含义
;PSP程序段前缀
;要了解ORG 0100h,就必须先了解程序段前缀PSP(Program Segment Prefix)
;程序段前缀是一个操作系统(DOS)概念。当输入一个外部命令或通过EXEC子功能
;(系统功能调用INT21h,子功能号为4Bh)加载一个程序时,COMMAND确定当前可用内存的最低端
;作为程序段的起点,也就是程序被加载到内存空间的起点。在程序所占用内存的前256(0100h)个
;字节中,DOS会为程序创建前缀(PSP)数据区。PSP结构与CP/M中的“控制区域”概念十分接近,
;这是因为DOS就是从CP/M演变而来的。
;DOS利用PSP与被加载的程序进行通信。PSP中有程序的返回地址、程序文件名等信息。
;16位DOS中,内存的物理地址=段地址*16 + 偏移量,比如段地址0xC0h,偏移量0x50h,
;则最后的物理地址是0xC0h * 16 + 0x50h = 0xC50h
;ORG用来告诉汇编器,程序加载到内存时的初始偏移量为0x100h,用于跳过PSP。
;比如你有一个标号Test的偏移地址是0x0Bh,当编译器看见ORG 0x100h后,就会给
;这个偏移加上0x100h,编译完成的.com文件中,这个偏移就变成了0x10Bh。
;如果你没有加ORG 0100h,则偏移仍然是0x0Bh,则访问该标号时,就跑到PSP里了,
;因为程序段的前0100h个字节,都是PSP的数据,而不是用户数据。
;同理,你写ORG 0x200h,则该标号的偏移地址在编译的.com文件中,会变成0x20Bh。
jmp LABEL_BEGIN
[SECTION .gdt]
;GDT 定义了一个叫做GDT的数据结构
LABEL_GDT: Descriptor 0,0,0;空描述符
LABEL_DESC_CODE32: Descriptor 0,SegCode32Len-1,DA_C+DA_32;代码段,32位
LABEL_DESC_VIDEO: Descriptor 0B8000h,0ffffh,DA_DRW ;显存首地址
;GDT结束
GdtLen equ $-LABEL_GDT ;GDT长度
GdtPtr dw GdtLen ;GDT界限
dd 0 ;GDT基地址 在16位代码段中被重新设置
;GDT选择子
SelectorCode32 equ LABEL_DESC_CODE32-LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO-LABEL_GDT
;END OF [SECTION .gdt]
;定义26位代码 进行与GDT有关的操作
[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0100h
;初始化32位代码段描述符
xor eax,eax
mov ax,cs
shl eax,4
add eax,LABEL_SEG_CODE32
mov word [LABEL_DESC_CODE32+2],ax
shr eax,16
mov byte [LABEL_DESC_CODE32+4],al
mov byte [LABEL_DESC_CODE32+7],ah
;mov ax,cs
;shl eax,4
;将cs的值(16bit 实模式下即为当前代码段的基地址)
;左移4bit即得到当前代码段的物理基地址
;add eax,LABEL_SEF_CODE32
;此时eax即为实模式下LABEL_SEF_CODE32的物理地址
;然后再用此地址分为三部分去初始化LABEL_DESC_CODE32
;为加载gdtr做准备
xor eax,eax
mov ax,ds
shl eax,4
add eax,LABEL_GDT ;eax <-- gdt基地址
mov dword [GdtPtr+2],eax ;[GdtPtr+2] <-- gdt基地址
;加载gdtr
lgdt [GdtPtr]
;关中断
cli
;打开地址线A20
in al,92h
or al,00000010b
out 92h,al
;准备切换到保护模式
mov eax,cr0
or eax,1
mov cr0,eax
;真正进入保护模式
jmp dword SelectorCode32:0
;执行这一句会把SelectorCode32
;装入cs,并转到SelectorCode32:0处
[SECTION .S32] ;32位代码,由实模式跳入
[BITS 32]
LABEL_SEG_CODE32:
mov ax,SelectorVideo
mov gs,ax ;视频段选择子
mov edi,(80*10+0)*2 ;屏幕第10行 第0列
mov ah,0ch ;0000:黑底 1100:红字
mov al,'P'
mov [gs:edi],ax
;到此停止
jmp $
SegCode32Len equ $-LABEL_SEG_CODE32
;END of [SECTION .S32]
- 自己动手写操作系统第二章 pmtest1.asm分析
- 《自己动手写操作系统》第三章a/pmtest1.asm
- 全面剖析《自己动手写操作系统》的pmtest1.asm
- 全面剖析《自己动手写操作系统》的pmtest1.asm
- 全面剖析《自己动手写操作系统》的pmtest1.asm
- 全面剖析《自己动手写操作系统》的pmtest1.asm
- 全面剖析《自己动手写操作系统》的pmtest1.asm (转)
- 全面剖析《自己动手写操作系统》的pmtest1.asm
- 全面剖析《自己动手写操作系统》的pmtest1.asm
- 自己动手写操作体统 pmtest1.asm 详细解释
- 自己动手写操作体统 pmtest1.asm 详细解释
- 《自己动手写操作系统》第三章 pmtest1——从实模式到保护模式
- pmtest1.asm
- 自己动手写操作系统源码剖析——第三章 pmtest4.asm
- 《自己动手写操作系统》源码解析——第三章pmtest5.asm
- 自己动手写操作系统 ( chapter5/c/loader.asm完全注释 )
- 《自己动手写操作系统》第一章 boot.asm源码剖析
- 《自己动手写操作系统》多进程代码分析
- C++创建类必备的三个函数以及使用new所需要做的事
- MachineLearning(Hsuan-Tien Lin)第十一讲
- JAVA命令大全
- Winform中的Load事件处理
- leetcode-Word Search(2014.2.18)
- 自己动手写操作系统第二章 pmtest1.asm分析
- Hibernate Annotation 一对一主键关联
- Java中Vector和ArrayList的区别
- leetcode-Unique Binary Search Trees(2014.1.31)
- 如何在Eclipse中查看JDK类库的源代码
- Tomcat 无法访问中文文件名的图片
- MyEclipse取消验证Js的两种途径.
- leetcode-Triangle (2014.3.12)
- 项目名上有感叹号