The Way of the great learning involves manifesting virtue, renovating the people, and abiding by the highest good.

2008年12月26日星期五

80386保护模式简介

发信人: CompLangC (屠龙小猪), 信区: Assembler标 题: 【80386保护模式简介】(摘录)发信站: BBS 水木清华站 (Fri Jun 4 20:16:43 2004), 站内【80386保护模式简介】(摘录)--------------------------------------------------------------------------进入保护模式可以得到很多好处 ,让你的程式不再有 640K 限制 ,可以产生虚拟记忆体、拦 I/O ,所有的应用程式读写系统暂存器 ,产生中断....都可以完全拦截 ,而且 TSS 工作切换能力可以让你不占用 DOS 下的堆叠区 ,还有很多好处无法一一叙述 ,因此由笔者来教你如何切入保护模式吧....从简单的开始。在保护模式下有很多新的名词 ,包含 GDT.LDT.IDT 以及 CR0-CR3 ,笔者对保护模式并不清楚 ,所以底下资料可能有错误。这里使用大量的线性记忆体观念 ,请您一定要从头往後看 ,否则很可能会看不懂 ,且必须懂线性记忆体计算方式。--------------------------------------------------------------------------在进入保护模式时 ,首先你要先设定 GDT 表格 ,这个表格描述主要是来定义每个段落的记忆体起始位址与长度、存取权。 这个情形就好像传统 REAL MODE 那样 ,REAL MODE 每个区段的记忆体开始位址与长度都已经由 CPU 定死了 ,比如说当我们看到 1000:0000 ,其实它就是指记忆体的第 64K 位址 ,同理看到 2000:0000就代表是第 128K 位址 ,定址方式就是 Segment:Offset。而保护模式的段落起始位址与长度却是可程式变动的 ,这个可变动的段落起始位址与长度就是由 GDT 来设定的 ,根据这个值 ,你可以将每个段落改成64K ,或是1MB...甚至更多 ,可任意设定 1BYTE~4GB ,所以定址方式变成 Selector:Offset或许您曾用过 386DEBUG ,看过定址方式为 XXXX:XXXXXXXX ,根据後面这八位数 ,理论上可定址到 4GB ,其实这是不行的 ,如果你在 GDT 表格设定的记忆体为 1K则你尝试 DUMP 1K 以後的记忆体都会看到 FF ,就好像没有记忆体一般。---------------------------------------------------------------------------Gdtadds dw 0018h,GdtTable 32 位元线性位址GdtTable db 00h,00h,00h,00h,00h,00h,00h,00h ;db 7fh,ffh,00h,08h,0bh,93h,00h,00h ;B800:0 32Kdb ffh,ffh,56h,34h,12h,93h,0fh,78h ;^^^^^^^ ^^^^^^^^^^^ ^^^ ^^^ ^^^↑ ↑ ↑ ↑ ↑│ │ └——————93=可读写区段│ │ │ │└———————————┴————0fffff+1=1MB (Limits)│ │└—————————┴——12345678 (Base)它所代表的意思是如下图所示:(每组 8 byte)┌——————————————————————┐1│ Limit bit 0-15 │ 0 byte├——————————————————————┤3│ Base bit 0-15 │ 2├——————————┬———————————┤5│ 存取权 │ Base bit 16-23 │ 4├——————————┼———————————┤7│ Base bit 24-31 │G│..│limit bit 16-19│ 6└——————————┴———————————┘"G"代表 Limit 的单位是 Byte 或 PAGE(4K)所以....#0000 Segment not present.#0008 Base=000B8000 Limit=0000FFFF Flags=93 USE32 Byte granularity#0010 Base=12345678 Limit=000FFFFF Flags=93 USE32 Byte granularity^^^^^Selector ^^存取权设定完後 ,就是切入保护模式 ,只要将 CR0 暂存器的 Bit0 设为 '1' ,再用一个跳越指令 ,就进入保护模式了。---------------------------------------------------------------------------讲不懂没关系 ,现在来看看实例 ,这样比较容易懂..C:\>386MICE SAMPLE.EXE-G 1AEEAX=00044A1C EBX=00000003 ECX=00000000 EDX=00000100ESI=00000000 EDI=00000000 EBP=00000000 ESP=0000FFFEDS=4A1C SS=4A1C ES=4A1C FS=4A0C GS=4A0C-U 1AE4A1C:000001AE CLI4A1C:000001AF LGDT CS:[BX] ——→ DUMP CS:[BX] ——→ 4A1C:00000003 18 00 C9 A1 04 00 <--- GDT 表放在 0004A1C9 长度 18h4A1C:000001B3 MOV EAX,CR0 │4A1C:000001B6 OR EAX,1 ↓4A1C:000001BA MOV CR0,EAX 4A1C:00000009 00 00 00 00 00 00 00 00-FF FF C0 A1 04 9B 00-004A1C:000001BD JMP 01C0 4A1C:00000010 FF FF 00 80 0B 93 00 00 (GDT表)4A1C:000001BF NOP4A1C:000001C0 MOV AX,0008H4A1C:000001C3 MOV DS,AX4A1C:000001C5 MOV WORD PTR DS:[0000H],7041h由上面的 GDT 表知道 此程式共规划了三个区段 ,其中 0000 区段是不使用故区段的表示方式如下:#0000 Segment not present.#0008 Base=0004A1C0 Limit=0000FFFF Flags=9B USE32 Byte granularity#0010 Base=000B8000 Limit=0000FFFF Flags=93 USE32 Byte granularity-G 1BDEAX=00000001 EBX=00000003 ECX=00000000 EDX=00000100ESI=00000000 EDI=00000000 EBP=00000000 ESP=0000FFFEDS=4A1C SS=4A1C ES=4A1C FS=4A0C GS=4A0C4A1C:000001BD JMP 01C0-T (这儿就算是进入保护模式了)EAX=00000001 EBX=00000003 ECX=00000000 EDX=00000100ESI=00000000 EDI=00000000 EBP=00000000 ESP=0000FFFEDS=0000 SS=0000 ES=0000 FS=0000 GS=00000000:000001C0 MOV AX,0008H0000:000001C3 MOV DS,AX0000:000001C5 MOV WORD PTR DS:[0000H],7041h因为进入保护模式 ,所以 Selector 的区段应该要去查 GDT 表格 ,这个例子的 Selector 0010 的 Base = B8000 ,所以...保护模式下的 0010:00000000 = 真实模式下的 B800:0000 ,这样您懂了吗?在行号 1C5 的位址有一行写入 7041 的动作 ,就是在萤幕秀 'A' 反白字元.最後要进入真实模式时 ,只要将 CR0 的 Bit0 设为 '0' ,再用一个跳越指令就回到真实模式了..==========================================================================┌————————┐│80386 暂存器介绍│└————————┘80386 的暂存器除了扩充成 32 位元以外 ,亦增加了许多新的暂存器 ,除了一般使用者暂存器(AX.BX....SI.DI)各位已经了解以外 ,也增加了系统暂存器、以及扩充的旗标 暂存器....等等。A.使用者暂存器 → EAX.EBX.ECX.EDX.ESI,EDI.EBP.ESPB.指令指标暂存器 → CS.EIP 两个暂存器C.区段暂存器 → CS.SS.DS.ES.FS.GS虽然 80386 已经进入 32 位元时代 ,但是这几个暂存器仍是 16 位元的 ,且多了 FS.GS 两个暂存器 ,这两个暂存器并无特殊意义 ,各位可以把它当做 DS.ES来看待。D.系统暂存器A. 控制暂存器:包含 CR0.CR2.CR3 三个 ,各位可能看到漏了一个 CR1 ,原因是386.486.586 都没有此暂存器B. 除错暂存器:包含 DR0.DR1.DR2.DR3.DR6.DR7 共六个 ,也是漏了 DR4.DR5 两个 ,原因同上C. 保护模式分段控制:IDT.GDT.LDT.TR注:自 586 起新增 CR4.DR4.DR5 系统暂存器--------------------------------------------------------------------------┌————┐│工作切换│└————┘当您设定某些系统暂存器以後 ,电脑并不会马上反应所设定的工作 ,必需透过工作切换的动作才会起动 ,这个工作切换很难用文字表达 ,笔者认为工作切换就是等级切换的动作。可造成工作切换的指令包含 INT_X 、JMP TSS区段...等 ,其中 INT_X是指在 V86下的程式若发生中断 ,电脑会自动切换至保护模式 ,并呼叫保护模式下的中断处理程式 ,再由保护模式下的程式决定是否呼叫原来 V86 下的中断向量表 ,而这切换到保护模式、再切回 V86 下 , 共发生两次工作切换......┌——┐│等级│└——┘保护模式下 ,等级共有 0.1.2.3 四个等级 ,其中第0级等级最高 ,第3级最低 ,而0级因为是最高等级 ,因此也有人称为「特权等级」 ,而应用程式的等级为多少呢?这表示在 EFLAG 的 IOPL (BIT12.13) 里 ,在 V86 下的等级多半是最低的第3级 ,所以此值为 '11'。或许各位会认为自己去修改这个旗标将自己的等级调高就好了 ,事实上改好後还要经过工作切换的动作 ,等级才能被修改 ,而经过工作切换的动作後 ,你的程式控制权将转交给别人 ;再简单的说 ,发生 INT_X 时 ,电脑会将等级切换成最高等级(事实上是由中断表上决定的) ,并进入保护模式 ,之後保护模式的程式再来决定将使用者的EFLAG 切成什麽等级 ,然後再 IRETD切回 V86 ,於是应用程式根本抢不过最早进入保护模式的家伙。(这样你有办法在V86下抢到最高等级吗....不可能嘛)等级的高低可以决定自己有多少控制权 ,例如等级最高的人才可以读写系统暂存器 ,其馀的人想读写系统暂存器都会发生 General Protection Error 0D ,你可以把它想像成等级不够 ,却要读取系统资源 ,会发生 INT_0D ,而原本这行指令将不会被执行 ,而堆叠里所摆的 EIP 值也停在这行上面 ,如果 INT_0D 的处理程式不去跳过这个指令 ,则会永远停在这个指令里(形同当机)。 ※注二在 V86 下发生中断时 ,会自动 PUSH EIP.CS.EFLAG.ESP.SS......数个暂存器 ,并自动将 SS.ESP 的值替换 ,以免发生中断时 ,会动用到 V86 的堆叠 ,可是如果发生的是 General Protection Error(俗称异常),则会在 PUSH EIP 之前再多摆入一个DWORD 的错误代码 ,如果您的程式在 IRETD 前不减去这个可能存在的错误代码 ,则会发生不可预知的後果。这也是保护模式下的程式不好写的原因之一。 而 SS 与ESP所替换的值 ,则是最初进入保护模式後 ,由最高等级的人决定的(摆於TSS区段)。第二集里笔者有介绍 GDT 表 ,其中有个 93 代表可写区段 ,如果设成 89 ,则表示此区段是 TSS 表格 ,再由 TR 暂存器来指定发生中断时 ,取用那一个区段的表格.举例来说 ,下面是 GDT 表格gdttab db 000h,000h,000h,000h,000h,000h,000h,000h ;00db 0ffh,0ffh,000h,000h,000h,09bh,000h,000h ;08db 0ffh,0ffh,000h,000h,000h,093h,08fh,000h ;10db 0ffh,0ffh,000h,000h,000h,089h,000h,000h ;18db 0ffh,0ffh,000h,000h,000h,089h,000h,000h ;20db 0ffh,0ffh,000h,000h,000h,093h,000h,000h ;28db 0ffh,007h,000h,000h,000h,093h,000h,000h ;30db 0ffh,0ffh,000h,080h,00bh,093h,000h,000h ;38db 0ffh,0ffh,000h,000h,000h,093h,000h,000h ;40我们可以看到 18.20 两个 Selector 正好就是 89h ,也就是说它们俩个都可以是TSS 描述表格 ,如果 MOV AX,0018、LTR AX ,则表示发生工作切换时 ,取用 0018 的描述表格。注一:General Protection Error 发生後会去呼叫该中断 ,但是一般产生中断只会存入 EIP.CS.EFLAG.ESP.SS.... ,但是发生 General Protection Error 的话堆叠会存入 错误代码.EIP.CS.EFLAG.ESP.SS.....堆叠多存放了一个"错误代码" ,记得在切回 V86 前要将此值减去唷 !!注二:前面说发生 GP Error #0D 等於呼叫 INT_0D ,这只能说是半对 ,原因『注一』已说明 ,不再重复。--------------------------------------------------------------------------┌——————┐│TSS 表格简介│└——————┘TSS 也有人称为「工作切换」 ,其表格设定如下 ,详情可看书比较详细。tssltr dd 00000000hdd 0000ff00h ;ESPdw 0028h,0000h ;SS.0dd 0,0,0,0,0dw offset enter_v86,0000h ;EIPdd 00000200h ;EFlagdd 0,0,0,0dd 0000ff00h ;ESPdd 0,0,0dw 0010h,0000h ;ES.0dw 0008h,0000h ;CS.0dw 0028h,0000h ;SS.0dw 0010h,0000h ;DS,0dw 0010h,0000h ;FS.0dw 0010h,0000h ;GS.0dw 0000h,0000h ;LDT.0dw 0000h,0068h ;0.IOMAP起点db 1000h dup (0) ;4K IOMAP 表dw 0ffffh如果您的程式使用 JMP XXXX:YYYYYYYY 的方式跳到本区节的话 ,原本指定的YYYYYYYY 将无用途 ,因为所有的暂存器将被替换成此表格的数值(含CS.EIP) ,并完成等级切换的动作。--------------------------------------------------------------------------┌———————┐│进入 V86 模式│└———————┘clilgdt fword ptr cs:gdtaddslidt fword ptr cs:idtaddsmov eax,cr0or al,01hmov cr0,eaxmov bx,0018hltr bx ;发生工作切换时 ,SS:ESP 将参考 0018 的区段表格jmp 0020h:0000h ;进入工作切换 ,会跳到此表格内指定的 CS:EIP(LTR.JMP 不可指向同一表格)enter_v86 : ;假设您已将 CS:EIP 指向此处继续执行xor eax,eaxmov ax,codepush eax ;GSpush eax ;FSpush eax ;DSpush eax ;ESpush eax ;SSmov ax,0f000hpush eax ;ESPmov eax,00023000h ;设定VM=1 等级=3push eax ;Eflagxor eax,eaxmov ax,codepush eax ;CSmov ax,offset return_dospush eax ;EIPclts ;将 387 切换成 32 位元模式iretd ;回到 V86 (共弹出24h BYTE)紧接著就程式回到 V86 下继续执行著...--------------------------------------------------------------------------┌————————┐│中断向量表的处理│└————————┘在 V86 下产生中断後 ,电脑会自动切回保护模式 ,并从 LTR 所指定的位址取得TSS 表格 ,然後以表格内的资料重新设定 SS.ESP ,然後把 V86 下的各暂存器值摆入此堆叠内 ,在此需注意的是它摆放在堆叠的资料是32位元方式 ,所以对於 DS.ES....这类16位元暂存器摆於堆叠 ,不足部份补 '0000' ,用以凑足 32Bit。简单来说 ,在真实模式下或 V86下使用一组 SS:SP ,一但透过中断进入保护模式後 ,原先的 SS:SP 暂存器将被置换另一组数值(定义於TSS表) ,然後再将大部份的暂存器值摆放在这个新堆叠区内(包含SS.ESP) ,直到执行 IRETD 回到 V86 後 ,SS:ESP暂存器值才会从原先堆叠中弹出。换句话说 ,在 V86下发生中断会使用自己的堆叠 ,而不会破坏 V86 的堆叠区 ,这也就是为什麽像 S-ICE 除错程式执行 'T' 的命令却不会更动 User 的堆叠资料。存於保护模式堆叠内的 CS:EIP 会指向 V86下 "INT_X" 的下一行 ,而 SS:SP 值却仍维持原来数值(不像以往产生中断会自动减6 ,然後堆叠内摆入 FLAG.CS.IP),因此保护模式下处理中断的程式必需修改 V86 的 SP 值减6 ,并将 V86 的 CS.IP.FLAG摆入 V86 的堆叠 ,最後再去查 0000:0000 的表格 ,将保护模式堆叠内的 CS:EIP 值修改、指向此中断向量表 ,最後保护模式的程式执行 IRETD 返回 V86 後 ,跳到 V86下的中断所指位址 ,这样便完成整个模拟 DOS 中断的效果。PS:保护模式下堆叠会存放 EFLAG.EIP.ECS.ESP.SS...... 忘了 ,比 Real Mode 还要多好多喔。底下仅列出部份中断的处理方式....您必需处理 256 个中断表。new_20 :push 0020hjmp int_emunew_21 :push 0021hjmp int_emunew_22 :push 0022hjmp int_emunew_23 :push 0023hjmp int_emuint_emu :push bpmov bp,spadd bp,04hpush eaxpush ebxmov ax,0010h ;mov ds,ax ;(Selector 0010h 的 Base=0)mov ax,ss:[bp+0ch] ;sub ax,06h ;改V86的SP-6mov ss:[bp+0ch],ax ;xor eax,eax ;xor ebx,ebx ;修改V86下的SS:SP ,帮它摆入mov ax,ss:[bp+10h] ;INT_X 後的下一行位址 ,供V86shl eax,04h ;下的程式IRET返回INT_X的下一行用mov bx,ss:[bp+0ch] ;add ebx,eax ;mov ax,ss:[bp+00h] ;mov ds:[ebx],ax ;mov ax,ss:[bp+04h] ;mov ds:[ebx+02h],ax ;mov ax,ss:[bp+08h] ;mov ds:[ebx+04h],ax ;nopxor ebx,ebx ;mov bx,ss:[bp-02h] ;shl ebx,02h ;mov ax,ds:[ebx] ;IRETD 後到V86中断表所指的位址继续执行mov ss:[bp+00h],ax ;(查 0000:0000 的中断表)mov ax,ds:[ebx+02h] ;mov ss:[bp+04h],ax ;mov eax,ss:[bp+08h]or eax,00032000h ;等级=3 VM=1and eax,0fffffeffh ;关闭'T'旗标mov ss:[bp+08h],eaxpop ebxpop eaxpop bpadd sp,02hiretd--------------------------------------------------------------------------┌——————┐│拦 I/O 能力│└——————┘TSS 表格内除了可定义产生工作切换後 ,SS.ESP.DS.ES....各暂存器替换值 ,也可以开一块记忆体做 IOMAP ,这块记忆体每个 Bit 代表一个 PORT ,一般习惯是开4K大小 (65536埠),当某位元设定为 '1' 後 ,只要不是最高等级的人去读写此埠 ,都会发生 GP Err #0D ,当然在最低等级的 V86 程式也不例外 ,发生此错误後 ,就形同拦到 I/O 动作了 ,紧接著透过最高等级的处理程式去判断发生错误的原因 ,例如判断程式码是否为 『EC IN AL,DX』、『EE OUT DX,AL』 ,或是其它程式码 ,就可以分辨发生的原因是读或写产生的 ,拦到 I/O 後 ,你是否会写骗 I/O 的程式 ?以 S-ICE 的拦 I/O 能力为例 ,它先使用 IO-MAP 的方式去拦 I/O ,然後再判别"EE.E4.EC.E6...." 等等程式码。注:IOMAP 表是也是 TSS 表格的一部份。--------------------------------------------------------------------------┌———————┐│相容性的处理一│ 系统暂存器的相容处理法└———————┘或许您曾经在挂入 QEMM386、EMM386 之後 ,在 V86 下执行 MOV EAX,CR0 的指令 ,但是前面笔者提到读写系统暂存器必需在最高等级才可执行 ,为什麽 User 仍可在最低等级下执行本命令呢 ? 底下是欺骗方式。(User) V86 下执行 MOV EAX,CR0↓发生 General Protection 0DCPU 自动切入保护模式 ,并执行 INT_0D 的处理程式(堆叠里多储存了错误代码 DWORD)↓(EMM) 检查发生错误的原因读取 EAX,CR0 (因此时已是最高等级 ,本行可以正确执行)↓(EMM) 修改堆叠内的 EIP 值 ,指向下一行指令↓(EMM) 修改使用者等级 3 / 设定 VM 旗标等於 1↓(EMM) ESP 值扣掉错误代码 4byte↓(EMM) IRETD 切回 V86↓(User) 使用者取得 EAX 的数值由於程式有一大半在保护模式下执行 ,所以使用者根本感觉不到 ,只知道自己真的读到系统暂存器。这便是 EMM 系的欺骗手段。本来标准的程式是不会在 V86 下读写系统暂存器 ,可是确实也有不正常的程式是这样搞的 ,例如倚天中文会执行 MOV EAX,CR3 ,或是一些保护程式会写入除错暂存器 (DRx)。所以为了相容性 ,这些最好做进去。注:判别发生的原因也可以利用判断 I/O 的那种方法 ,但写起来很麻烦。--------------------------------------------------------------------------┌———————┐│相容性的处理二│ HIMEM.SYS└———————┘HIMEM.SYS 是一个可以控制 1MB 以外记忆体的程式 ,不过之前笔者有提过 ,要读写超过 1MB 以外的记忆体必需进入保护模式才行(据说有後门可用) ,那麽载入自己的保护模式程式後 ,再遇到呼叫 HIMEM.SYS 去搬移 1MB 以外的记忆体 ,电脑竟然会发生 GP Err #0D ,原来这是因为 HIMEM.SYS 在执行搬移记忆体的命令後会去呼叫BIOS 的 AH=87h INT_15h 去搬记忆体 ,换句话说就是因为这个 BIOS 中断会进入保护模式去搬记忆体 ,所以才会造成当机 ,因此你的保护模式介面程式必需去模拟这个BIOS 函式 ,就可以与 HIMEM.SYS 相容了。注:BIOS AH=87h INT_15h 会重设 GDT.IDT 表 ,然後进入保护模式去搬记忆体 ,然後就当在 LIDT 或 LGDT 的命令上。另外如果你的程式摆在 1MB 以上的记忆体位址去执行 ,还会有另一个问题产生 ,不过如果你已经学会上面的这些功能 ,再尝试去写个程式去试试 ,你自然会知道它会发生什麽问题 ,解决的办法也很简单 ,你一定会解决。--------------------------------------------------------------------------切入 V86 後 ,还有很多问题要处理 ,不过上面提到的两个问题如果你都能处理的话 ,基本上就不会有其它大问题 ,等你会进入保护模式後 ,再来学习 VCPI、DPMI就很简单了。如果各位会切入保护模式的话 ,接下来应该是学习 VCPI 的切入方式 ,虽然有很多书籍有介绍 ,但是要真正了解并不容易。建议各位去买套大宇出品的激斗战士、战国策 ,它的外加保护就是切入保护模式的最佳范例 ,包含透过 VCPI、自己切286.386保护模式 ,虽然这是不道德的行为 ,但是却是一个最佳范本。花个五百块学新知绝对划算。有关保护模式的部份笔者暂时介绍到此 ,下一集笔者将为您介绍虚拟记忆体 ,如果情况允许 ,还会顺便介绍更难懂的分页机能。教各位如何写出类似 S-ICE 的 BPR功能 ,锁定某一块记忆体的读写状态。==========================================================================底下是进入保护模式、进入 V86 的精简范例 ,执行前请确定 CPU 是处在真实模式 ,程式码因为用到 386 指令 ,请用 TASM 3.1 来编译。--------------------------------------------------------------------------┌——————┐│进入保护模式│└——————┘进入保护模式的程式范例 ,其目地是进入保护模式 ,并在保护模式下用绝对记忆体读写的方式 ,直接将 'Protection Mode !' 字串写入 Video Ram (B800:0000) ,本程式以最精简的方式撰写 ,没有任何错误处理 ,因此请确定电脑现在处在真实模式下才可执行本程式。(禁挂 EMM 系保护模式软体)程式流程如下:(底下所指记忆体位址皆为 32bit 绝对位址)1. 设定 GDTtab 表所在的记忆体位址填入 GDTadds2. 设定 Selector 0008 的记忆体起始位址就是现在 CS 的记忆体位址设定 Selector 0010 的记忆体起始位址就是现在 CS 的记忆体位址Selector 0018 的记忆体起始位址就是 000B8000 = (B800:0000)3. 执行 LGDT FWORD PTR CS:GDTadds 告诉 CPU 一但进入保护模式 ,各区段的记忆体起始位址、长度4. 设定 CR0 的 Bit0 = '1' ,并透过 JMP 指令进入保护模式※ 进入保护模式後 ,DS.ES.SS.CS.GS.FS 等等暂存器定址方式不再是 Segment ,而变成 Selector5. 秀字 将 0010:MSG_1 搬到 0018:0000意即将 'Protection Mode !' 字串搬到 Video Ram 去6. 设定 CR0 的 Bit0 = '0' ,并透过 JMP 指令回到真实模式※ 回到真实模式後 ,DS.ES.SS.CS.GS.FS 等等暂存器定址方式不再是 Selector ,而变成 Segment5. 秀字 将 CS:MSG_2 搬到 B800:00A0意即将 'Return Real Mode !' 字串搬到 Video Ram 去6. 结束程式----------------------------- P.ASM ------------------------------------code segmentassume cs:code,ds:code.386pstart proc nearjmp nextgdtadds dw 001fh,0000h,0000hgdttab db 000h,000h,00h,00h,00h,00h,00h,00h ;00 Nulldb 0ffh,0ffh,00h,00h,00h,9bh,00h,00h ;08 PRG Segdb 0ffh,0ffh,00h,00h,00h,93h,00h,00h ;10 PRG Segdb 0ffh,0ffh,00h,80h,0bh,93h,00h,00h ;18 B8000msg_1 db 'Protection Mode !'msg_2 db 'Return Real Mode !'next :xor eax,eax ;xor ebx,ebx ;mov ax,cs ;设定 GDTaddsshl eax,04h ;mov bx,offset gdttab ;add eax,ebx ;mov di,offset gdtadds+02h ;mov cs:[di],eax ;NOPxor eax,eax ;xor ebx,ebx ;mov ax,cs ;shl eax,04h ;mov di,offset gdttab+08h ;设定 GDTtab 内的mov si,offset gdttab+10h ;Selector 0008 及 0010mov cs:[di+02h],ax ;两个段落的记忆体起始位址mov cs:[si+02h],ax ;shr eax,10h ;mov cs:[di+04h],al ;mov cs:[si+04h],al ;mov cs:[di+07h],ah ;mov cs:[si+07h],ah ;NOPclilgdt fword ptr cs:gdtadds ;载入 GDT 表格mov eax,cr0 ;or al,01h ;mov cr0,eax ;jmp protection_mode ;进入保护模式protection_mode : ;mov ax,0010h ;mov ds,ax ;mov si,offset msg_1 ;mov ax,0018h ;将 0010:MSG_1 搬到 0018:0000mov es,ax ;mov di,0000h ;mov ah,70h ;mov cx,0011h ;cld ;L1 : ;lodsb ;stosw ;loop L1 ;NOPmov eax,cr0 ;and al,0feh ;mov cr0,eax ;回到真实模式jmp return_real_mode ;return_real_mode : ;stimov ax,cs ;mov ds,ax ;mov si,offset msg_2 ;mov ax,0b800h ;mov es,ax ;将 CS:MSG_2 搬到 B800:00A0mov di,00a0h ;mov ah,70h ;mov cx,0012h ;cld ;L2 : ;lodsb ;stosw ;loop L2 ;mov ax,4cffhint 21hstart endpcode endsend start--------------------------------------------------------------------------因为保护模式下不能呼叫真实模式下的中断 ,所以笔者以直接填写显示卡记忆体的方式秀字。这是一个简单、尚未使用中断向量表的范例。注: 所谓一山不容二虎 ,如果已载入其它保护模式的程式 ,那本程式将会与它打架 ,造成电脑当机。┌————————┐│进入虚拟 86 模式│ 为求精简 ,本程式毫无错误处理能力└————————┘------------------------ V86.ASM ---------------------------------------code segmentassume cs:code,ds:code.386pstart proc nearjmp nextgdtadds dw 002fh,0000h,0000hgdttab db 000h,000h,000h,000h,000h,000h,000h,000h ;00 Nulldb 0ffh,0ffh,000h,000h,000h,09bh,000h,000h ;08 PRG Segdb 0ffh,0ffh,000h,000h,000h,093h,08fh,000h ;10 Dos=Pagedb 0ffh,0ffh,000h,000h,000h,089h,000h,000h ;18 TSSltrdb 0ffh,0ffh,000h,000h,000h,089h,000h,000h ;20 TSSjmpdb 0ffh,003h,000h,000h,000h,093h,000h,000h ;28 Stack (1K)tssltr dd 00000000hdd 000003ffh ;ESPdw 0028h,0000h ;SS.0dd 0,0,0,0,0dw offset enter_v86,0000h ;EIPdd 00000200h ;EFlagdd 0,0,0,0dd 000003ffh ;ESPdd 0,0,0dw 0010h,0000h ;ES.0dw 0008h,0000h ;CS.0dw 0028h,0000h ;SS.0dw 0010h,0000h ;DS,0dw 0010h,0000h ;FS.0dw 0010h,0000h ;GS.0dw 0000h,0000h ;LDT.0dw 0000h,0068h ;0.IOMAPdw 0ffffhtssjmp dd 00000000hdd 000003ffh ;ESPdw 0028h,0000h ;SS.0dd 0,0,0,0,0dw offset enter_v86,0000h ;EIPdd 00000000h ;EFlagdd 0,0,0,0dd 000003ffh ;ESPdd 0,0,0dw 0010h,0000h ;ES.0dw 0008h,0000h ;CS.0dw 0028h,0000h ;SS.0dw 0010h,0000h ;DS,0dw 0010h,0000h ;FS.0dw 0010h,0000h ;GS.0dw 0000h,0000h ;LDT.0dw 0000h,0068h ;0.IOMAPiomap db 1000h dup (0)dw 0ffffhbuffer1 db 0400h dup (0) ;Stackidtadds dw 07ffh,0000h,0000hidttab dw offset new_00,0008h,0ee00h,0000h,offset new_01,0008h,0ee00h,0000hdw offset new_02,0008h,0ee00h,0000h,offset new_03,0008h,0ee00h,0000hdw offset new_04,0008h,0ee00h,0000h,offset new_05,0008h,0ee00h,0000hdw offset new_06,0008h,0ee00h,0000h,offset new_07,0008h,0ee00h,0000hdw offset new_08,0008h,0ee00h,0000h,offset new_09,0008h,0ee00h,0000hdw offset new_0a,0008h,0ee00h,0000h,offset new_0b,0008h,0ee00h,0000hdw offset new_0c,0008h,0ee00h,0000h,offset new_0d,0008h,0ee00h,0000hdw offset new_0e,0008h,0ee00h,0000h,offset new_0f,0008h,0ee00h,0000hdw offset new_10,0008h,0ee00h,0000h,offset new_11,0008h,0ee00h,0000hdw offset new_12,0008h,0ee00h,0000h,offset new_13,0008h,0ee00h,0000hdw offset new_14,0008h,0ee00h,0000h,offset new_15,0008h,0ee00h,0000hdw offset new_16,0008h,0ee00h,0000h,offset new_17,0008h,0ee00h,0000hdw offset new_18,0008h,0ee00h,0000h,offset new_19,0008h,0ee00h,0000hdw offset new_1a,0008h,0ee00h,0000h,offset new_1b,0008h,0ee00h,0000hdw offset new_1c,0008h,0ee00h,0000h,offset new_1d,0008h,0ee00h,0000hdw offset new_1e,0008h,0ee00h,0000h,offset new_1f,0008h,0ee00h,0000hdw offset new_20,0008h,0ee00h,0000h,offset new_21,0008h,0ee00h,0000hdw offset new_22,0008h,0ee00h,0000h,offset new_23,0008h,0ee00h,0000hdw offset new_24,0008h,0ee00h,0000h,offset new_25,0008h,0ee00h,0000hdw offset new_26,0008h,0ee00h,0000h,offset new_27,0008h,0ee00h,0000hdw offset new_28,0008h,0ee00h,0000h,offset new_29,0008h,0ee00h,0000hdw offset new_2a,0008h,0ee00h,0000h,offset new_2b,0008h,0ee00h,0000hdw offset new_2c,0008h,0ee00h,0000h,offset new_2d,0008h,0ee00h,0000hdw offset new_2e,0008h,0ee00h,0000h,offset new_2f,0008h,0ee00h,0000hdw offset new_30,0008h,0ee00h,0000h,offset new_31,0008h,0ee00h,0000hdw offset new_32,0008h,0ee00h,0000h,offset new_33,0008h,0ee00h,0000hdw offset new_34,0008h,0ee00h,0000h,offset new_35,0008h,0ee00h,0000hdw offset new_36,0008h,0ee00h,0000h,offset new_37,0008h,0ee00h,0000hdw offset new_38,0008h,0ee00h,0000h,offset new_39,0008h,0ee00h,0000hdw offset new_3a,0008h,0ee00h,0000h,offset new_3b,0008h,0ee00h,0000hdw offset new_3c,0008h,0ee00h,0000h,offset new_3d,0008h,0ee00h,0000hdw offset new_3e,0008h,0ee00h,0000h,offset new_3f,0008h,0ee00h,0000hdw offset new_40,0008h,0ee00h,0000h,offset new_41,0008h,0ee00h,0000hdw offset new_42,0008h,0ee00h,0000h,offset new_43,0008h,0ee00h,0000hdw offset new_44,0008h,0ee00h,0000h,offset new_45,0008h,0ee00h,0000hdw offset new_46,0008h,0ee00h,0000h,offset new_47,0008h,0ee00h,0000hdw offset new_48,0008h,0ee00h,0000h,offset new_49,0008h,0ee00h,0000hdw offset new_4a,0008h,0ee00h,0000h,offset new_4b,0008h,0ee00h,0000hdw offset new_4c,0008h,0ee00h,0000h,offset new_4d,0008h,0ee00h,0000hdw offset new_4e,0008h,0ee00h,0000h,offset new_4f,0008h,0ee00h,0000hdw offset new_50,0008h,0ee00h,0000h,offset new_51,0008h,0ee00h,0000hdw offset new_52,0008h,0ee00h,0000h,offset new_53,0008h,0ee00h,0000hdw offset new_54,0008h,0ee00h,0000h,offset new_55,0008h,0ee00h,0000hdw offset new_56,0008h,0ee00h,0000h,offset new_57,0008h,0ee00h,0000hdw offset new_58,0008h,0ee00h,0000h,offset new_59,0008h,0ee00h,0000hdw offset new_5a,0008h,0ee00h,0000h,offset new_5b,0008h,0ee00h,0000hdw offset new_5c,0008h,0ee00h,0000h,offset new_5d,0008h,0ee00h,0000hdw offset new_5e,0008h,0ee00h,0000h,offset new_5f,0008h,0ee00h,0000hdw offset new_60,0008h,0ee00h,0000h,offset new_61,0008h,0ee00h,0000hdw offset new_62,0008h,0ee00h,0000h,offset new_63,0008h,0ee00h,0000hdw offset new_64,0008h,0ee00h,0000h,offset new_65,0008h,0ee00h,0000hdw offset new_66,0008h,0ee00h,0000h,offset new_67,0008h,0ee00h,0000hdw offset new_68,0008h,0ee00h,0000h,offset new_69,0008h,0ee00h,0000hdw offset new_6a,0008h,0ee00h,0000h,offset new_6b,0008h,0ee00h,0000hdw offset new_6c,0008h,0ee00h,0000h,offset new_6d,0008h,0ee00h,0000hdw offset new_6e,0008h,0ee00h,0000h,offset new_6f,0008h,0ee00h,0000hdw offset new_70,0008h,0ee00h,0000h,offset new_71,0008h,0ee00h,0000hdw offset new_72,0008h,0ee00h,0000h,offset new_73,0008h,0ee00h,0000hdw offset new_74,0008h,0ee00h,0000h,offset new_75,0008h,0ee00h,0000hdw offset new_76,0008h,0ee00h,0000h,offset new_77,0008h,0ee00h,0000hdw offset new_78,0008h,0ee00h,0000h,offset new_79,0008h,0ee00h,0000hdw offset new_7a,0008h,0ee00h,0000h,offset new_7b,0008h,0ee00h,0000hdw offset new_7c,0008h,0ee00h,0000h,offset new_7d,0008h,0ee00h,0000hdw offset new_7e,0008h,0ee00h,0000h,offset new_7f,0008h,0ee00h,0000hdw offset new_80,0008h,0ee00h,0000h,offset new_81,0008h,0ee00h,0000hdw offset new_82,0008h,0ee00h,0000h,offset new_83,0008h,0ee00h,0000hdw offset new_84,0008h,0ee00h,0000h,offset new_85,0008h,0ee00h,0000hdw offset new_86,0008h,0ee00h,0000h,offset new_87,0008h,0ee00h,0000hdw offset new_88,0008h,0ee00h,0000h,offset new_89,0008h,0ee00h,0000hdw offset new_8a,0008h,0ee00h,0000h,offset new_8b,0008h,0ee00h,0000hdw offset new_8c,0008h,0ee00h,0000h,offset new_8d,0008h,0ee00h,0000hdw offset new_8e,0008h,0ee00h,0000h,offset new_8f,0008h,0ee00h,0000hdw offset new_90,0008h,0ee00h,0000h,offset new_91,0008h,0ee00h,0000hdw offset new_92,0008h,0ee00h,0000h,offset new_93,0008h,0ee00h,0000hdw offset new_94,0008h,0ee00h,0000h,offset new_95,0008h,0ee00h,0000hdw offset new_96,0008h,0ee00h,0000h,offset new_97,0008h,0ee00h,0000hdw offset new_98,0008h,0ee00h,0000h,offset new_99,0008h,0ee00h,0000hdw offset new_9a,0008h,0ee00h,0000h,offset new_9b,0008h,0ee00h,0000hdw offset new_9c,0008h,0ee00h,0000h,offset new_9d,0008h,0ee00h,0000hdw offset new_9e,0008h,0ee00h,0000h,offset new_9f,0008h,0ee00h,0000hdw offset new_a0,0008h,0ee00h,0000h,offset new_a1,0008h,0ee00h,0000hdw offset new_a2,0008h,0ee00h,0000h,offset new_a3,0008h,0ee00h,0000hdw offset new_a4,0008h,0ee00h,0000h,offset new_a5,0008h,0ee00h,0000hdw offset new_a6,0008h,0ee00h,0000h,offset new_a7,0008h,0ee00h,0000hdw offset new_a8,0008h,0ee00h,0000h,offset new_a9,0008h,0ee00h,0000hdw offset new_aa,0008h,0ee00h,0000h,offset new_ab,0008h,0ee00h,0000hdw offset new_ac,0008h,0ee00h,0000h,offset new_ad,0008h,0ee00h,0000hdw offset new_ae,0008h,0ee00h,0000h,offset new_af,0008h,0ee00h,0000hdw offset new_b0,0008h,0ee00h,0000h,offset new_b1,0008h,0ee00h,0000hdw offset new_b2,0008h,0ee00h,0000h,offset new_b3,0008h,0ee00h,0000hdw offset new_b4,0008h,0ee00h,0000h,offset new_b5,0008h,0ee00h,0000hdw offset new_b6,0008h,0ee00h,0000h,offset new_b7,0008h,0ee00h,0000hdw offset new_b8,0008h,0ee00h,0000h,offset new_b9,0008h,0ee00h,0000hdw offset new_ba,0008h,0ee00h,0000h,offset new_bb,0008h,0ee00h,0000hdw offset new_bc,0008h,0ee00h,0000h,offset new_bd,0008h,0ee00h,0000hdw offset new_be,0008h,0ee00h,0000h,offset new_bf,0008h,0ee00h,0000hdw offset new_c0,0008h,0ee00h,0000h,offset new_c1,0008h,0ee00h,0000hdw offset new_c2,0008h,0ee00h,0000h,offset new_c3,0008h,0ee00h,0000hdw offset new_c4,0008h,0ee00h,0000h,offset new_c5,0008h,0ee00h,0000hdw offset new_c6,0008h,0ee00h,0000h,offset new_c7,0008h,0ee00h,0000hdw offset new_c8,0008h,0ee00h,0000h,offset new_c9,0008h,0ee00h,0000hdw offset new_ca,0008h,0ee00h,0000h,offset new_cb,0008h,0ee00h,0000hdw offset new_cc,0008h,0ee00h,0000h,offset new_cd,0008h,0ee00h,0000hdw offset new_ce,0008h,0ee00h,0000h,offset new_cf,0008h,0ee00h,0000hdw offset new_d0,0008h,0ee00h,0000h,offset new_d1,0008h,0ee00h,0000hdw offset new_d2,0008h,0ee00h,0000h,offset new_d3,0008h,0ee00h,0000hdw offset new_d4,0008h,0ee00h,0000h,offset new_d5,0008h,0ee00h,0000hdw offset new_d6,0008h,0ee00h,0000h,offset new_d7,0008h,0ee00h,0000hdw offset new_d8,0008h,0ee00h,0000h,offset new_d9,0008h,0ee00h,0000hdw offset new_da,0008h,0ee00h,0000h,offset new_db,0008h,0ee00h,0000hdw offset new_dc,0008h,0ee00h,0000h,offset new_dd,0008h,0ee00h,0000hdw offset new_de,0008h,0ee00h,0000h,offset new_df,0008h,0ee00h,0000hdw offset new_e0,0008h,0ee00h,0000h,offset new_e1,0008h,0ee00h,0000hdw offset new_e2,0008h,0ee00h,0000h,offset new_e3,0008h,0ee00h,0000hdw offset new_e4,0008h,0ee00h,0000h,offset new_e5,0008h,0ee00h,0000hdw offset new_e6,0008h,0ee00h,0000h,offset new_e7,0008h,0ee00h,0000hdw offset new_e8,0008h,0ee00h,0000h,offset new_e9,0008h,0ee00h,0000hdw offset new_ea,0008h,0ee00h,0000h,offset new_eb,0008h,0ee00h,0000hdw offset new_ec,0008h,0ee00h,0000h,offset new_ed,0008h,0ee00h,0000hdw offset new_ee,0008h,0ee00h,0000h,offset new_ef,0008h,0ee00h,0000hdw offset new_f0,0008h,0ee00h,0000h,offset new_f1,0008h,0ee00h,0000hdw offset new_f2,0008h,0ee00h,0000h,offset new_f3,0008h,0ee00h,0000hdw offset new_f4,0008h,0ee00h,0000h,offset new_f5,0008h,0ee00h,0000hdw offset new_f6,0008h,0ee00h,0000h,offset new_f7,0008h,0ee00h,0000hdw offset new_f8,0008h,0ee00h,0000h,offset new_f9,0008h,0ee00h,0000hdw offset new_fa,0008h,0ee00h,0000h,offset new_fb,0008h,0ee00h,0000hdw offset new_fc,0008h,0ee00h,0000h,offset new_fd,0008h,0ee00h,0000hdw offset new_fe,0008h,0ee00h,0000h,offset new_ff,0008h,0ee00h,0000hnew_00 :push 0000hjmp int_emunew_01 :push 0001hjmp int_emunew_02 :push 0002hjmp int_emunew_03 :push 0003hjmp int_emunew_04 :push 0004hjmp int_emunew_05 :push 0005hjmp int_emunew_06 :push 0006hjmp int_emunew_07 :push 0007hjmp int_emunew_08 :push 0008hjmp int_emunew_09 :push 0009hjmp int_emunew_0a :push 000ahjmp int_emunew_0b :push 000bhjmp int_emunew_0c :push 000chjmp int_emunew_0d :push 000dhjmp int_emunew_0e :push 000ehjmp int_emunew_0f :push 000fhjmp int_emunew_10 :push 0010hjmp int_emunew_11 :push 0011hjmp int_emunew_12 :push 0012hjmp int_emunew_13 :push 0013hjmp int_emunew_14 :push 0014hjmp int_emunew_15 :cmp ah,87hjnz L3push bpmov bp,spadd bp,02hpush eaxpush ebxpush ecxpush edxpush edipush esimov ebx,ss:[bp+14h]shl ebx,04hand esi,0000ffffhadd ebx,esimov ax,0010hmov ds,axmov es,axmov esi,ds:[ebx+12h]mov edi,ds:[ebx+1ah]and esi,00ffffffhand edi,00ffffffhor cx,cxjz L2L1 :mov ax,ds:[esi]mov es:[edi],axadd esi,02hadd edi,02hloop L1L2 :pop esipop edipop edxpop ecxpop ebxpop eaxpop bpiretdL3 :push 0015hjmp int_emunew_16 :push 0016hjmp int_emunew_17 :push 0017hjmp int_emunew_18 :push 0018hjmp int_emunew_19 :push 0019hjmp int_emunew_1a :push 001ahjmp int_emunew_1b :push 001bhjmp int_emunew_1c :push 001chjmp int_emunew_1d :push 001dhjmp int_emunew_1e :push 001ehjmp int_emunew_1f :push 001fhjmp int_emunew_20 :push 0020hjmp int_emunew_21 :push 0021hjmp int_emunew_22 :push 0022hjmp int_emunew_23 :push 0023hjmp int_emunew_24 :push 0024hjmp int_emunew_25 :push 0025hjmp int_emunew_26 :push 0026hjmp int_emunew_27 :push 0027hjmp int_emunew_28 :push 0028hjmp int_emunew_29 :push 0029hjmp int_emunew_2a :push 002ahjmp int_emunew_2b :push 002bhjmp int_emunew_2c :push 002chjmp int_emunew_2d :push 002dhjmp int_emunew_2e :push 002ehjmp int_emunew_2f :push 002fhjmp int_emunew_30 :push 0030hjmp int_emunew_31 :push 0031hjmp int_emunew_32 :push 0032hjmp int_emunew_33 :push 0033hjmp int_emunew_34 :push 0034hjmp int_emunew_35 :push 0035hjmp int_emunew_36 :push 0036hjmp int_emunew_37 :push 0037hjmp int_emunew_38 :push 0038hjmp int_emunew_39 :push 0039hjmp int_emunew_3a :push 003ahjmp int_emunew_3b :push 003bhjmp int_emunew_3c :push 003chjmp int_emunew_3d :push 003dhjmp int_emunew_3e :push 003ehjmp int_emunew_3f :push 003fhjmp int_emunew_40 :push 0040hjmp int_emunew_41 :push 0041hjmp int_emunew_42 :push 0042hjmp int_emunew_43 :push 0043hjmp int_emunew_44 :push 0044hjmp int_emunew_45 :push 0045hjmp int_emunew_46 :push 0046hjmp int_emunew_47 :push 0047hjmp int_emunew_48 :push 0048hjmp int_emunew_49 :push 0049hjmp int_emunew_4a :push 004ahjmp int_emunew_4b :push 004bhjmp int_emunew_4c :push 004chjmp int_emunew_4d :push 004dhjmp int_emunew_4e :push 004ehjmp int_emunew_4f :push 004fhjmp int_emunew_50 :push 0050hjmp int_emunew_51 :push 0051hjmp int_emunew_52 :push 0052hjmp int_emunew_53 :push 0053hjmp int_emunew_54 :push 0054hjmp int_emunew_55 :push 0055hjmp int_emunew_56 :push 0056hjmp int_emunew_57 :push 0057hjmp int_emunew_58 :push 0058hjmp int_emunew_59 :push 0059hjmp int_emunew_5a :push 005ahjmp int_emunew_5b :push 005bhjmp int_emunew_5c :push 005chjmp int_emunew_5d :push 005dhjmp int_emunew_5e :push 005ehjmp int_emunew_5f :push 005fhjmp int_emunew_60 :push 0060hjmp int_emunew_61 :push 0061hjmp int_emunew_62 :push 0062hjmp int_emunew_63 :push 0063hjmp int_emunew_64 :push 0064hjmp int_emunew_65 :push 0065hjmp int_emunew_66 :push 0066hjmp int_emunew_67 :push 0067hjmp int_emunew_68 :push 0068hjmp int_emunew_69 :push 0069hjmp int_emunew_6a :push 006ahjmp int_emunew_6b :push 006bhjmp int_emunew_6c :push 006chjmp int_emunew_6d :push 006dhjmp int_emunew_6e :push 006ehjmp int_emunew_6f :push 006fhjmp int_emunew_70 :push 0070hjmp int_emunew_71 :push 0071hjmp int_emunew_72 :push 0072hjmp int_emunew_73 :push 0073hjmp int_emunew_74 :push 0074hjmp int_emunew_75 :push 0075hjmp int_emunew_76 :push 0076hjmp int_emunew_77 :push 0077hjmp int_emunew_78 :push 0078hjmp int_emunew_79 :push 0079hjmp int_emunew_7a :push 007ahjmp int_emunew_7b :push 007bhjmp int_emunew_7c :push 007chjmp int_emunew_7d :push 007dhjmp int_emunew_7e :push 007ehjmp int_emunew_7f :push 007fhjmp int_emunew_80 :push 0080hjmp int_emunew_81 :push 0081hjmp int_emunew_82 :push 0082hjmp int_emunew_83 :push 0083hjmp int_emunew_84 :push 0084hjmp int_emunew_85 :push 0085hjmp int_emunew_86 :push 0086hjmp int_emunew_87 :push 0087hjmp int_emunew_88 :push 0088hjmp int_emunew_89 :push 0089hjmp int_emunew_8a :push 008ahjmp int_emunew_8b :push 008bhjmp int_emunew_8c :push 008chjmp int_emunew_8d :push 008dhjmp int_emunew_8e :push 008ehjmp int_emunew_8f :push 008fhjmp int_emunew_90 :push 0090hjmp int_emunew_91 :push 0091hjmp int_emunew_92 :push 0092hjmp int_emunew_93 :push 0093hjmp int_emunew_94 :push 0094hjmp int_emunew_95 :push 0095hjmp int_emunew_96 :push 0096hjmp int_emunew_97 :push 0097hjmp int_emunew_98 :push 0098hjmp int_emunew_99 :push 0099hjmp int_emunew_9a :push 009ahjmp int_emunew_9b :push 009bhjmp int_emunew_9c :push 009chjmp int_emunew_9d :push 009dhjmp int_emunew_9e :push 009ehjmp int_emunew_9f :push 009fhjmp int_emunew_a0 :push 00a0hjmp int_emunew_a1 :push 00a1hjmp int_emunew_a2 :push 00a2hjmp int_emunew_a3 :push 00a3hjmp int_emunew_a4 :push 00a4hjmp int_emunew_a5 :push 00a5hjmp int_emunew_a6 :push 00a6hjmp int_emunew_a7 :push 00a7hjmp int_emunew_a8 :push 00a8hjmp int_emunew_a9 :push 00a9hjmp int_emunew_aa :push 00aahjmp int_emunew_ab :push 00abhjmp int_emunew_ac :push 00achjmp int_emunew_ad :push 00adhjmp int_emunew_ae :push 00aehjmp int_emunew_af :push 00afhjmp int_emunew_b0 :push 00b0hjmp int_emunew_b1 :push 00b1hjmp int_emunew_b2 :push 00b2hjmp int_emunew_b3 :push 00b3hjmp int_emunew_b4 :push 00b4hjmp int_emunew_b5 :push 00b5hjmp int_emunew_b6 :push 00b6hjmp int_emunew_b7 :push 00b7hjmp int_emunew_b8 :push 00b8hjmp int_emunew_b9 :push 00b9hjmp int_emunew_ba :push 00bahjmp int_emunew_bb :push 00bbhjmp int_emunew_bc :push 00bchjmp int_emunew_bd :push 00bdhjmp int_emunew_be :push 00behjmp int_emunew_bf :push 00bfhjmp int_emunew_c0 :push 00c0hjmp int_emunew_c1 :push 00c1hjmp int_emunew_c2 :push 00c2hjmp int_emunew_c3 :push 00c3hjmp int_emunew_c4 :push 00c4hjmp int_emunew_c5 :push 00c5hjmp int_emunew_c6 :push 00c6hjmp int_emunew_c7 :push 00c7hjmp int_emunew_c8 :push 00c8hjmp int_emunew_c9 :push 00c9hjmp int_emunew_ca :push 00cahjmp int_emunew_cb :push 00cbhjmp int_emunew_cc :push 00cchjmp int_emunew_cd :push 00cdhjmp int_emunew_ce :push 00cehjmp int_emunew_cf :push 00cfhjmp int_emunew_d0 :push 00d0hjmp int_emunew_d1 :push 00d1hjmp int_emunew_d2 :push 00d2hjmp int_emunew_d3 :push 00d3hjmp int_emunew_d4 :push 00d4hjmp int_emunew_d5 :push 00d5hjmp int_emunew_d6 :push 00d6hjmp int_emunew_d7 :push 00d7hjmp int_emunew_d8 :push 00d8hjmp int_emunew_d9 :push 00d9hjmp int_emunew_da :push 00dahjmp int_emunew_db :push 00dbhjmp int_emunew_dc :push 00dchjmp int_emunew_dd :push 00ddhjmp int_emunew_de :push 00dehjmp int_emunew_df :push 00dfhjmp int_emunew_e0 :push 00e0hjmp int_emunew_e1 :push 00e1hjmp int_emunew_e2 :push 00e2hjmp int_emunew_e3 :push 00e3hjmp int_emunew_e4 :push 00e4hjmp int_emunew_e5 :push 00e5hjmp int_emunew_e6 :push 00e6hjmp int_emunew_e7 :push 00e7hjmp int_emunew_e8 :push 00e8hjmp int_emunew_e9 :push 00e9hjmp int_emunew_ea :push 00eahjmp int_emunew_eb :push 00ebhjmp int_emunew_ec :push 00echjmp int_emunew_ed :push 00edhjmp int_emunew_ee :push 00eehjmp int_emunew_ef :push 00efhjmp int_emunew_f0 :push 00f0hjmp int_emunew_f1 :push 00f1hjmp int_emunew_f2 :push 00f2hjmp int_emunew_f3 :push 00f3hjmp int_emunew_f4 :push 00f4hjmp int_emunew_f5 :push 00f5hjmp int_emunew_f6 :push 00f6hjmp int_emunew_f7 :push 00f7hjmp int_emunew_f8 :push 00f8hjmp int_emunew_f9 :push 00f9hjmp int_emunew_fa :push 00fahjmp int_emunew_fb :push 00fbhjmp int_emunew_fc :push 00fchjmp int_emunew_fd :push 00fdhjmp int_emunew_fe :push 00fehjmp int_emunew_ff :push 00ffhjmp int_emuint_emu :push bpmov bp,spadd bp,04hpush eaxpush ebxmov ax,0010h ;mov ds,ax ;mov ax,ss:[bp+0ch] ;sub ax,06h ;mov ss:[bp+0ch],ax ;xor eax,eax ;xor ebx,ebx ;mov ax,ss:[bp+10h] ;V86 下 IRET 要返回的位址shl eax,04h ;mov bx,ss:[bp+0ch] ;add ebx,eax ;mov ax,ss:[bp+00h] ;mov ds:[ebx],ax ;mov ax,ss:[bp+04h] ;mov ds:[ebx+02h],ax ;mov ax,ss:[bp+08h] ;mov ds:[ebx+04h],ax ;nopxor ebx,ebx ;mov bx,ss:[bp-02h] ;shl ebx,02h ;mov ax,ds:[ebx] ;IRETD後跳到何处执行mov ss:[bp+00h],ax ;(查 0000:0000 的中断表)mov ax,ds:[ebx+02h] ;mov ss:[bp+04h],ax ;mov eax,ss:[bp+08h]or eax,00032000hand eax,0fffffeffhmov ss:[bp+08h],eaxpop ebxpop eaxpop bpadd sp,02hiretdset_base :mov cs:[di+02h],axshr eax,0010hmov cs:[di+04h],almov cs:[di+07h],ahretnext :xor eax,eaxxor ebx,ebxmov ax,csshl eax,04hmov bx,offset gdttabadd eax,ebxmov di,offset gdtadds+02hmov cs:[di],eax ;设定 gdtaddsNOPxor eax,eaxxor ebx,ebxmov ax,csshl eax,04hmov di,offset gdttab+08hcall set_base ;设定 PRG Seg 的 BaseNOPxor eax,eaxxor ebx,ebxmov ax,csshl eax,04hmov bx,offset tssltradd eax,ebxmov di,offset gdttab+18hcall set_baseNOP ;设定 TSSltr 的 Basexor eax,eaxxor ebx,ebxmov ax,csshl eax,04hmov bx,offset tssjmpadd eax,ebxmov di,offset gdttab+20hcall set_baseNOP ;设定 TSSjmp 的 Basexor eax,eaxxor ebx,ebxmov ax,csshl eax,04hmov bx,offset buffer1add eax,ebxmov di,offset gdttab+28hcall set_baseNOP ;设定 Stack 的 Basexor eax,eaxxor ebx,ebxmov ax,csshl eax,04hmov bx,offset idttabadd eax,ebxmov di,offset idtadds+02hmov cs:[di],eax ;设定 idtaddsNOPclilgdt fword ptr cs:gdtaddslidt fword ptr cs:idtaddsmov eax,cr0or al,01hmov cr0,eaxmov bx,0018hltr bxdb 0eah,00h,00h,20h,00h ;根据TSS表可知跳到enter_v86enter_v86 :mov ax,0028hmov es,axxor eax,eaxmov ax,codepush eax ;GSpush eax ;FSpush eax ;DSpush eax ;ESpush eax ;SSmov ax,0f000hpush eax ;ESPmov eax,00023000h ;设定VM=1 等级=3push eax ;Eflagxor eax,eaxmov ax,codepush eax ;CSmov ax,offset return_dospush eax ;EIPclts ;将 387 切换成 32 位元模式iretd ;回到 V86 (共弹出24h BYTE);-------------------------------------------------------------------------; 下面的程式便是回到 V86 继续执行的程式;-------------------------------------------------------------------------return_dos :stimov ax,csmov ds,axmov dx,offset nextadd dx,0200hint 27hstart endpcode endsend start;-------------------------------------------------------------------------如何侦测现在是在真实模式下或保护模式呢 ,重点就在於 CR0 暂存器的 Bit0是否为 '1' ,若为 '1' 则表示现在在保护模式 ,反之则为真实模式 ,不过如果要执行 MOV EAX,CR0 这个指令必需要在特权等级才能执行 ,所以您要侦测这个位元的话 ,可以使用 SMSW AX ,来读取 CR0 的低位元部份。

没有评论: