|
mul s1track mov s1cyl,ax ;每柱面扇数 mov ax,cx mov cl,6 shr al,cl xchg al,ah inc ax mov media_c,ax ;柱面数 h_geo2: ret h_geo endp chain proc ;处理链 chain0: mov ax,201h Call rw1sec mov al,buf[1beh+4] call pri_non test buf[1beh+16+4],255 ;0,5,0fh之1 je chain1 mov ax,word ptr buf[1beh+16+8] Add ax,entrydi ;加基址entrydi mov lbal,ax mov ax,word ptr buf[1beh+16+10] adc ax,entryes ;加基址entryes mov lbah,ax jmp chain0 chain1: ret chain endp nondos proc 查未占过盘符的DOS主分区及非DOS分区 nondos0:cmp dl,mod_p je nondos4 mov ax,201h mov cx,1 int 13h mov bp,dx sub bp,80h mov al,fcbsz[bp] 取已占分区表号 mul extblk mov fcbdat,ax xor bp,bp nondos1:cmp bp,4*16 je nondos3 cmp bp,fcbdat je nondos2 ;已占 mov al,buf[1beh+bp+4] test al,255 不理闲置分区 jz nondos2 mov cx,extmksz ;不理扩展分区 lea di,extmk repne scasb jz nondos2 call pri_non nondos2:Add bp,16 jmp nondos1 nondos3:inc dl jmp nondos0 nondos4:ret nondos endp show proc ;分区信息 mov al,dl 取硬盘编号 lea di,from80 alasc mov al,buf[1beh+bp] ;取BootON lea di,Boot alasc mov al,buf[1beh+bp+4] ;取volume lea di,volume alasc mov ax,word ptr buf[1beh+bp+8] ;取Front low Add ax,lbal ;为chain而加 pushf lea di,Front_l axasc mov ax,word ptr buf[1beh+bp+10] ;Front high popf adc ax,lbah ;为chain而加 lea di,Front_h axasc mov ax,word ptr buf[1beh+bp+12] ;取In low lea di,In_l axasc push dx mov dx,word ptr buf[1beh+bp+14] ;In high mov ax,dx lea di,In_h axasc mov ax,word ptr buf[1beh+bp+12] rept 11 In扇转为M shr dx,1 rcr ax,1 endm lea di,MB[4] axasc mov ax,dx lea di,MB axasc mov ah,9 lea dx,.from80 int 21h pop dx ret Show endp rw1sec proc 读/写1扇 test dl,80h jz rw1sec1 test drv_p,1 jz rw1sec1 xor al,al 不校验写 or ah,40h lea si,extblk ;扩展块 jmp rw1sec2 rw1sec1:push ax push dx call lba2chs pop dx pop ax call cxdh rw1sec2:cmp cmd_p,'v' je rw1sec3 int 13h ret 遗c rw1sec3:Call [entry] cmp bp,4096 VxD按(8.3)返bp值 jae rw1sec4 push bx add bx,bp ;使bx,bx+511在4k内 mov buf_off,bx 扩展i13 push cx push si lea si,buf511 ;原buf尾 mov di,si add di,bp ;新buf尾 std ;从后向前移1扇 mov cx,256 rep movsw cld pop si pop cx Call [entry] pop bx mov buf_off,bx 扩展i13 cmp bp,4096 rw1sec4:je rw1sec5 cmp bp,1010h jne rw1sec6 xor ah,ah Call [entry] 释它页 rw1sec5:clc ret rw1sec6:stc ret rw1sec endp f_geo proc lea bx,buf ;缓区 mov cx,1 ;引导扇,在0:0:1(chs) f_geo0: mov ax,201h ;读1扇 int 13h ;读11起的bios参数块 jc f_geo0 ;换盘 mov al,[bx+26] ;偏移26:头数 mov media_h,al mov ah,[bx+24] ;偏移24:每道扇数 mov s1track,ah mul ah mov s1cyl,ax ;每柱面扇数 mov ax,[bx+19] ;偏移19:总扇数 xor dx,dx ;高字 div s1cyl mov media_c,ax ;柱面数 ret f_geo endp rng proc mov ax,cyl ;当前柱面 lea di,cyl_p1 axasc mov al,hd ;当前头 lea di,hd_p1 alasc mov al,sec ;当前扇号 lea di,sec_p1 alasc mov ax,lbah ;当前lba高字 lea di,lbah_p1 axasc mov ax,lbal ;当前lba低字 lea di,lbal_p1 axasc mov ah,9 lea dx,cyl_p int 21h lea dx,hd_p int 21h lea dx,sec_p int 21h lea dx,lba_p int 21h ret rng endp scr proc xor si,si scr1: mov ax,2 ;清屏 int 10h mov ax,In_h ;当前扇号 lea di,MB[4] mov dx,di axasc mov ah,9 int 21h cmp scr_p,'q' jne scr2 ret scr2: mov ax,si lea di,stk1 axasc lea bp,rowasc scr3: mov al,[bx+si] mov di,bp alasc Add bp,2 + 2 - 1 inc si test si,15 jne scr3 mov ah,9 lea dx,stk1 int 21h test si,255 je scr4 jmp scr2 scr4: mov ah,9 lea dx,scr_p int 21h mov ah,1 ;按1键 int 21h cmp al,'q' je scr5 test si,511 je scr6 jmp scr1 scr5: mov scr_p,al scr6: ret scr endp cxdh proc mov dh,hd ;头号 mov cx,cyl ;柱面号 xchg ch,cl rept 6 shl cl,1 endm or cl,sec ;低6位扇号 ret cxdh endp lba2chs proc mov ax,lbal mov dx,lbah div s1cyl ;柱面号 mov cyl,ax mov ax,dx div s1track mov hd,al ;头号 inc ah mov sec,ah ;扇号 ret lba2chs endp chs2lba proc mov ax,cyl ;柱面号 mul s1cyl mov lbal,ax mov lbah,dx mov al,s1track ;每道扇数 mul hd Add lbal,ax adc lbah,0 mov al,sec ;此处,低6位扇号 dec al cbw Add lbal,ax adc lbah,0 ret chs2lba endp INnib proc ;kbd限长nib入kbd2.转后入stk1,低字还入bx INnib1: mov ah,9 int 21h push dx inc ah ;回车才收 lea dx,kbd int 21h pop dx mov al,kbd dec al cmp al,kbd1 ;实长 jnz INnib1 xor bp,bp lea si,kbd2 INnib2:lodsb mov cx,16 lea di,hextbl repne scasb jnz INnib1 dec kbd1 inc cx ;转'[0-9a-f]'为0~15 sub cx,16 neg cx rept 4 shl bx,1 ;bx接收nibble endm and bl,240 or bl,cl test kbd1,3 ;已收4个nibble jnz INnib2 mov stk1[bp],bx add bp,TYPE stk1 test kbd1,255 jnz INnib2 ret INnib endp c ends end @ (8) 论9x的V86下,直寻硬盘扇区,只能靠VxD VToolsD建的C级VxD,有读/写DOS分区的R0_ReadAbsoluteDisk/R0_Write...函数. 例如,响应自32位C的W32_DEVICEIOCONTROL事件时,用格式R0_Read...(2,1,0,buf,&w),读相对DOS分区的逻辑扇号是0的分区引导扇区PBS,对80H硬盘,PBS位于第0柱,第1头,第1扇,即0:1:1(chs).这时,当前虚拟机hVM,是系统(证于Test_Sys_VM_Handle测事件实参IOCTLPARAMS.dioc_hvm).VxD不改hVM身份. 又如,响应自16位ASM程序的V86_API_Entry入口调用时,同上,读PBS,这时,hVM是DOS(证于Test_...测入口实参VMHANDLE). 均读PBS含"MSWIN4...". 但VxD,也能在V86下,用Exec_Int(0x13),法如13h,直寻硬盘,如PBS之前MBR(硬盘主引导记录,0:0:1(chs)). 笔者c.cpp,a.exe搭档,直读MBR连续5扇,启动config.sys,需rem dev=EMM386 (8.1) 用QuickVxD,建C++级VxD,设备名=C,设备ID=0x3180,选动态安装 选API页Standard App Entry Points框Real/V86 Mode,(8.3)是体 选OnSysDynamicDeviceInit,OnSysDynamicDeviceExit,体返true (8.2) 写a.asm,汇编时,/DNPAGE=5,指明5扇.读变写,需debug下,改r2w3处的2为3. VxD查客户这5扇缓区,囿V86内存空间1页(4K字节)的整体性,未全囿,bp返回<4k的修正量. IF2 IF NPAGE LT 1 or NPAGE GT 8 %OUT 0 .ERR ENDIF ENDIF d segment buf db NPAGE*512*2-1 dup(9);留足修区 entry dd 0 d ends c segment assume cs:c,ds:d @: mov bp,d mov ds,bp mov ax,1684h 功能号 mov bx,3180h 接口ID int 2fh mov ax,es es/di=API_Entry入口段/偏移 or ax,di jz @3 ;es及di全为零,失败 mov word ptr [entry],di mov word ptr [entry+2],es mov ax,ds 设exec_int参数 mov es,ax lea bx,buf es:bx,指向缓区首 r2w3: mov ah,2 读80h硬盘MBR处NPAGE扇 mov al,NPAGE mov cx,1 0:0:1(chs) mov dx,128 std VxD出兰屏,写修 call [entry] cmp bp,4096 VxD按(8.3)返bp值 jae @2 add bx,bp 修缓区首址 test ah,1 查读/写 jz @1 此例ah=2,读盘 lea si,buf 写入时,从后向前,移NPAGE*256字 add si,NPAGE*512-1 si指向原缓区尾 mov di, si add di,bp di指向新缓区尾 mov cx, NPAGE*256 rep movsw ds:si所指cx字,移到es:di mov cx,1 @1: call [entry] cmp bp,4096 @2: je @3 cmp bp,1010h jne @3 xor ah,ah ;释它页 call [entry] @3: xor ax,ax mov es,ax mov ax,[bx+1beh] 成功/失败,72h矢量=分区表首字/9 mov es:[1c8h],ax mov ah,4ch int 21h c ends end @ (8.3) 体 ...V86_API_Entry(VMHANDLE hVM, CLIENT_STRUCT* pRegs){ DWORD h,t; CLIENT_STRUCT s; if(pRegs->CBRS.Client_AH){//2读3写 h=(DWORD)Map_Flat(CLIENT_ES,CLIENT_BX);//h=客户缓区首es:bx的32位线性址 t=h+pRegs->CBRS.Client_AL*512-1;//t=尾的线性址 if((h>>12)!=(t>>12)){ pRegs->CWRS.Client_BP=(4096-(h&4095));//首尾未囿同页,bp返客户增bx量 return; } if((h>>12)<0x110)//缓区能被V86寻,bp返4096 pRegs->CWRS.Client_BP=4096; else if(LinMapIntoV86(h>>12,hVM,0x10,1,0,&t)){ //缓区所在页,成功映入V86第0x10页,bp返0x1010 pRegs->CWRS.Client_BP=0x1010; h=(16<<12)+(h&4095);//由t及偏移,得缓区V86址h }else{//无页等,bp返0x1110 pRegs->CWRS.Client_BP=0x1110; return; } Save_Client_State(&s);//存reg Begin_Nest_V86_Exec();//当前虚拟机,能寻V86 pRegs->CRS.Client_ES=(h>>4);//es=址h的段值 pRegs->CRS.Client_EBX=(h&15);//bx=址h的偏移 Exec_Int(0x13); End_Nest_Exec();//复原 Restore_Client_State(&s); if(pRegs->CWRS.Client_Flags&1024){//方向,控兰屏 sprintf((char*)s.CBRS.Client_res30,"%x",pRegs->CWRS.Client_BP); SHELL_SYSMODAL_Message(hVM,MB_SYSTEMMODAL,(char*)s.CBRS.Client_res30,"bp"); } }else//知bp返0x1010时,客户释它页 MapIntoV86(GetNulPageHandle(),hVM,16,1,0,0); } (8.4) 如下装C.VxD,用Viewer验装,在DOS窗口A,运行a.exe,出兰屏后,在A,用debug,得0:1c8分区表首字,前2种装,重boot,启新VxD. 静态装,置VxD于c:\windows\system,在c:\windows\system.ini中,对节[386Enh]加一行"device=C.VxD" 4种动态装: 置VxD于c:\windows\system\iosubsys 用Loader 用DriverMonitor,先Open,再Start 在DOS窗口V,用笔者 #include #define pre "\\\\.\\" main(int ac,char *av[]){ char *vxd; HANDLE h; if (ac==1) printf("vxd_load ?.vxd\n"); else{ vxd=malloc(strlen(pre)+strlen(av[1])); sprintf(vxd,"%s%s",pre,av[1]); h=CreateFile(vxd,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0); if(h!=INVALID_HANDLE_VALUE){ printf("To unload,hit Enter"); getch(); CloseHandle(h); } } } 的vxd_load.exe,装参C.VxD,做完a.exe,在V,敲回车,卸VxD
|
|