AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > 汇编语言

驻留exe文件

51自学网 http://www.wanshiok.com

(4) 链接时,程序cs:ip及ss:sp设定

用'END expression'形式指明的各伪指令,最先者,expression所在段,及expression相对所在段的偏置,是程序的cs:ip.无此伪指令,cs,ip是0.

例如,a1的'END @'先于a3的'END @1',因此,程序a.exe入口,cs=1,是@所在段相对exe文件装入模块首的节数,ip=11,是@相对所在段的偏置.

用组合属性STACK指明的各逻辑段,map文件最末者,是栈段;无此逻辑段,map文件最先逻辑段,是栈段.

例如,指明STACK的组合逻辑段STK2,后于单逻辑段STK1,因此,程序a.exe栈区,ss=STK2相对exe文件装入模块首的节数0ch,sp=88h,是STK2尺寸.

(5) 汇编时的机器码暂定

能/不能被链接解决的作为操作数的段值/段偏置,其指令后面,带后缀R被暂定;能被链接解决的外部定义,其指令后面,带后缀E被暂定.因此,

a1.lst含:

0013  BB ---- R          mov bx,grp
0018  BA 0000 R          mov dx,OFFSET str1
001D  BA 0000 E          mov dx,OFFSET grp:str2
0022  BB ---- R          mov bx,SEG str3
0027  8D 16 0000 R          lea dx,str3

a3.lst含:

0000  B9 ---- R  @1:  mov cx,SEG grp
0005  BA 0000 E    mov dx,OFFSET grp:str3
000A  B9 ---- R    mov cx,seg1  
000F  BA 0000 R    mov dx,OFFSET seg1:str4

(6) 链接时的机器码暂定,及运行重定位exe文件

作为操作数的段值,相对装入模块首,被暂定.外壳command.com启动命令行上的程序时,先开辟被节号x,节长1的存储控制块(MCB)标识的空闲内存,此MCB前3个域值为:字节值5A(内存块链尾),字0(无效进程PSP),字y(x+1+y=A000段,即640K内存尾),然后在x+1段首,先建10节程序段前缀(PSP),后铺展程序的装入模块.

这时,exe装入头的cs/ss值,与x+11h(叫"装入段值")相加,形成运行cs/ss值,此为"运行重定位exe".装入模块中,链接时的各机器码暂定,与外壳指定的"重定位因子"相加,形成运行逻辑段值.

一般地,重定位因子=装入段值.也可用功能4b03的装入段值/重定位因子两参数,分别指定,如(8)所述.

因此,改a1.exe为a,做debug a,用U 321,反出代码区:

0321 B409          MOV AH,09                              
0323 BB0000        MOV BX,0000  ;取grp段值                            
0326 8EDB          MOV DS,BX                              
0328 BA0000        MOV DX,0000  ;取str1相对seg1偏置
032B CD21          INT 21                                
032D BA8C00        MOV DX,008C  ;取str2相对grp偏置
0330 CD21          INT 21                                
0332 BB0A00        MOV BX,000A  ;取str3段值
0335 8EDB          MOV DS,BX                              
0337 8D160000      LEA DX,[0000]  ;ASSUME ds:ovlap时,取str3相对ds偏置                          
033B CD21          INT 21                                
033D B90000        MOV CX,0000  ;取grp段值                            
0340 8ED9          MOV DS,CX                              
0342 BAB000        MOV DX,00B0  ;取str3相对grp偏置                            
0345 CD21          INT 21                                
0347 B90800        MOV CX,0008  ;取seg1段值                            
034A 8ED9          MOV DS,CX                              
034C BA0F00        MOV DX,000F  ;取str4相对seg1偏置                            
034F CD21          INT 21                                
0351 B44C          MOV AH,4C                              
0353 CD21          INT 21                                

(7) MS-DOS的exe文件两部构成:

前部,含装入头(1ch字节长)及重定位表;后部,是装入模块.

链接时的各机器码暂定,相对装入模块首的偏置:节,用2个字w_o,w_p,存于重定位表.

(7.1) 装入头的字节偏置:

0,1  : 4d(M),5a(Z)标识
2,3  : exe文件净长度,除以512后的余数
4,5  : exe文件净长度,被512量的值
6,7  : 重定位表的项数
8,9  : 前部占用节数
a,b  : 装入模块之后,所需最小节数
c,d  : 装入模块之后,所需最大节数
e,f  : ss相对装入模块首的节数
10,11 : sp
12,13 : exe文件的字检查和
14,15 : ip
16,17 : cs相对装入模块首的节数
18,19 : 重定位表相对exe文件的字节偏置
1a,1b : 覆盖号

a,长840字节(348h),做debug a,用D 100 L2e,显出exe文件头的前2Eh个字节:

0100  4D 5A 48 01 02 00 04 00-20 00 00 00 FF FF 0C 00
0110  88 00 D3 A2 11 00 01 00-1E 00 00 00 01 00 14 00
0120  01 00 23 00 01 00 2E 00-01 00 38 00 01 00

(7.2) 解释装入头:

(7.2.1) a的长度,除以512后,余148H,放2,3字节
(7.2.2) a的长度,被512量,占2,放4,5字节
(7.2.3) 重定位表,含4项
(7.2.4) exe文件前部,占20H节
(7.2.5) 重定位表相对a,字节偏置是1eh

(7.3) 相对a,字节偏置是1eh的重定位表解释:

第1项,w_o=14h,w_p=1,指出此机器码暂定,相对装入模块首,是1节14h偏置,即1*10h+14h=24h(字节).

debug从100h装a,向高20h节(200h字节),是装入模块首,(100h+200h)加上24h的324h处,恰为MOV BX,0000中的段值位置.

第2项,w_o=23,w_p=1,相对装入模块首,是1节23h偏置,即1*10h+23h=33h(字节).300h加上33h的333h处,恰为MOV BX,000A中的段值位置.

同理,第3,4项,是MOV CX,0000及MOV CX,0008中的段值位置.

(8) 重定位因子调度覆盖模块

功能4b03,铺展exe装入模块.前部略去PSP的装入模块,称覆盖模块.

调用覆盖模块cs:ip入口的常驻者(如ovlayer.exe),要做:

(8.1) 将覆盖模块所在exe装入头中的程序cs:ip,读到entry
(8.2) 调用功能4a,释放其尾后内存
(8.3) 填写4b03的装入段值/重定位因子两参数
(8.4) 调用功能4b03,它在空闲内存MCB之高1节,铺展覆盖模块
(8.5) 用call entry语句,调用覆盖模块cs:ip入口

覆盖模块(如ovlayee.exe)工作完时,用retf,返回控制到常驻者.

覆盖模块被功能403铺展时,与(6)同样处理,作为mov ax,work操作数的段值work,与重
定位因子相加,这使ovlayee.exe,被ovlayer.exe调度,显示某区/某串值,例如,先显
o1区串s1值'os1',再显o2区串s2值'os2'.

(8.6) ovlayee文
要点: 只含1个逻辑段work,故work的机器码暂定,相对装入模块首,必为0,与重
定位因子的相加结果,恰=重定位因子.

要点: 不需写"END @"伪指令,让cs/ip为0,而ss/sp,借用ovlayer.exe栈区.

work segment
assume cs:work

push ds
mov ax,work
mov ds,ax

mov ah,9  ;显串
int 21h  ;dx被ovlayer指定
pop ds

retf   ;远返回

work ends
END

(8.7) ovlayer文
要点: 引入PARA对齐的tail空段,使长度可变的ovlayer.exe,从PSP首到tail,作为新占用内存,tail之上,是空闲内存MCB.
要点: mov bx,tail语句之后,勿写标号,否则masm5报错.

o1 segment
s1 db 'os1$'
o1 ends

o2 segment
s2 db 'os2$'
o2 ends

arg segment
loadseg dw      2       ;装入段值
factor  dw      2       ;重定位因子
entry   dd      4
filenam db 'ovlayee.exe',0
header  db      1ch     dup(1)
arg ends

stk     segment STACK
        dw      16      dup(9)
stk     ends

root    segment
        assume  cs:root,ds:NOTHING

@: mov ax,arg
mov ds,ax

mov ax,3d00h ;读打开
        mov     dx,offset arg:filenam
int 21h
        jnc     @F         ;@F,@B,向前/后找最近的@@标号

        mov     ah,4ch
        int     21h

@@:     mov     bx,ax           ;句柄送bx

        mov ah,3fh  ;读装入头到header
        mov cx,1ch
        mov     dx,offset arg:header
        int 21h

mov ah,3eh  ;关闭
int 21h

mov     bx,tail       ;tail指向映像尾节
mov di,es
        sub     bx,di           ;bx是此程序新占用内存的节数

        mov ah,4ah  ;新占用内存,始于es所指PSP节,长bx节
        int 21h

add bx,di
       inc bx

        mov     ds:loadseg,bx ;装入段值=MCB之高1节

mov ax,seg s1 ;重定位因子=s1所在段
        mov     ds:factor,ax

        mov  ax,word ptr ds:[header+14h] ;取覆盖模块ip
        mov     word ptr ds:[entry],ax

        add bx,word ptr ds:[header+16h] ;覆盖模块的cs,加上MCB之高1节
        mov     word ptr ds:[entry+2],bx

mov ax,ds
mov es,ax

        mov ax,4b03h
        mov     bx,offset arg:loadseg      ;es:bx指参数块
        mov     dx,offset arg:filenam      ;ds:dx指程序名
        int 21h

        mov     dx,offset o1:s1    ;dx是s1相对o1的偏置
        call    ds:entry

mov ax,seg s2
        mov     ds:factor,ax       ;重定位因子=s2所在段

        mov ax,4b03h
        mov     bx,offset arg:loadseg      ;es:bx指参数块
        mov     dx,offset arg:filenam      ;ds:dx指程序名
        int 21h

        mov     dx,offset o2:s2    ;dx是s2相对o2的偏置
        call    ds:entry

        mov     ah,4ch
        int     21h

root ends

tail    segment   ;空段
tail ends

        END @

 
 

上一篇:动态库的执行时间  下一篇:仿FDISK及PQMAGIC列出分区逻辑盘符的prw.asm实现