Make your own free website on Tripod.com

Passing Commandline Parameters to an Executable

Materials:
Working complete PC
Blank Diskette
Source Code Diskette (created in the Introduction to TASM module)
Student Diskette, "New Boot A Ver 2.0+"
Student CD-ROM, "QBOOT" (any version)
Objectives:
The student will become familiar with the Borland Turbo Assembly language compiler including:
Using a blank source code file,
Building a source file in stages,
Building internal procedures,
Opening, reading, and determining a file's size,
Getting passed commandline parameters,
Building the object file,
Building the executable.
Competency:
The student will learn how to design executable assembly language programs and how to compile and link the source code text file into an executable. The student will become familiar with some basic compiler "dot" directives and some simple machine language instructions. The student will learn how to call DOS to open a file, read the contents of a file and how to determine the file's size.

    Preparation

  1. The student will need a copy of Borland's Turbo Assembly Lanugage software, preferably version 5.0.

  2. After launching QBOOT by pressing [F8] say yes to all CONFIG.SYS prompts and all AUTOEXEC.BAT prompts except the last one to launch Windows 3.11.

  3. Change to the K: drive and insert the source code diskette created in the Introduction to TASM module. Copy BLANK.ASM and DEV.BAT from the diskette to the root of the K: drive and then run "edit blank.asm" All assembly language source files should have the file extention .ASM so that the compilers can easily recognize them.

  4. Procedures

  5. In EDIT's main field, the following source code should be present:

    .model tiny
    .stack 200h
    .data
    .code
    main proc
      mov ax, @data
      mov ds, ax
    terminate:
      mov ax, 4C00h
      int 21h
    main endp
    end main
    
  6. Press [Alt]+[F] to open the File menu and then press [A] to save the file with a new name. Name the file XTYPE.ASM. Make the following changes:

    .model tiny
    .stack 200h
    .data
    msg             db "Press a key to continue...$"
    fopenmsg        db "Cannot open specified file.",0Dh,0Ah,'$'
    freadmsg        db "Error occured while reading the file.",0Dh,0Ah,'$'
    crlf            db 0Dh, 0Ah, '$'
    fhandle         dw 0FFFFh ;invalid file handle
    fname           db "TEST.TXT",0
    fbuf            db 2000 dup(0)
    crlfcount       db 0
    bufsize         dw 0
    fsizehi         dw 0
    fsizelo         dw 0
    fopenerr        db 0
    freaderr        db 0
    fsizeeven       db 0
    fdone           db 0
    lastread        db 0
    
    .code
    main proc
      mov ax, @data
      mov ds, ax
    
    start:
    ;open the file, check an error flag quit if set otherwise continue  
    
    ;check the file size and if it is evenly divisible by 2000 (the buffer size
    
    main1:
    ;read the file and set a file done flag, if done then quit
    
    main2:
      mov cx, bufsize      ;set loop counter
      mov bx, offset fbuf  ;set base indexed addressing
      xor si, si           ;set offset pointer to zero
    main3:  
      mov dl, [bx+si]      ;read character from file buffer in RAM
      mov ah, 2            ;DOS function 2 display character
      int 21h
      cmp dl, 0Ah          ;watch for a line feed
      je inccrlf           ;if it is jump to the counter otherwize continue
    main4:
      inc si               ;point to the next char in the file buffer
      loop main3           ;continue the loop displaying chars on screen
      jmp main1            ;when the buffer is done, go read more info from the file
    inccrlf:
      inc crlfcount        ;add 1 to the line feed count
      cmp crlfcount, 23    ;have there been 24 line feeds displayed (screen is full)
      ja main5             ;yes: jump out to the pause code
      jmp main4            ;no: continue displaying chars on screen
    main5:
    ;set crlfcount back to 0
      push cx              ;save current cx (loop counter) on the stack
      xor cx, cx           ;clear it
      mov crlfcount, cl    ;clear line feed counter variable
      pop cx               ;restore loop counter from the stack
    
      mov ah, 9            ;function 9: display a string
      mov dx, offset msg   ;the pause message
      int 21h              ;call DOS to show the string
      
      mov ah, 8            ;function 8 = get a key w/o echo
      int 21h              ;this waits for the user to press any key
      
      mov ah, 9            ;these three lines display a carriage return/line feed
      mov dx, offset crlf
      int 21h
    
      jmp main3            ;continue displaying chars from the file buffer
    
    terminate:
      mov ax, 4C00h             ;function 4C = quit program
      int 21h
    main endp
    end main
    

  7. Press [Alt]+[F] then [S] to save the changes. The highlighted lines are the ones that were added to the original BLANK.ASM. The first change creates the new variables and the second change starts creating the executable code. This is going to be a long project so it should be developed in stages starting with a few executable lines and then notes on what needs to be added later.

  8. At this point because there is going to be a lot of repitition of commands to copy the file to the floppy, then compile, link and execute it quit EDIT and run dev xtype. This batch file will open the file in EDIT. Press [Alt]+[F] then [X] to quit. At the continue prompt type [Y] to save the file to the floppy, then press [Y] to compile, [Y] to link, and [N] to execute.

  9. Now run dev xtype again and in EDIT add the following code:

    .model tiny
    .stack 200h
    .data
    msg             db "Press a key to continue...$"
    fopenmsg        db "Cannot open specified file.",0Dh,0Ah,'$'
    freadmsg        db "Error occured while reading the file.",0Dh,0Ah,'$'
    crlf            db 0Dh, 0Ah, '$'
    fhandle         dw 0FFFFh ;invalid file handle
    fname           db "TEST.TXT",0
    fbuf            db 2000 dup(0)
    crlfcount       db 0
    bufsize         dw 0
    fsizehi         dw 0
    fsizelo         dw 0
    fopenerr        db 0
    freaderr        db 0
    fsizeeven       db 0
    fdone           db 0
    lastread        db 0
    
    .code
    main proc
      mov ax, @data
      mov ds, ax
    
    start:
    ;open the file, check an error flag quit if set otherwise continue  
    
      call fopen
      cmp fopenerr, 0
      jne terminate
    
    ;check the file size and if it is evenly divisible by 2000 (the buffer size
    
    main1:
    ;read the file and set a file done flag, if done then quit
    
    main2:
      mov cx, bufsize      ;set loop counter
      mov bx, offset fbuf  ;set base indexed addressing
      xor si, si           ;set offset pointer to zero
    main3:  
      mov dl, [bx+si]      ;read character from file buffer in RAM
      mov ah, 2            ;DOS function 2 display character
      int 21h
      cmp dl, 0Ah          ;watch for a line feed
      je inccrlf           ;if it is jump to the counter otherwize continue
    main4:
      inc si               ;point to the next char in the file buffer
      loop main3           ;continue the loop displaying chars on screen
      jmp main1            ;when the buffer is done, go read more info from the file
    inccrlf:
      inc crlfcount        ;add 1 to the line feed count
      cmp crlfcount, 23    ;have there been 24 line feeds displayed (screen is full)
      ja main5             ;yes: jump out to the pause code
      jmp main4            ;no: continue displaying chars on screen
    main5:
    ;set crlfcount back to 0
      push cx              ;save current cx (loop counter) on the stack
      xor cx, cx           ;clear it
      mov crlfcount, cl    ;clear line feed counter variable
      pop cx               ;restore loop counter from the stack
    
      mov ah, 9            ;function 9: display a string
      mov dx, offset msg   ;the pause message
      int 21h              ;call DOS to show the string
      
      mov ah, 8            ;function 8 = get a key w/o echo
      int 21h              ;this waits for the user to press any key
      
      mov ah, 9            ;these three lines display a carriage return/line feed
      mov dx, offset crlf
      int 21h
    
      jmp main3            ;continue displaying chars from the file buffer
    
    terminate:
      mov ax, 4C00h             ;function 4C = quit program
      int 21h
    main endp
    fopen proc
      mov ah, 3Dh          ;function 3D = open file w/handle
      mov al, 0            ;access byte: 0000b:readonly,0001=writeonly,0010:R/W
      mov dx, offset fname ;must point to the ASCII filename and end with a zero
                           ;known as an ASCIIZ string
      int 21h
      jc fopen1            ;if DOS fails to open the file it will return with the carry flag
      mov fhandle, ax      ;otherwise the AX holds the file handle which must be saved
      jmp fopenex          ;then quit the procedure
    fopen1:
      mov ah, 9                ;if here then there was an error, show the message and...
      mov dx, offset fopenmsg
      int 21h
      inc fopenerr             ;set the error flag, then quit
    fopenex:
      ret
    fopen endp
    
    end main
    

  10. Save the changes, then [Y] to copy, [Y] to compile, [Y] to link and [N] to execute. Run dev xtype again and make these changes:

    .model tiny
    .stack 200h
    .data
    msg             db "Press a key to continue...$"
    fopenmsg        db "Cannot open specified file.",0Dh,0Ah,'$'
    freadmsg        db "Error occured while reading the file.",0Dh,0Ah,'$'
    crlf            db 0Dh, 0Ah, '$'
    fhandle         dw 0FFFFh ;invalid file handle
    fname           db "TEST.TXT",0
    fbuf            db 2000 dup(0)
    crlfcount       db 0
    bufsize         dw 0
    fsizehi         dw 0
    fsizelo         dw 0
    fopenerr        db 0
    freaderr        db 0
    fsizeeven       db 0
    fdone           db 0
    lastread        db 0
    
    .code
    main proc
      mov ax, @data
      mov ds, ax
    
    start:
    ;open the file, check an error flag quit if set otherwise continue  
      call fopen
      cmp fopenerr, 0
      jne terminate
    ;check the file size and if it is evenly divisible by 2000 (the buffer size
    
      call fsize
    
    main1:
    ;read the file and set a file done flag, if done then quit
    
    main2:
      mov cx, bufsize      ;set loop counter
      mov bx, offset fbuf  ;set base indexed addressing
      xor si, si           ;set offset pointer to zero
    main3:  
      mov dl, [bx+si]      ;read character from file buffer in RAM
      mov ah, 2            ;DOS function 2 display character
      int 21h
      cmp dl, 0Ah          ;watch for a line feed
      je inccrlf           ;if it is jump to the counter otherwize continue
    main4:
      inc si               ;point to the next char in the file buffer
      loop main3           ;continue the loop displaying chars on screen
      jmp main1            ;when the buffer is done, go read more info from the file
    inccrlf:
      inc crlfcount        ;add 1 to the line feed count
      cmp crlfcount, 23    ;have there been 24 line feeds displayed (screen is full)
      ja main5             ;yes: jump out to the pause code
      jmp main4            ;no: continue displaying chars on screen
    main5:
    ;set crlfcount back to 0
      push cx              ;save current cx (loop counter) on the stack
      xor cx, cx           ;clear it
      mov crlfcount, cl    ;clear line feed counter variable
      pop cx               ;restore loop counter from the stack
    
      mov ah, 9            ;function 9: display a string
      mov dx, offset msg   ;the pause message
      int 21h              ;call DOS to show the string
      
      mov ah, 8            ;function 8 = get a key w/o echo
      int 21h              ;this waits for the user to press any key
      
      mov ah, 9            ;these three lines display a carriage return/line feed
      mov dx, offset crlf
      int 21h
    
      jmp main3            ;continue displaying chars from the file buffer
    
    terminate:
      mov ax, 4C00h             ;function 4C = quit program
      int 21h
    main endp
    fopen proc
      mov ah, 3Dh          ;function 3D = open file w/handle
      mov al, 0            ;access byte: 0000b:readonly,0001=writeonly,0010:R/W
      mov dx, offset fname ;must point to the ASCII filename and end with a zero
                           ;known as an ASCIIZ string
      int 21h
      jc fopen1            ;if DOS fails to open the file it will return with the carry flag
      mov fhandle, ax      ;otherwise the AX holds the file handle which must be saved
      jmp fopenex          ;then quit the procedure
    fopen1:
      mov ah, 9                ;if here then there was an error, show the message and...
      mov dx, offset fopenmsg
      int 21h
      inc fopenerr             ;set the error flag, then quit
    fopenex:
      ret
    fopen endp
    
    fsize proc
      mov ax, 4202h    ;move file position pointer
                       ;method 2 in AL means reckon from end of file
      mov bx, fhandle  ;specify an open file by its handle number
      xor cx, cx       ;start position is start of file 
      xor dx, dx       ;held as CX:DX = 0
      int 21h         
    
      mov fsizelo, ax  ;position will be returned as a 32-bit value stored as DX:AX
      mov fsizehi, dx 
    ;test for divisible by 2000
      mov cx, 2000
      div cx          ;divides implicit ax by cx, quotient (number of times to 
                      ;loop) left in ax, remainder left in dx (if zero it is even
                      ;divisible by 2000)
      cmp dx, 0       ;evenly divisible?
      jne fsizeex      ;yes: jump over the adjustment
      inc fsizeeven   ;set warning flag
    fsizeex:
      mov ax, 4200h   ;reset file pointer to beginning of the file
      mov bx, fhandle
      xor cx, cx
      xor dx, dx
      int 21h
      ret
    fsize endp
    end main
    

  11. The DOS call in fsize that starts with the instruction "mov ax, 4202" is a programmer's trick to determine the size of the file by moving the current DOS file pointer from the beginning of the file (where it is when it is opened) to the end which is what this call does. by doing this, the current file pointer position is returned in DX:AX and since it points to the last byte in the file it is the same as its size in bytes. Once this is done, the pointer must be returned to the beginning of the file so that the sequential reads can begin in the next part of the program. Save these changes and exit EDIT. Press [Y] to copy the source file to the floppy, [Y] to compile, [Y] to link and [N] to execute. Run dev xtype again and make these changes:

    .model tiny
    .stack 200h
    .data
    msg             db "Press a key to continue...$"
    fopenmsg        db "Cannot open specified file.",0Dh,0Ah,'$'
    freadmsg        db "Error occured while reading the file.",0Dh,0Ah,'$'
    crlf            db 0Dh, 0Ah, '$'
    fhandle         dw 0FFFFh ;invalid file handle
    fname           db "TEST.TXT",0
    fbuf            db 2000 dup(0)
    crlfcount       db 0
    bufsize         dw 0
    fsizehi         dw 0
    fsizelo         dw 0
    fopenerr        db 0
    freaderr        db 0
    fsizeeven       db 0
    fdone           db 0
    lastread        db 0
    
    .code
    main proc
      mov ax, @data
      mov ds, ax
    
    start:
    ;open the file, check an error flag quit if set otherwise continue  
      call fopen
      cmp fopenerr, 0
      jne terminate
    ;check the file size and if it is evenly divisible by 2000 (the buffer size
      call fsize
    
    main1:
    ;read the file and set a file done flag, if done then quit
    
      call fread
      cmp fdone, 0
      jne terminate
      cmp freaderr, 0
      jne terminate
    
    main2:
      mov cx, bufsize      ;set loop counter
      mov bx, offset fbuf  ;set base indexed addressing
      xor si, si           ;set offset pointer to zero
    main3:  
      mov dl, [bx+si]      ;read character from file buffer in RAM
      mov ah, 2            ;DOS function 2 display character
      int 21h
      cmp dl, 0Ah          ;watch for a line feed
      je inccrlf           ;if it is jump to the counter otherwize continue
    main4:
      inc si               ;point to the next char in the file buffer
      loop main3           ;continue the loop displaying chars on screen
      jmp main1            ;when the buffer is done, go read more info from the file
    inccrlf:
      inc crlfcount        ;add 1 to the line feed count
      cmp crlfcount, 23    ;have there been 24 line feeds displayed (screen is full)
      ja main5             ;yes: jump out to the pause code
      jmp main4            ;no: continue displaying chars on screen
    main5:
    ;set crlfcount back to 0
      push cx              ;save current cx (loop counter) on the stack
      xor cx, cx           ;clear it
      mov crlfcount, cl    ;clear line feed counter variable
      pop cx               ;restore loop counter from the stack
    
      mov ah, 9            ;function 9: display a string
      mov dx, offset msg   ;the pause message
      int 21h              ;call DOS to show the string
      
      mov ah, 8            ;function 8 = get a key w/o echo
      int 21h              ;this waits for the user to press any key
      
      mov ah, 9            ;these three lines display a carriage return/line feed
      mov dx, offset crlf
      int 21h
    
      jmp main3            ;continue displaying chars from the file buffer
    
    terminate:
      mov ax, 4C00h             ;function 4C = quit program
      int 21h
    main endp
    fopen proc
      mov ah, 3Dh          ;function 3D = open file w/handle
      mov al, 0            ;access byte: 0000b:readonly,0001=writeonly,0010:R/W
      mov dx, offset fname ;must point to the ASCII filename and end with a zero
                           ;known as an ASCIIZ string
      int 21h
      jc fopen1            ;if DOS fails to open the file it will return with the carry flag
      mov fhandle, ax      ;otherwise the AX holds the file handle which must be saved
      jmp fopenex          ;then quit the procedure
    fopen1:
      mov ah, 9                ;if here then there was an error, show the message and...
      mov dx, offset fopenmsg
      int 21h
      inc fopenerr             ;set the error flag, then quit
    fopenex:
      ret
    fopen endp
    fsize proc
      mov ax, 4202h    ;move file position pointer
                       ;method 2 in AL means reckon from end of file
      mov bx, fhandle  ;specify an open file by its handle number
      xor cx, cx       ;start position is start of file 
      xor dx, dx       ;held as CX:DX = 0
      int 21h         
    
      mov fsizelo, ax  ;position will be returned as a 32-bit value stored as DX:AX
      mov fsizehi, dx 
    ;test for divisible by 2000
      mov cx, 2000
      div cx          ;divides implicit ax by cx, quotient (number of times to 
                      ;loop) left in ax, remainder left in dx (if zero it is even
                      ;divisible by 2000)
      cmp dx, 0       ;evenly divisible?
      jne fsizeex      ;yes: jump over the adjustment
      inc fsizeeven   ;set warning flag
    fsizeex:
      mov ax, 4200h   ;reset file pointer to beginning of the file
      mov bx, fhandle
      xor cx, cx
      xor dx, dx
      int 21h
      ret
    fsize endp
    
    fread proc
      cmp lastread, 0      ;check for a last read               
      ja fread3            ;yes if greater than zero, else continue
    
      mov ah, 3Fh          ;function 3F = read from file using handle
      mov bx, fhandle      ;refers to the file using its handle
      mov cx, 2000         ;number of bytes to read
      mov dx, offset fbuf  ;address of the buffer to be filled with file data
      int 21h              ;call DOS to read from the file
    
      jc fread1            ;carry: there was a problem reading the file, else
      cmp ax, 2000         ;number of bytes read good?
      jne fread2           ;no then set for last read
      jmp freadex
    fread1:
      mov ah, 9
      mov dx, offset freadmsg
      int 21h
      inc freaderr         ;we are here if there was a problem reading the file
    fread2:
      inc lastread         ;this prevents another read attempt
      cmp fsizeeven, 0     ;if even multiple of 2000 then 
      jne fread3           ;indicate that the file is done
      jmp freadex          ;otherwise quit so program can continue
    fread3:
      inc fdone            ;this notifies the program to quit immediately
    freadex:
      mov bufsize, ax      ;save number of valid bytes read
      ret
    fread endp
    
    end main
    

  12. Save the changes and exit EDIT, [Y] to copy, [Y] to compile, [Y] to link, [N] to execute. At this point the program works, in that it will open the file named "TEST.TXT" and display one screen at a time. Test it by copying any text file to the root of the K: drive and then renaming the file TEST.TXT. You should test it with a large file and then with one smaller than one screen to be sure that it can handle it right. You should then create a test file that is exactly 2000 bytes in size to be sure that it handles this one correctly and another that is 4000 bytes in size.

  13. Once these tests are complete run dev xtype and make the following changes:

    .model tiny
    .stack 200h
    .data
    msg             db "Press a key to continue...$"
    fopenmsg        db "Cannot open specified file.",0Dh,0Ah,'$'
    freadmsg        db "Error occured while reading the file.",0Dh,0Ah,'$'
    crlf            db 0Dh, 0Ah, '$'
    fhandle         dw 0FFFFh ;invalid file handle
    fname           db 129 dup(0)
    fbuf            db 2000 dup(0)
    crlfcount       db 0
    bufsize         dw 0
    fsizehi         dw 0
    fsizelo         dw 0
    fopenerr        db 0
    freaderr        db 0
    fsizeeven       db 0
    fdone           db 0
    lastread        db 0
    
    .code
    main proc
      mov ax, @data
      mov ds, ax
    
    start:
    
    ;get the commandline passed parameter
      call getparams
    
    ;open the file, check an error flag quit if set otherwise continue  
      call fopen
      cmp fopenerr, 0
      jne terminate
    ;check the file size and if it is evenly divisible by 2000 (the buffer size
      call fsize
    
    main1:
    ;read the file and set a file done flag, if done then quit
    
      call fread
      cmp fdone, 0
      jne terminate
      cmp freaderr, 0
      jne terminate
    
    main2:
      mov cx, bufsize      ;set loop counter
      mov bx, offset fbuf  ;set base indexed addressing
      xor si, si           ;set offset pointer to zero
    main3:  
      mov dl, [bx+si]      ;read character from file buffer in RAM
      mov ah, 2            ;DOS function 2 display character
      int 21h
      cmp dl, 0Ah          ;watch for a line feed
      je inccrlf           ;if it is jump to the counter otherwize continue
    main4:
      inc si               ;point to the next char in the file buffer
      loop main3           ;continue the loop displaying chars on screen
      jmp main1            ;when the buffer is done, go read more info from the file
    inccrlf:
      inc crlfcount        ;add 1 to the line feed count
      cmp crlfcount, 23    ;have there been 24 line feeds displayed (screen is full)
      ja main5             ;yes: jump out to the pause code
      jmp main4            ;no: continue displaying chars on screen
    main5:
    ;set crlfcount back to 0
      push cx              ;save current cx (loop counter) on the stack
      xor cx, cx           ;clear it
      mov crlfcount, cl    ;clear line feed counter variable
      pop cx               ;restore loop counter from the stack
    
      mov ah, 9            ;function 9: display a string
      mov dx, offset msg   ;the pause message
      int 21h              ;call DOS to show the string
      
      mov ah, 8            ;function 8 = get a key w/o echo
      int 21h              ;this waits for the user to press any key
      
      mov ah, 9            ;these three lines display a carriage return/line feed
      mov dx, offset crlf
      int 21h
    
      jmp main3            ;continue displaying chars from the file buffer
    
    terminate:
    
      cmp fhandle, 0FFFFh       ;same as original value?
      je term2                  ;yes: then just quit, otherwise...
      mov ah, 3Eh               ;function 3Eh, close open file
      mov bx, fhandle
      int 21h
    term2:
      mov ax, 4C00h             ;function 4C = quit program
      int 21h
    main endp
    fopen proc
      mov ah, 3Dh          ;function 3D = open file w/handle
      mov al, 0            ;access byte: 0000b:readonly,0001=writeonly,0010:R/W
      mov dx, offset fname ;must point to the ASCII filename and end with a zero
                           ;known as an ASCIIZ string
      int 21h
      jc fopen1            ;if DOS fails to open the file it will return with the carry flag
      mov fhandle, ax      ;otherwise the AX holds the file handle which must be saved
      jmp fopenex          ;then quit the procedure
    fopen1:
      mov ah, 9                ;if here then there was an error, show the message and...
      mov dx, offset fopenmsg
      int 21h
      inc fopenerr             ;set the error flag, then quit
    fopenex:
      ret
    fopen endp
    fsize proc
      mov ax, 4202h    ;move file position pointer
                       ;method 2 in AL means reckon from end of file
      mov bx, fhandle  ;specify an open file by its handle number
      xor cx, cx       ;start position is start of file 
      xor dx, dx       ;held as CX:DX = 0
      int 21h         
    
      mov fsizelo, ax  ;position will be returned as a 32-bit value stored as DX:AX
      mov fsizehi, dx 
    ;test for divisible by 2000
      mov cx, 2000
      div cx          ;divides implicit ax by cx, quotient (number of times to 
                      ;loop) left in ax, remainder left in dx (if zero it is even
                      ;divisible by 2000)
      cmp dx, 0       ;evenly divisible?
      jne fsizeex      ;yes: jump over the adjustment
      inc fsizeeven   ;set warning flag
    fsizeex:
      mov ax, 4200h   ;reset file pointer to beginning of the file
      mov bx, fhandle
      xor cx, cx
      xor dx, dx
      int 21h
      ret
    fsize endp
    
    fread proc
      cmp lastread, 0      ;check for a last read               
      ja fread3            ;yes if greater than zero, else continue
    
      mov ah, 3Fh          ;function 3F = read from file using handle
      mov bx, fhandle      ;refers to the file using its handle
      mov cx, 2000         ;number of bytes to read
      mov dx, offset fbuf  ;address of the buffer to be filled with file data
      int 21h              ;call DOS to read from the file
    
      jc fread1            ;carry: there was a problem reading the file, else
      cmp ax, 2000         ;number of bytes read good?
      jne fread2           ;no then set for last read
      jmp freadex
    fread1:
      mov ah, 9
      mov dx, offset freadmsg
      int 21h
      inc freaderr         ;we are here if there was a problem reading the file
    fread2:
      inc lastread         ;this prevents another read attempt
      cmp fsizeeven, 0     ;if even multiple of 2000 then 
      jne fread3           ;indicate that the file is done
      jmp freadex          ;otherwise quit so program can continue
    fread3:
      inc fdone            ;this notifies the program to quit immediately
    freadex:
      mov bufsize, ax      ;save number of valid bytes read
      ret
    fread endp
    
    getparams proc
      mov di, offset fname ;now 129 zeros
      mov ah, 51h          ;function 51h: get PSP address (Program Segment Prefix)
                           ;this is where DOS is holding the commandline parameters
      int 21h
      mov es, bx           ;segment is returned in BX, move it to the DS segment
      mov si, 80h          ;offset to start of passed parameters in the PSP
      xor cx, cx           ;CX=0
      mov cl, es:[si]      ;segment override: read the byte located at es:si 
    ;this has set the loop counter to the length of the parameters entered by the user
      add si, 2            ;offset 80h holds the length, the next byte holds the space
                           ;between the exe and the start of the parameters
    gp1:
      mov al, es:[si]      ;get the byte
      cmp al, 0Dh          ;is it the [Enter] key?
      je gpexit            ;yes: then end of desired data has been reached   
      mov [di], al         ;put it into fname variable
      inc si
      inc di               ;advance both pointers
      loop gp1
    
    gpexit:
      ret
    getparams endp
    
    end main
    

  14. Also included is the proper operation of closing the open file while quitting the program. DOS has been handling this automatically for us, but it is not good programming practice to depend on DOS for the clean up. Save the changes and exit EDIT. [Y] to copy it to the floppy, [Y] to compile, [Y] to link and [N] to execute. Now execute XTYPE and follow it with a valid filename. The string held in the PSP has been upper cased by DOS and any valid relative or absolute path may be included in the file name:

    K:\>xtype q:\dos\country.txt
    ...
    
  15. This concludes the simple execution of a program that can use passed parameters from the command line. In a future exercise a program will be developed that can take user input and save it to a file named in the commandline.

Back to Page Top

Copyrightę2000-2006 Brian Robinson ALL RIGHTS RESERVED