彙編語言命令參數程序的編寫

一、 引言:
    如果大家用過TurboC2.0/3.0 or BorlandC3.X等編譯器編寫DOS應用程序的話,編寫一個命令行參數形式的應用程序對大家來說是一件非常容易的事情,只要在主函main()中加幾個參數就OK(int main(int argc,char *argv[],char *env[]){})。相對彙編語言來說編寫一個命令行參數的程序就比較艱難,它要用到DOS的程序段前綴PSP(Program Segment Prefix)知識以及其他相關DOS知識。(本文只對參數介紹,環境塊不作討論)
二、相關知識:
    在DOS的提示符下鍵入一個命令(內/外部命令)或程序的名字,DOS SHELL(COMMAND.COM)首先根據名字判別其是內部命令還是外部命令或用戶程序,若是內部命令則調用COMMAND.COM暫駐在內存中的部分的DOS內部命令代碼,若是外部命令或用戶程序,DOS SHELL則在當前目錄和搜索路徑中搜索匹配的文件名,找到了就加載程序,加載出錯顯示錯誤信息,找不到則顯示Bad command or file name。
    用戶載DOS提示符下輸入一串字符串,DOS SHELL把以回車(0Dh)爲結束的這以字符串作爲一個命令和參數進行解釋,第一個空格以前的字符串爲命令名(必須符合DOS命名規則),第一個空格(包括空格)到回車之間的字符作爲命令或程序的參數。
    程序段前綴--PSP是DOS加載一個外部命令或用戶程序(擴展名爲COM or EXE)時,在程序段前設置一個以節爲邊界,固定長度爲10H(即256字節,一節爲16字節)的存儲塊,PSP和程序段共有一個內存控制塊(MCB),PSP位於每個程序的開始部分,無論是COM還是EXE,PSP的數據結構是相同的。PSP是程序與DOS的接口,DOS利用PSP管理進程,DOS用戶進程指的是一個已被裝入內存的可執行程序或已被調入內存但未執行的程序,COMMAND.COM是一個最早被裝入內存的程序,因而可被看作祖先進程,外部命令或用戶程序作爲子進程,被DOS通過INT 21H的4BH號子功能來加載。用戶程序也可以通過INT 21H的4BH號子功能調用來加載自己的子進程,控制子進程的執行,並通過4DH號子功能調用獲取子進程的運行狀況。
    PSP中存有許多關於程序啓動、執行、結束以及進程調度、進程環境地址和進程標誌等重要信息。程序利用PSP還可以控制父子進程間的通信。至於PSP的數據結構的詳細內容請參考有關書籍,本文不詳細給出。
    DOS加載一個COM或EXE程序時,段寄存器DS,ES都指向PSP段址(PSP段址是進程的唯一標誌符),而不是指向程序的數據段和附加段。COM文件的CS,SS也指向PSP的段址。EXE文件的CS,SS,IP和SP需要進行重定位。
    DOS加載一個外部命令或用戶程序時,把文件名之後到回車符之間的字符串,最多可達127個字符作爲參數,並把這些字符串送到PSP位移81H開始的區域,位移80H的一個字節存放參數字符串長度(回車符不算在內)。大家可用DEBUG.EXE加載一個帶參數的程序,然後用D DS:80子命令查看加載程序的參數。命令行參數一般以空格(20H)爲開始,回車符(0DH)爲結束,但命令行中的重定向,管道符以及有關信息不作爲參數傳遞給PSP。
 
三、示例程序:
    本例程序PARATEST.ASM在沒有參數(參數爲一連串空格也視爲無參數)的情況下顯示提示信息,程序以字符'/'作爲參數的標誌,'/'後的字符是參數,根據不同的參數顯示不同的字符串,並忽略'/'前的空格。程序還把非法參數顯示出來,由於程序中保存參數的單元只設了兩BYTES,如果字符'/'後的第一格字符是合法參數,程序不管字符'/'後有多少個字符都認爲是合法的。
    順便介紹一個彙編編程的技巧,文後附帶的示例源程序(PARATEST.ASM)中的DEBUG子程序是利用了INT 21H的07H號子功能等待用戶的鍵盤輸入,相當於TURBOC中的getch()函數,作爲程序的斷點。我們還可以利用其顯示斷點的調試信息(包括各寄存器的值)。但注意保存現場,並進行現場恢復。
 
四、結束語:
    一個月以前我還只是會看別人的彙編程序,自從自己動手寫程序後,自己的彙編編程水平有了很大的進步。寫程序的過程中遇到問題,然後自己看書自己解決問題,這樣學習彙編編程比光看書更有效。我的彙編編程的水平還很菜鳥,我會不斷提高自己的水平,同時也希望與廣大編程愛好者交流。
 
附:源程序(PARATEST.ASM)
; ************************************************
; * Program:Use asm language to creat a command  *
; *         line and parameter program.          *
; *==============================================*
; * Designer:Howard   Original Place:Wuhan       *
; * Creat Date:09/30/1999                        *
; * Modification Date:10/05/1999                 *
; * Now Version:1.0                              *
; * Pass:Tasm 5.0,Tlink 3.1                      *
; *==============================================*
; *       Modification History                   *
; *----------------------------------------------*
; * Version 1.0 1.Command line and parameter     *
; * 09/30/1999    test program.                  *
; *----------------------------------------------*
; * Version 1.1 2.Add the spaces parameters jud- *
; * 10/05/19999   gement.                        *
; ************************************************
;
 

.model small
.386
.code
  org 100h
start: 
main proc far
         push cs
  pop  ds  ;ds=psp seg address
  cld             ;cf=0
  mov  si,81h  ;psp+81h is the first parameter char        
  lea  bx,parameter  ;parameter address(offset) saved to bx
       ;unit parameter is used to save the parameter
         lodsb      ;load a byte from [si] to al,and si=si+1
  cmp  al,0dh     ; Enter?
  jz   scanexit     ;if yes then scan parameter end
  cmp  al,' '
  jz   judgespace
  lodsb
continue:
         push si
  cmp  al,'/'
  jz   parascanloop
         jmp  error      ;wrong parameter
judgespace:
         lodsb
;        call debug         ;set break point 
  cmp  al,0dh
  je   scanexit
  cmp  al,' '
  je   judgespace
  jne  continue
parascanloop:      ;saved the parameter to unit parameter
         mov  [bx],al     ;save al to [bx],just save the parameters
  lodsb
  cmp  al,0dh     ;Enter?
  jz   choise     ;if yes then jump choise
  inc  bx
  jnb  parascanloop  ;the next char
scanexit:
         lea  dx,noparametermsg
  call disp
  call rettodos
choise:
         lea  si,parameter
  mov  al,[si+1]     ;load the parameter to al
  cmp  al,'?'     ;judge the parameter and choose                                              ;the different process
  jz   help
  cmp  al,'p'
  jz   print
  cmp  al,'P'
  jz   print
  jmp  error     ;wrong parameter
print:
         lea  dx,message
  call disp
  call rettodos
help:                       ;print the help message
         lea  dx,helpmsg
  call disp
  call rettodos
error:                      ;print the error parameter message
         lea  dx,wrongparamsg
  call disp
  mov  ax,0200h
         pop  si
  dec  si
prnwrongparameter:  
         lodsb
  cmp  al,0dh
  jz   retdos
  mov  dl,al
  int  21h
  loop prnwrongparameter
retdos:
         mov  dl,'"'
  int  21h
  mov  dl,'!'
  int  21h
  call rettodos
main endp
 
disp proc near
         mov  ah,09h
  int  21h
  ret
disp endp
 
rettodos proc near
         mov  ah,4ch
  int  21h
rettodos endp
;
;set a break point
;debug proc near
;        push ax dx
;  mov  ax,0900h
;  mov  dx,offset debugmsg
;  int  21h
;  mov  ax,0700h
;  int  21h
;  pop  dx
;  pop  ax
;debug endp 
;debugmsg db 0dh,0ah,'Program stop here,press any key to continue...','$' 

noparametermsg db 0ah,0dh,'There is no parameter,enter paratest /? for help.','$'
message   db 0dh,0ah,'This is a parameter test program.','$'
wrongparamsg db 0dh,0ah,'The wrong parameter:"','$'
helpmsg   db 0dh,0ah,'1.Paratest /?'
          db 0dh,0ah,'  Print the help message.'
   db 0dh,0ah,'2.Paratest /p'
   db 0dh,0ah,'  Print the test message.','$'
parameter db 2 dup(?) 
end start  

文章出處:飛諾網(www.diybl.com):http://www.diybl.com/course/3_program/hb/hbjs/20100803/519557.html

發佈了2 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章