📄 9.txt
字号:
08h,0000h ;CS.0
> dw 0028h,0000h ;SS.0
> dw 0010h,0000h ;DS,0
> dw 0010h,0000h ;FS.0
> dw 0010h,0000h ;GS.0
> dw 0000h,0000h ;LDT.0
> dw 0000h,0068h ;0.IOMAP起点
> db 1000h dup (0) ;4K IOMAP 表
> dw 0ffffh
>
>
> 如果您的程式使用 JMP XXXX:YYYYYYYY 的方式跳到本区节的话 ,原本指定的
> YYYYYYYY 将无用途 ,因为所有的暂存器将被替换成此表格的数值(含CS.EIP) ,并
> 完成等级切换的动作。
>
>
> --------------------------------------------------------------------------
> ┌───────┐
> │进入 V86 模式│
> └───────┘
>
> cli
> lgdt fword ptr cs:gdtadds
> lidt fword ptr cs:idtadds
> mov eax,cr0
> or al,01h
> mov cr0,eax
> mov bx,0018h
> ltr bx ;发生工作切换时 ,SS:ESP 将参考 0018 的区段表格
> jmp 0020h:0000h ;进入工作切换 ,会跳到此表格内指定的 CS:EIP
> (LTR.JMP 不可指向同一表格)
>
> enter_v86 : ;假设您已将 CS:EIP 指向此处继续执行
> xor eax,eax
> mov ax,code
> push eax ;GS
> push eax ;FS
> push eax ;DS
> push eax ;ES
> push eax ;SS
> mov ax,0f000h
> push eax ;ESP
> mov eax,00023000h ;设定VM=1 等级=3
> push eax ;Eflag
> xor eax,eax
> mov ax,code
> push eax ;CS
> mov ax,offset return_dos
> push eax ;EIP
> clts ;将 387 切换成 32 位元模式
> iretd ;回到 V86 (共弹出24h BYTE)
>
> 紧接著就程式回到 V86 下继续执行著...
> --------------------------------------------------------------------------
> ┌────────┐
> │中断向量表的处理│
> └────────┘
> 在 V86 下产生中断後 ,电脑会自动切回保护模式 ,并从 LTR 所指定的位址取得
> TSS 表格 ,然後以表格内的资料重新设定 SS.ESP ,然後把 V86 下的各暂存器值摆入
> 此堆叠内 ,在此需注意的是它摆放在堆叠的资料是32位元方式 ,所以对於 DS.ES....
> 这类16位元暂存器摆於堆叠 ,不足部份补 '0000' ,用以凑足 32Bit。
>
> 简单来说 ,在真实模式下或 V86下使用一组 SS:SP ,一但透过中断i入保护模式
> 後 ,原先的 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 0020h
> jmp int_emu
> new_21 :
> push 0021h
> jmp int_emu
> new_22 :
> push 0022h
> jmp int_emu
> new_23 :
> push 0023h
> jmp int_emu
>
> int_emu :
> push bp
> mov bp,sp
> add bp,04h
> push eax
> push ebx
> mov ax,0010h ;
> mov ds,ax ;(Selector 0010h 的 Base=0)
> mov ax,ss:[bp+0ch] ;
> sub ax,06h ;改V86的SP-6
> mov ss:[bp+0ch],ax ;
> xor eax,eax ;
> xor ebx,ebx ;修改V86下的SS:SP ,帮它摆入
> mov ax,ss:[bp+10h] ;INT_X 後的下一行位址 ,供V86
> shl 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 ;
> nop
> xor 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=1
> and eax,0fffffeffh ;关闭'T'旗标
> mov ss:[bp+08h],eax
> pop ebx
> pop eax
> pop bp
> add sp,02h
> iretd
>
> --------------------------------------------------------------------------
> ┌──────┐
> │拦 I/O 能力│
> └───w──┘
>
> TSS 表格内除了可定义产生工作切换後 ,SS.ESP.DS.ES....各暂存器替换值 ,也
> 可以开一块记忆体做 IOMAP ,这块记忆体每个 Bit 代表一个 PORT ,一般习惯是开4K
> 大小 (65536埠),当某位元设定为 '1' 後 ,只要不是最高等级的人去读写此埠 ,都会
> 发生 GP Err #0D ,当然在最低等级的 V86 程式也不例外 ,发生此错误後 ,就形同拦
> 到 I/O 动作了 ,紧接著透过最高等级的处理程式去判断发生错误的原因 ,例如判断
> 程式码是否为 『EC IN AL,D
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -