一、Intel 段间间接远跳转
格式: jmp dword ptr orp执行的操作:
( IP ) < --- ( EA )
( CS ) <---- ( EA + 2 )
对于386及其后继机型:
( EIP ) <------ ( EA )
( CS ) <------- ( EA + 4)
其中EA为内存地址,
二、动手操作
1.在[SECTION .data1]中添加两个变量来存放跳转目标处的段基址和偏移
即为CSValueInRealMode和IPValueInRealMode,注意前者即CS为dw,IP为dd
还有保证在DateLen标号之前,曾今我把这两个变量放到DataLen之后,编译时间很长,而且生成的目标文件达到1.5G之多,肯定无法运行了,惨痛的教训啊!谨记
[SECTION .data1]
ALIGN 32
[BITS 32]
LABEL_DATA:
SPValueInRealMode dw 0
PMMessage db "In Protected Mode now. ^-^", 0
OffsetPMMessage equ PMMessage - $$
StrTest db "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0
OffsetStrTest equ StrTest - $$
IPValueInRealMode dd 0
CSValueInRealMode dw 0
DataLen equ $ - LABEL_DATA
; END OF [SECTION .data1]=====================================
2.在[SECTION .s16]中为CSValueInRealMode赋值,因为我们实在不同的段间跳转,而且这两个对象不仅代码段不同,数据段,堆栈段都不同,所以我们还要通过寄存器把DS值传到[SECTION .s16code]中,这里先把ds的值压栈中
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0100h
mov [CSValueInRealMode], ax
push ax
;mov [LABEL_GO_BACK_TO_REAL + 3], ax
mov [SPValueInRealMode], sp
3.在跳转到保护模式之前弹出堆栈内容到ax
; switch into Protected Mode
pop ax
jmp dword SelectorCode32:0
4.在保护模式中临时保存ds的值到
[SECTION .scode32]
[BITS 32]
LABEL_SEG_CODE32:
mov bx, ax
mov ax, SelectorData
mov ds, ax
mov ax, SelectorTest
mov es, ax
mov ax, SelectorVideo
mov gs, ax
mov ax, SelectorStack
mov ss, ax
mov esp, TopOfStack
5.关键时刻,来到了[SECTION .scode16]
LABEL_GO_BACK_TO_REAL:
;jmp 0:LABEL_REAL_ENTRY
mov ax, bx
mov ds, ax
mov [IPValueInRealMode], dword LABEL_REAL_ENTRY
jmp dword far [IPValueInRealMode]
三、小结
很显然,我这个方法没有作者的简单。但从这个小尝试我学到了很多,细节啊,太重要了啊!
此外,还发现一个奇怪的现象,如果没有保存edx的值前对它进行了赋值操作,结果是我们最后可以返回dos出现问题,没有提示符,而且我想显示的一段字符串也没有显示,调试发现在程序运行之前edx的值是0x40000,而且在正常成功返回dos时也是这个值,于是,我尝试在修改edx之后,在给它赋值0x40000,果不出我所料,成功返回到dos,一切正常,这个0x40000大概存放着特定的东东吧。