程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 匯編仿FDISK及PQMAGIC列出分區邏輯盤符的prw.asm實現

匯編仿FDISK及PQMAGIC列出分區邏輯盤符的prw.asm實現

編輯:匯編語言

仿98(DOS7.1)的F$.EXE(>512M模式運行),P_QUEST的P$.EXE
  
  本文基於486DX2,主板,可帶primary(啟動)/secondary控制IDE器2,中斷14/15,每個IDE,可帶master(啟動,電纜中)/slave(纜端)(跳線ds插/空)2通道,每通道,可帶1台硬盤驅動器,每驅動器,可帶1塊NORMAL,LBA,LARGE模式的IDE硬盤.
  
  DOS,98對硬盤,先按IDE,後按m/s,依次編號,不編閒置通道.例如,有3塊盤,塊1,2在pri_m/s上,塊3在sec_cs上,此3塊,編為80h~82h.
  
  開機盤的IDE及通道,由BIOS的BOOT SEQ指定.
  
  (1) DOS/98的讀寫F16/32格式的位置X的Y個連續扇區的BIOS中斷13h參數:
  ah的2/3指明讀/寫,al的低6位指明Y,es:bx指向內存buf首,cl的低6位指明X的扇號sector,最小1,ch,左拼cl第6,7位,齊指X的柱面號cylinder,最小0,dh指明磁頭號head,最小0,dl指明軟硬盤編號.
  
  IDE原有的NORMAL,BIOS限定柱面數1024,磁頭數16,扇區數63,每扇512字節,相乘=容量528MB.用作cmos_chs(cylinder:head:sector)立體尋扇.
  
  LBA,僅磁頭數異達255,容量8.4GB
  
  LARGE,柱面數>1024,磁頭數16,控制器做柱面數/2,磁頭數*2,以適13h.容量2048*16*63*512=1G
  
  周邊設定:Block模式加速,PIO(並行I/O接口)模式,影響rate
  
  (2) 針對LBA的擴展13h線性64位lba尋扇:
  
  chs轉時,lba=c*sectors_per_cylinder+h*sectors_per_track+(s-1)
  其中,sectors_per_cylinder為每柱面扇數,sectors_per_track為每磁道扇數,因s從1編號,要減1.
  
  互轉,見"(7) 文"的chs2lba,lba2chs.
  
  利用extblk塊:
  
  extblk  db  16  ;塊的字節數(含此字節)
      db  0
  sec_tot dw  1    指明Y個扇區
  buf_off dw  0   ;內存buf偏移
  buf_seg dw  0   ;buf段值
  lbal    dw  0   ;lba低雙字低字
  lbah    dw  0   ;lba低雙字高字
          dd  0   ;lba高雙字
  
  讀/寫時,ah=42h/43h,多ds:si指向extblk
  
  擴展i13的BIOS支持性(柱數<1024,先用chs),及導出硬盤柱數,頭數,每道扇數,算法見"(7) 文"的h_geo
  
  (3) 硬盤分區:
  
  每硬盤,最多劃為DOS主分區,DOS擴展分區,非DOS分區之1的4區,述於16字節/區的64字節分區表(dpt):
  
  bootON    db 0    80H/0,是活躍/不活躍.
      db ?    分區啟動chs的頭號
      dw ?    低6位:扇區,低第6,7位與高字節,'齊指'柱面號
  volume    db 0    分區標識值
      db ?    結束chs
      dw ?
  Front    dd 0    此分區之前(稱隱藏)扇區數.INT_25H_dx=1,是在其後讀邏輯首扇
  In    dd 0    此分區所含扇區數
  
  MBR(F$制的1扇盤主引導記錄,軟盤0:0:1,硬盤DOS分區的首扇,即INT_25H_扇號dx=1),轉cpu給Format.com制的駐有OS的活躍主分區引導記錄(OBR).
  
  主分區的保留區(引導扇區PBS囿其內,軟盤僅藏1區)之後,常是2份FAT,再後,是根目錄.


  
  PBS片斷:
  
  0~2:JMP引導程序
  3~0AH:廠,sys_ver
  (BPB首)0BH~0CH:每扇bytes
  0DH:每簇扇數
  0EH~0FH:保留區扇數
  10H:FAT份數
  11H~12H:F16根目錄32字節項的數目,F32:0.
  13H~14H:軟盤,32M內硬盤:分區總扇數
  15H:介質,軟盤:F0H,硬盤:F8H
  16H~17H:軟盤,32M內硬盤:每FAT占用扇
  18H~19H:每道扇數
  1AH~1BH:磁頭數
  1CH~1FH:此分區之前隱藏扇數
  20H~23H:32M外硬盤:分區總扇數
  24H~27H:32M外硬盤:每FAT占用扇
  40H:磁盤BIOS,1st硬盤:80H,軟盤:0
  47H~51H:vol
  52H~59H:file_sys
  
  軟盤6.22的io.sys,最先分得簇,如目錄項0基第13字,指向1e,此12BIT的項值,是1f0002,指明01f->020->...->fff鏈.
  
  分區標識值:
  
  閒置:0
  DOS主分區:1,4,6,0bh,0ch,0eh
  DOS擴展分區:5,0fh
  非DOS分區:其它
  
  筆者用P,對硬盤劃分4個DOS主分區,再prw,讀此盤(0:0:0)到文件0,用debug,改分區vol值為2,用prw,回寫0到(0:0:0),P的分區info頁,顯vol對應XENIX.
  
  釋意,見"(7) 文"的FAT
  
  若vol<20H,則高4位,1/0表示隱藏/非隱藏,後綴X,用於擴展i13接口.
  
  各硬盤,均含0:0:1(chs)的1扇MBR,其偏移1be字節,連續存4個分區表.
  
  各硬盤,最多1個DOS擴展分區,其內,能劃分稱為邏輯分區的數個DOS主分區,非DOS分區.
  
  邏輯分區串成鏈.例如,vol=5的擴展分區E,先含1個DOS主分區D,後含1個非DOS分區N,則E的Front域值F,是E內的各邏輯分區位置基址,F指明扇區S1,而S1的偏移1be字節,是D的分區表,偏移1ce字節,其vol=0fh,表示DOS擴展分區,其Front域值,加上基址F,指明扇區S2,而S2的偏移1be字節,是N的分區表,偏移1ce字節,其vol=鏈尾0.
  
  (4) 仿F$及P$,列出分區邏輯盤符:
  
  盤符,C:~Z:列出.用F$,P$,能建數個邏輯分區
  
  分區超過Z:符時,F$照列,P$不賦盤符,prw賦^符
  
  活躍分區數>1時,引導錯,但F$及prw照列,P$顯錯
  
  F$,P$,依vol域,查以下3步,每步,查80h至83h:
  
  (1) 查DOS主分區
  若是,則查bootON是否80H,若是,此分區就占1個邏輯盤符,若無活躍主分區,表項在MBR首現的主分區,就占1個邏輯盤符.
  
  例如,3硬盤,80h的第1,3分區是主分區,但第3分區活躍,則第3分區占盤符C:.而81h,只含DOS擴展分區,其上,含1個DOS主分區及1個非DOS分區;82h的第2,4分區是不活躍主分區,則最先在MBR中出現的第2分區,占盤符D:
  
  (2) 查DOS擴展分區
  按邏輯分區在鏈上次序,查它是否DOS主分區,若是,就占盤符,81h的DOS擴展分區上的DOS主分區,占盤符E:
  
  (3) 查未占過盤符的DOS主分區及非DOS分區
  按MBR中,分區表項出現的先後次序,查分區是否DOS主分區,若是,且它未占過盤符,就占盤符.80h的第1分區,占盤符F:,82h的第4分區,占盤符G:
  
  F$,P$,prw,不給非DOS分區賦盤符,僅顯In值.


  
  (5) 例:
  
  筆者486,在pri_ds上,裝ST32140A驅動器(2012M),在sec_ds上,裝QUANTUM(514M).
  
  (5.1) 80h上,現有vol=6的DOS活躍主分區(FAT16B,1299M),vol=6的主分區(F16B,39.4M),vol=17h的非DOS分區(HiddenNTFS,574.9M),vol=5的擴展分區,其托4個邏輯分區,按鏈上次序是:
  
  vol=0bh的DOS主分區(F32,35.4M),vol=83h的非DOS分區(LINUX_Ext2,19.7M),vol=1的DOS主分區(Unfmt,3.9M),vol=6的主分區(41.3M)
  
  (5.2) 81h上,現有vol=82h的非DOS分區(L_Swap,3M),vol=11h的非DOS分區(Unfmt,3M),vol=6的活躍主分區(472.5M),vol=0fh的擴展分區,其托4個邏輯分區,按鏈上次序:
  
  vol=82h的非DOS分區(L_Swap,10.8M),vol=1的主分區(F12,8.8M),vol=7的非DOS分區(N,9,8M),vol=1的主分區(U,7.8M).
  
  從98軟盤啟動,F$,P$,列出這些分區的盤符及容:
  
  C:1299M
  D;472.5M
  E:35.4M
  F:3.9M
  G:41.3M
  J:39.4M
  H:8.8M
  I:7.8M
  
  (6) prw功能
  
  命令行是prw.exe [foo1]
  
  初見:
  b(pb),p(arti),r(ead sec to foo/stdout),w(rite foo to sec),v(xd w)
  
  命令鍵b,p,r,w,v:
  
  (6.1) b,顯subBPB
  (6.2) p,顯分區盤編號,邏輯盤符,BootON值,vol值,Front值,In值,例如
  
  80,C:,Boot:80,FAT:06,Front:0000003f,In:00101661
  
  (6.3) r,讀軟硬盤內容到新建foo,或stdout
  (6.4) wv,寫已存foo到軟硬盤.v多依VxD,勝v86禁13h寫.算法,見"(8) 論V86下,直尋硬盤扇區,只能靠VxD"
  
  rwv,用舊FCB式,讀源F16,F32,寫F16.逐扇有結果I/O,直至出錯或事成.
  
  欲讀80h的MBR到文件b:d,先發:
  
  prw b:d
  
  再答r,界面:
  
  drv(00~01,80~83)80
  0~cyl(0029)
  0~hd(1f)
  1~sec(3f)
  0~lba(00014abf)
  c(hs),l(ba)l
  0~lba(00014abf)00000000
  0~cyl(0000)
  0~hd(00)
  1~sec(01)
  0~lba(00000000)
  1~total(ffff)0001
  
  事成/中止,d長度512/0.
  
  v86時,改向buf文符到F32的文件g,可發prw c:u>g
  
  (7) 文
  NIBSZ=8         ;8個hex數
  
  nibasc          macro
                  local   nq
  
          add        al,48
                  cmp             al,10+48
                  jb              nq
          add        al,97-48-10
  nq:
                  endm
  
  alasc           macro
          mov        ah,al
                  and             al,15
                  nibasc
                  xchg            ah,al
          rept        4
          shr        al,1    高nibble
          endm
                  nibasc
                  stosw
          endm
  
  axasc   macro  
              push ax
              mov al,ah    轉ah
              alasc
              pop ax    轉al
              alasc
          endm
  
  d segment
  buf     db      511 dup(0)    放MRB.全囿V86頁(4k),buf長1023,囿DMA_64k
  buf511    db    0        老buf尾
  
  info_sz     dw 26  ;min sz of info buf    新buf
  flags         dw 0   ;flags
  cylinders0      dw 0   ;number of cylinders on disk
  cylinders1      dw 0
  heads00       db 0   ;number of heads on disk
  heads01         db 0
  heads1          dw 0
  s1track00 db 0    ;number of sectors per track
  s1track01 db 0
  s1track1 dw 0
  sectors       dq 0   ;number of sectors on requested disk
  sector_sz   dw 0   ;number of bytes per sector  
                db      511-26  dup(0)  ;新buf
  
  FAT  db 13,10,'0~0eh:'
  db  13,10,'?OS,F12/Unfmt,,,F16/U_,EXtend,F16B,NTFS,,,,F32,F32_13X,,F16'
  db 13,10,'11,14,16,17,1b:(Hidden)'
  db 13,10,'F12/U_,F16,F16B,N,F32$'
  
  .view    db    '0000,cx='
  viewcx    db    '13EX,dx='
  viewdx    db    'tend'
  CR        db 13,10,36
  
  extblk  db  16,0    分區表16字節用
  sec_tot dw  1
  buf_off dw  buf ;buf偏移
  buf_seg dw  SEG buf
  lbal    dw  0   ;lba低雙字低字
  lbah    dw  0   ;lba低雙字高字
          dd  0   ;lba高雙字
  
  cmd_p    db 'b(pb),p(arti),r(ead sec to foo/stdout),w(rite foo to sec),v(xd w)$';rwv用
  
  logi_p    db 13,10,'logi_drv(A:=01)$'
  subBPB    db 13,10,'SV_sec:'
  SV_sec    db 0,'000,FATs:'    向foo讀
  FATs    db '00,sec_per_FAT:'
  sec1FAT   db '0000$'
  
  drv_p   db 13,10,'drv(00~01,80~83)$'       ;擴展i13用
  mod_p   db 13,10,'c(hs),l(ba)$'            ;dosext,nondos用
  
        db  13,10
  from80  db  '8?,'
  logidrv db  'C:,Boot:'
  Boot    db  '?0,FAT:'
  volume  db  '06,Front:'
  Front_h dw  ?,?    又做總扇數
  Front_l db  '0000,In:'
  In_h    dw  0,?    又做當前扇號
  In_l    db  '0000$'
  
  cyl_p   db  13,10,'0~cyl('
  cyl_p1 db    '????)$'
  
  hd_p    db  13,10,'0~hd('
  hd_p1 db     '??)$'
  
  sec_p   db  13,10,'1~sec('
  sec_p1 db    '??)$'
  
  lba_p   db  13,10,'0~lba('
  lbah_p1 db   '????'
  lbal_p1 db   '????)$'
  
  total_p db  13,10,'1~total(ffff)$'
  
  scr_p   db      '^C,f(ast),n(ext)$'
  
  primk  db      1,4,6,11,12,14    主分區標識
  primksz=$-primk
  extmk  db      5,15        擴展分區標識
  extmksz=$-extmk
  
  stk1    dw    NIBSZ/4 dup(0)  ;INnib棧
          db     32
  rowasc  db (2+1)*16 dup(32),36
  
  kbd     db  NIBSZ+1 ;鍵盤buf
  kbd1     db 67    parti用
  kbd2    db  NIBSZ+1 dup(0)
  
  fcbdrv  db  0
  fcbnam  db  8 dup(32)
  fcbext  db  3 dup(32)
  
  fcbblk  dw  0
  fcbrsz  dw  512
  
  fcbsz  db  4 dup (4)    已占分區表號,4硬盤*1字節,parti用
  fcbdat  dw  0
  
  fcbdos1 db  10 dup(0)
  fcbrno  db  0
  
  entry   label   dword   ;fcbrand
  entrydi dw      0
  entryes dw      0
  
  media_h db  0   ;頭數
  media_c dw  0   ;柱數
  s1cyl   dw  0   ;扇數/柱
  s1track db  0   ;扇數/道
  
  drv     db  0   ;輸入
  hd      db  0
  cyl     dw  0
  sec     db  0
  
  hextbl db   '0123456789abcdef'
  d ends
  
  c segment
          assume cs:c,ds:d,es:d
  
  @       proc    far
  
      push    ds          ;為exe返回
      xor    ax,ax            壓cd20的psp:0
          push ax
  
          mov ax,d
          mov es,ax
  
          cmp     byte ptr ds:[5dh],32    缺foo
      je    @0
  
          inc     es:SV_sec
          mov cx,1+8+3
      mov     si,5ch    sh復制盤符+大寫8.3名到5ch
      lea     di,fcbdrv
          rep movsb    es:di=ds:si的盤符+8.3
  
  @0:    mov ds,ax
  
          mov ah,9
          lea dx,cmd_p   ;問命令
          int 21h
  
          mov     ah,1        
          int     21h
  
      cmp    al,'b'
          je     b
          jmp    p
  
  b:      mov kbd,2 + 1
          lea dx,logi_p    問邏輯盤
          Call INnib
  
      mov ax,440dh
      mov cx,860h    傳統及擴展13,共享BPB前12字節
      lea dx,buf
      int 21h
  
          mov ax,word ptr buf[7+3]
          lea di,SV_sec
          axasc
  
      mov al,buf[7+5]
          lea di,FATs
          alasc
  
          mov ax,word ptr buf[7+11]
      or ax,ax
      jnz bo
  
          mov ax,word ptr buf[7+25]
  
  bo:     lea di,sec1FAT
      axasc
  
      mov ah,9
      lea dx,subBPB
      int 21h
      ret
  
  p:      cmp    al,'p'
          jne r
  
      mov ah,9
          lea dx,FAT
      int 21h
  
          lea bx,buf
  
          mov     dx,80h    擴展i13,可兼容傳統
          Call dospri
          mov mod_p,dl
  
          mov     dl,80h
          Call dosext
                                
          mov lbal,0
          mov lbah,0
          
          mov dl,80h
          Call nondos  
          ret
  
  r:    mov      cmd_p,al
  
      cmp     al,'r'
          je rwv
  
          cmp     al,'w'
          je rwv
  
          cmp     al,'v'
          je     v
  
      ret
  
  v:      mov     ax,1684h    ;func
          mov     bx,3180h    ;接口ID
          int     2fh
  
          mov     ax,es       ;es:di=V86口cs:ip
          or      ax,di
          jnz     v1            
      ret            es,di全0,失敗
  
  v1:     mov entrydi,di
          mov entryes,es
          push ds
          pop es
  
  rwv:    mov kbd,2 + 1
          lea    dx,drv_p    問磁盤
          Call INnib
  
          mov drv,bl
      mov dl,bl        驅動器
          
      test bl,80h
          jne rwv1
  
      xor dh,dh        頭
          Call f_geo
          jmp rwv2
  
  rwv1:    Call h_geo
  
  rwv2:   test media_h,255
          jne rwv3
          ret
          
  rwv3:  mul s1cyl
  
          sub ax,1        ;lba始於0,可寫CF
          sbb dx,0
  
          mov lbal,ax
          mov lbah,dx
  
          Call lba2chs
          Call rng
  
          mov ah,9               ;問尋扇
          lea dx,mod_p
          int     21h
  
          mov ah,1
          int     21h      
          cmp     al,'c'
          je rwv4
  
          mov kbd,8 + 1
          lea dx,lba_p
          call    INnib       ;問lbah,lbal
          mov lbal,bx
  
          mov ax,stk1
          mov lbah,ax
  
          Call lba2chs
          jmp rwv5
  
  rwv4:mov kbd,4 + 1
          lea     dx,cyl_p    ;問柱面號
          Call INnib
          mov cyl,bx
  
          mov kbd,2 + 1
          lea     dx,hd_p     ;問頭號
          Call INnib
          mov hd,bl
  
          mov kbd,2 + 1
          lea     dx,sec_p    ;問扇號
          Call INnib
          mov sec,bl
  
          Call chs2lba
  
  rwv5:Call rng          ;顯出立體,線性值
  
          mov kbd,4 + 1
          lea     dx,total_p  ;問總計
          Call INnib
  
          mov Front_h,bx
  
          lea dx,fcbdrv  ;指向fcb
  
          mov     ah,15       ;open for w,v
          cmp cmd_p,'r'
          jne rw1
  
          test SV_sec,1    向foo讀
          jz rw2
  
          mov     ah,16h      ;create or trunc for r,軟盤啟動,拒存取F32盤
  rw1:    int     21h    改fcbdrv為3=C
          
      or      al,al        al為0,成功
          jnz     rw7
  
          mov fcbrsz,512        重置
  
  rw2:    mov        ax,600h        al=clr
          mov        bx,700h        bl=page
          xor        cx,cx
          mov        dx,184fh    25*80
          int        10h            cursor grow 0,24
  
          mov     ah,1ah      ;DTA
          lea dx,buf
          mov bx,dx              ;I/O數據區
          int     21h
  
  rw3:   test    Front_h,65535
          jz rw6
  
       cmp cmd_p,'r'
          jne rw4
  
          mov ax,201h
          mov dl,drv
          Call rw1by1
      je rw6
  
      Call scr
  
          test SV_sec,1        ;向foo讀
          jz rw5
  
      mov     ah,15h      ;強制write
          lea dx,fcbdrv
          int     21h
          jmp rw5
  
  rw4:   mov     ah,14h      ;read
          lea dx,fcbdrv
          int     21h
        
          Call scr
  
          mov ax,301h
          mov dl,drv
          Call rw1by1
          je rw8             ;出錯,關閉
  
  rw5:    add lbal,1
          adc lbah,0
  
          inc In_h
          dec Front_h
          jmp rw3
  
  rw6:    test SV_sec,1    向foo讀
      jnz rw8
  
  rw7:    ret
  
  rw8:    mov     ah,16       ;close
          lea dx,fcbdrv
          int     21h
  
          ret
  @       endp
  
  dospri  proc                ;統計硬盤數,查DOS主分區
  dospri0:cmp dl,80h+4
          je dospri7
  
          mov     ax,201h     ;測硬盤
          mov cx,1
          int     13h
          jc dospri7
  
          mov bp,4*16        
  
          xor     si,si       ;分區表,占4*16字節
  dospri1:cmp si,4*16
          je dospri4
  
          mov al,buf[1beh+si+4]       取vol
          mov cx,primksz         是主分區?
          lea di,primk
          repne scasb
          jne dospri3
  
          test byte ptr buf[1beh+si],80h  ;取BootON
          jnz dospri2
  
          cmp bp,4*16
          jnz dospri3
          
  dospri2:mov bp,si                  ;暫選首現主分區
          jnz dospri5
  
  dospri3:Add si,16
          jmp dospri1
  
  dospri4:cmp bp,4*16
          je dospri6
  
  dospri5:mov si,dx
          sub si,80h
  
      mov ax,bp
      div extblk      
          mov fcbsz[si],al    標占分區表項號
  
          mov al,kbd1
          mov logidrv,al
          inc kbd1
  
      Call Show
  
  dospri6:inc dl                ;讀下塊硬盤
          jmp dospri0
  
  dospri7:ret
  dospri endp
  
  pri_non proc
          mov logidrv,32
  
          mov cx,primksz
          lea di,primk
          repne scasb
          jne non             ;不賦非DOS分區盤符
  
          mov logidrv,94        ^符
  
          mov al,kbd1
          cmp al,'Z'
          ja non
  
          mov logidrv,al
          inc kbd1
  
  non:    Call Show
          ret
  pri_non endp
  
  dosext  proc                查DOS擴展分區
  dosext0:cmp dl,mod_p
          je dosext4
  
          mov ax,201h
          mov cx,1
          int 13h
              
          xor bp,bp
  dosext1:cmp bp,4*16
          je dosext3
  
          mov al,buf[1beh+bp+4]
          mov cx,extmksz             是擴展分區?
          lea di,extmk
          repne scasb
          jne dosext2
  
          push bx
          push dx
          Call h_geo
          pop dx
          pop bx
  
          mov     ax,word ptr buf[1beh+bp+8]   ;Front low
          mov entrydi,ax    基址
          mov lbal,ax
  
          mov     ax,word ptr buf[1beh+bp+10]  ;Front high
          mov entryes,ax
          mov lbah,ax
  
          xor bp,bp       ;為show
          Call chain            
          jmp dosext3
  
  dosext2:Add bp,16
          jmp dosext1
  
  dosext3:inc dl
          jmp dosext0
  
  dosext4:ret
  dosext endp
  
  h_geo proc
          mov     ah,41h
          mov     bx,55aah    ;測BIOS支持i13_X
          int     13h
          jc      h_geoo
  
          cmp     bx,0aa55h    再核
          jne     h_geoo
  
          test cx,1              ;支持41~44,47~48第1子集?
          jz h_geoo
  
      mov ah,48h            取尺寸
          lea si,info_sz
          int 13h
  
          mov     al,heads00         ;頭數
          or        al,al
          jz        h_geoo    無效info包
  
          mov     media_h,al
          inc drv_p    啟擴展
  
          mov     ah,s1track00 ;每道扇數
      mov    s1track,ah
  
          mul ah
          mov  s1cyl,ax            每柱面扇數
  
          mov     ax,cylinders0      ;柱面數
          mov     media_c,ax
      ret
  
  h_geoo:    mov ah,8    取尺寸
          int 13h
          jc h_geoq
  
          inc dh
  
          mov al,dh
          mov     media_h,al  ;頭數
  
          mov s1track,cl
          and s1track,63      每道扇數
  
          mul s1track
          mov     s1cyl,ax    ;每柱面扇數
  
       xchg ch,cl
       rol ch,1
           rol ch,1
        and ch,3
  
          mov ax,cx
          inc ax
          mov     media_c,ax  ;柱面數
  
  h_geoq:    ret
  h_geo endp
  
  chain     proc                ;處理鏈
  chain0: mov ax,201h
          Call rw1by1
  
          mov al,buf[1beh+4]
          call pri_non
  
          test buf[1beh+16+4],255         ;0,5,15之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    ;分區信息
          push dx
  
          and dl,3            盤號80~83
          add dl,48
          mov from80[1],dl
  
          mov Boot,48            多數為0
          test buf[1beh+bp],80h
          jz show0
          mov Boot,56
  
  show0:    mov al,buf[1beh+bp+4]  ;顯vol
          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
  
          mov        ax,word ptr buf[1beh+bp+14]  ;In high
          lea di,In_h
          axasc
  
          mov ah,9
          lea dx,from80
        sub dx,2
          int 21h
  
          pop dx
          ret
  Show endp
  
  rw1by1 proc            讀/寫1扇
          test drv_p,1    13=傳統
          jnz rw1by11
  
       xor     al,al        不校驗寫
          or     ah,40h
          lea     si,extblk   ;擴展塊
          jmp rw1by12
  
  rw1by11:push ax
          push dx
          call lba2chs
          pop dx
          pop ax
  
          call cxdh
  
          mov word ptr viewcx,cx
          mov word ptr viewdx,dx
  
  rw1by12:cmp cmd_p,'v'
          je rw1by13
  
      int    13h
      ret            遺c
  
  rw1by13:Call [entry]
  
          cmp    bp,4096    VxD按(8.3)返bp值
          jae     rw1by14
  
          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
  rw1by14:je    rw1by15
  
      cmp    bp,1010h
      jne    rw1by16
  
      xor ah,ah
          Call [entry]        釋它頁
  
  rw1by15:cmp al,al    置zr
  rw1by16:ret
  
  rw1by1 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
          mov        cx,16    字符數/row
  
          xor     si,si
  
  scr0:    push    bx
          mov        ah,2
          xor        bh,bh    pg
          xor        dx,dx    dh=row
          int        10h
          pop        bx
  
          lea dx,.view
  
          test si,256
          jz scr1
          jmp scr3
  
  scr1:    mov di,dx
          mov    ax,In_h        現扇號
          axasc
  
          test drv_p,1
          jnz scr2
          jmp scr3
  
  scr2:    lea di,viewcx
          mov    ax,word ptr [di]
          axasc
  
          lea di,viewdx
          mov    ax,word ptr [di]
          axasc
  
  scr3:    mov ah,9
          int 21h
  
  scr4:   mov ax,si
          lea di,stk1
          axasc
  
          lea bp,rowasc
  
  scr5:    mov al,[bx+si]
  
          mov di,si
          and di,15
  
          mov FAT[di],46
  
          cmp al,32
          jb scr6        
  
          mov FAT[di],al
  
  scr6:   mov di,bp
          alasc
  
          Add bp,2+2-1
  
          inc si
          test si,15
          jne scr5
  
          mov ah,9    行的hex
          lea dx,stk1
          int 21h
  
          push bx
          mov ah,64    行的asc及漢字
          mov bx,1
          lea dx,FAT
          int 21h
          pop bx
  
          mov ah,9
          lea dx,CR
          int 21h
  
          test si,255
          je scr7
          jmp scr4
  
  scr7:   cmp scr_p,'f'
          je scr8
  
          mov ah,9
          lea dx,scr_p
          int 21h
  
          mov ah,1        ;按1鍵
          int 21h
  
          cmp al,'f'
          jne scr8
  
          mov scr_p,al
  
  scr8:   test si,511
          je scr9
          jmp scr0
  
  scr9:   ret
  scr     endp
  
  cxdh proc
          mov     dh,hd       ;頭號
  
          mov     cx,cyl      ;柱面號
          xchg cl,ch
  
          ror cl,1
          ror cl,1
      and cl,not 63
  
          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
  INnib0: 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 INnib0
  
          xor bp,bp
          lea si,kbd2
  INnib1:    lodsb
  
          mov cx,16
          lea di,hextbl
          repne scasb
  
          jnz INnib0
          dec kbd1
  
          inc cx          ;轉'[0-9a-f]'為0~15
          sub cx,16
          neg cx
  
          rept 4
          shl bx,1        ;bx接收nibble,左入0
          endm
  
          or bl,cl
  
          test kbd1,3     ;已收4個nibble
          jnz INnib1
  
          mov stk1[bp],bx
          add bp,TYPE stk1
  
          test kbd1,NIBSZ*2-1
          jnz INnib1
          ret
  INnib endp
  
  c ends
          end     @


  
   (8) 論V86下,直尋硬盤扇區,只能靠VxD
  
  VToolsD建的C級VxD,有讀/寫DOS分區的R0_ReadAbsoluteDisk/R0_Write...函數.
  
  例如,響應自32位C的W32_DEVICEIOCONTROL事件時,用格式R0_Read...(2,1,0,buf,&w),讀相對DOS分區的邏輯扇號是1的分區引導扇區PBS.這時,當前虛擬機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.
  
  筆者c.cpp+a.exe,直讀MBR連續5扇.需cfg.sys,隱dev=EMM386
  
  (8.1) 用QuickVxD,建C++級VxD,設備名=C,設備ID=0x3180,選動態裝
  
  選API頁Standard App Entry Points框Real/V86 Mode.體,見(8.3).
  
  選OnSysDynamicDevice的Init及Exit.體中:
  
  選發SHELL_SYSMODAL_Message(Get_Cur_VM_Handle(),MB_SYSTEMMODAL,"m","cap")
  必發return(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) 裝VxD法
  
  靜態:
  放C.VXD於c:\windows\system,在c:\windows\system.ini的386Enh,寫device=C.VxD,再reboot
  
  動態4法:
  用VxD_Loader,選C.VXD
  用DriverMonitor,先打開C.VXD,再Start
  放C.VXD於c:\windows\system\iosubsys,再reboot
  
  用筆者DOS窗口a的exe
  
  #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);
          }
      }
  }
  
  裝C.VXD,事畢,敲回車到窗a,卸此VXD

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved