home *** CD-ROM | disk | FTP | other *** search
- Page 55,132
- Title SEND - Send a file using XMODEM protocol
-
- SPECIAL Equ 0 ;If true, include data size in block
-
- If SPECIAL
- BLOCK Struc
- B_SOH Db 001H ;Start of header
- B_BLK1 Db 000H ;Block number
- B_BLK2 Db 0FFH ;(Block number)'
- B_CNT Db ? ;Count of bytes used in the data area
- B_DATA Db 128 Dup (?) ;The data area
- B_CHKSUM Db ? ;Checksum of the data
- BLOCK Ends
- Else
- BLOCK Struc
- B_SOH Db 001H ;Start of header
- B_BLK1 Db 000H ;Block number
- B_BLK2 Db 0FFH ;(Block number)'
- B_DATA Db 128 Dup (?) ;The data area
- B_CHKSUM Db ? ;Checksum of the data
- BLOCK Ends
- Endif
-
- ERROR Macro N
- Mov AH,09H ;Display the error message
- Lea DX,ERRMSG&N ;
- Int 021H ;
- Mov AX,04C10H+N ;And leave
- Int 021H ;
- Endm
-
- CODE Segment Public 'CODE'
- CODE Ends
-
- DATA Segment Public 'DATA'
-
- BAUD_TABLE Label Word
- Dw 9600 ;
- Dw 4800 ;
- Dw 2400 ;
- Dw 1200 ;
- Dw 600 ;
- Dw 300 ;
- Dw 150 ;
- Dw 110 ;
-
- FILENAME Db 64 Dup (0) ;Name of file to send
-
- BUFFER BLOCK <> ;The block buffer
-
- ERRMSG0 Db '?No output file specified',13,10,'$'
- ERRMSG1 Db '?Unable to create output file',13,10,'$'
- ERRMSG2 Db '?Invalid baud rate specified',13,10,'$'
- ERRMSG3 Db '?Transmitter time-out occurred',13,10,'$'
- ERRMSG4 Db '?Error while writing the output file',13,10,'$'
- ERRMSG5 Db '^C',13,10,'%Reception aborted via control-C',13,10,'$'
-
- TXTMSG1 Db 'Waiting for transmitter...',13,10,'$'
- TXTMSG2 Db 'Block number '
- TXTNUM2 Db '0 ',13,'$'
- TXTMSG3 Db 10,'Reception complete',13,10,'$'
- TXTMSG4 Db 'No retries needed',13,10,'$'
- TXTMSG5 Db 'Retry count was '
- TXTNUM5 Db '0 ',13,10,'$'
-
- MODE Db 11101011B ;9600 baud, odd parity, 1 stop bit,
- ;8 bit character
-
- BLOCK_COUNT Dw 0 ;Total block count
- RETRY_COUNT Dw 0 ;Retry count
-
- BLK_NUM Db 001H ;8 bit block number expected.
-
- DATA Ends
-
- STACK Segment Stack 'STACK'
-
- Dw 128 Dup (?) ;Program stack
-
- STACK Ends
-
- CODE Segment Public 'CODE'
-
- Assume CS:CODE,DS:Nothing,ES:Nothing,SS:STACK
-
- MAIN Proc Near
- Sti ;Enable interrupts
- Mov AX,DATA ;Set up ES
- Mov ES,AX ;
-
- Assume ES:DATA
-
- Cld ;Make sure the direction flag is clear
- Mov SI,080H ;Use SI to get the file name
- Lodsb ;Get the length
- Or AL,AL ;Is there anything??
- Jnz MAIN01 ;Yes. Proceed
- MAIN00: Mov AX,ES ;Set up DS
- Mov DS,AX ;
-
- Assume DS:DATA
-
- ERROR 0 ;Nope. Die!
-
- Assume DS:Nothing
-
- MAIN01: Cbw ;Make it a word count
- Mov CX,AX ;Copy to CX
-
- MAIN05: Jcxz MAIN00 ;If nothing left, error!
- Dec CX ;Decrement the character count
- Lodsb ;And get the character
- Cmp AL,020H ;Space or less??
- Ja MAIN10 ;Nope. Start the file name
- Jmp Short MAIN05 ;Try again...
-
- MAIN10: Lea DI,FILENAME ;Point DI to the file name buffer
- MAIN11: Stosb ;Store the character
- Jcxz MAIN20 ;Got the file name. Open the file
- Dec CX ;Decrement the character count
- Lodsb ;Get the next character
- Cmp AL,020H ;Is it a displayable character
- Ja MAIN11 ;Yes. Put it in the file name
-
- MAIN13: Jcxz MAIN20 ;No more characters?
- Dec CX ;Decrement the count
- Lodsb ;Get another character
- Cmp AL,020H ;Space or less??
- Ja MAIN15 ;Yes. See if it's a number
- Jmp Short MAIN13 ;Keep looking
-
- MAIN15: Xor DX,DX ;Clear DX
- MAIN16: Cmp AL,'0' ;Is this a digit??
- Jae MAIN18 ;Yes.
- MAIN17: ERROR 2 ;Not a valid baud rate
-
- MAIN18: Cmp AL,'9' ;Still a digit??
- Ja MAIN17 ;Nope.
- Sub AL,'0' ;Convert to binary
- Cbw ;Convert to a word
- Shl DX,1 ;Double the previous number
- Mov BX,DX ;Save in BX for a bit
- Shl DX,1 ;
- Shl DX,1 ;
- Add DX,BX ;Now DX = (Old DX)*10
- Add DX,AX ;Add in the last digit
- Jcxz MAIN19 ;All done.
- Dec CX ;Decrement the character count
- Lodsb ;And get a character
- Cmp AL,020H ;Space or less?
- Ja MAIN16 ;
-
- MAIN19: Mov AX,DX ;Put the baud rate in AX
- Lea DI,BAUD_TABLE ;Point to the baud rate table
- Mov CX,8 ;Eight entries in the table
- Repne Scasw ;Look for this baud rate
- Jne MAIN17 ;No good! Die!
- Mov AL,CL ;Get the index
- Mov CL,5 ;And position it
- Shl AL,CL ;
- Or AL,00001011B ;Odd parity, 1 stop bit, 8 bit character
- Mov MODE,AL ;And save it
-
- MAIN20: Mov AX,ES ;Set up DS
- Mov DS,AX ;
-
- Assume DS:DATA
-
- Mov AH,03CH ;Create the file specified
- Xor CX,CX ;With no attributes
- Lea DX,FILENAME ;
- Int 021H ;
- Jnc MAIN25 ;Proceed!
- ERROR 1 ;Couldn't create the file
-
- MAIN25: Mov BX,AX ;Put the handle in BX
-
- Xor AH,AH ;Initialize the RS232 channel
- Mov AL,MODE ;
- Xor DX,DX ;On channel zero
- Int 014H ;
-
- Mov AH,09H ;Display the "Waiting..." message
- Lea DX,TXTMSG1 ;
- Int 021H ;
-
- Mov CX,64 ;This shall be our original timeout
- MAIN30: Mov AH,06H ;See if a character is waiting
- Mov DL,0FFH ;
- Int 021H ;
- Jz MAIN32 ;Nope.
- Cmp AL,3 ;Is it a control-C??
- Jne MAIN32 ;
-
- Mov AH,03EH ;Close the input file
- Int 021H ;
- ERROR 5 ;And die
-
- MAIN32: Mov AX,0115H ;Send a NAK to the transmitter
- Xor DX,DX ;(channel 0)
- Int 014H ;
-
- Push CX ;Save CX on the stack
- Call GET_BLOCK ;Get a block of data
- Pop CX ;Restore CX
- Jnc MAIN35 ;Got one. Go check it.
-
- MAIN31: Loop MAIN30 ;Repeat until CX = 0
- Mov AH,03EH ;Close the input file
- Int 021H ;
- ERROR 3 ;And die!
-
- MAIN35: Cmp BUFFER.B_SOH,04H ;Is this the end of the file??
- Je MAIN80 ;Yes. Close the file and leave
-
- Lea DI,TXTNUM2 ;Fill in the block number
- Mov AX,BLOCK_COUNT ;
- Call FILL_NUM ;
- Mov AH,09H ;Display the block number
- Lea DX,TXTMSG2 ;
- Int 021H ;
-
- Mov AH,040H ;Write the file...
- If SPECIAL
- Mov CL,BUFFER.B_CNT ;This many bytes only!
- Xor CH,CH ;
- Else
- Mov CX,128 ;Up to 128 bytes
- Endif
- Lea DX,BUFFER.B_DATA ;From our buffer
- Int 021H ;
- Jnc MAIN40 ;Got it; now ship it
- Mov AH,03EH ;Close the input file
- Int 021H ;
- ERROR 4 ;And die (for some unknown reason)
-
- MAIN40: Mov AX,0105H ;Send an ACK
- Xor DX,DX ;
- Int 014H ;
-
- MAIN42: Call GET_BLOCK ;Get another block
- Jnc MAIN35 ;Check for EOF.
-
- Mov AX,0115H ;Send another NAK (just in case)
- Xor DX,DX ;
- Int 014H ;
- Jmp Short MAIN42 ;And try again
-
- ;
- ; End of file...
- ;
-
- MAIN80: Mov AX,0105H ;Send a final ACK
- Xor DX,DX ;
- Int 014H ;
-
- Mov AH,09H ;Display the EOT message
- Lea DX,TXTMSG3 ;
- Int 021H ;
-
- Mov AH,03EH ;Close the input file
- Int 021H ;
-
- Cmp RETRY_COUNT,0 ;Did we have to do any retries??
-
- Mov AH,09H ;No retries needed
- Lea DX,TXTMSG4 ;
- Int 021H ;
- Jmp Short MAIN99 ;Leave
-
- MAIN95: Lea DI,TXTNUM5 ;Point to the buffer
- Mov AX,RETRY_COUNT ;Get the count
- Call FILL_NUM ;
- Mov AH,09H ;And display the message
- Lea DX,TXTMSG5 ;
- Int 021H ;
-
- MAIN99: Mov AX,04C00H ;And leave
- Int 021H ;
- MAIN Endp
-
- ;
- ;
- ;
-
- FILL_NUM Proc Near
- Xor CX,CX ;Clear the character count
- Mov SI,10 ;Use SI to divide with
- FILL10: Xor DX,DX ;
- Div SI ;Divide DX:AX by SI (10)
- Add DL,'0' ;Convert DL to ASCII
- Push DX ;Save it on the stack
- Inc CX ;Increment the character count
- Or AX,AX ;Any more to do??
- Jnz FILL10 ;Yes. Keep going
- Cld ;(just to be sure)
- FILL20: Pop AX ;Get a character from the stack
- Stosb ;And store it
- Loop FILL20 ;Repeat CX times
- Ret ;And return
- FILL_NUM Endp
-
- ;
- ; Get a block from the transmitter
- ;
-
- GET_BLOCK Proc Near
- Cld ;(just to be sure)
- Lea DI,BUFFER ;Point to the buffer
- Mov CX,20 ;Time out for the first byte
-
- GETB10: Mov AH,06H ;See if a character is waiting
- Mov DL,0FFH ;
- Int 021H ;
- Jz GETB12 ;Nope.
- Cmp AL,3 ;Is it a control-C??
- Jne GETB12 ;
-
- Mov AH,03EH ;Close the input file
- Int 021H ;
- ERROR 5 ;And die
-
- GETB12: Mov AH,02H ;Get a character
- Xor DX,DX ;
- Int 014H ;
- Test AH,08EH ;Any errors??
- Jnz GETB14 ;Yup. Ignore it!
- Cmp AL,01H ;SOH??
- Je GETB20 ;Yes. Start the block
- Cmp AL,04H ;End-of-text??
- Je GETB15 ;Yes. Return it.
- Jmp Short GETB12 ;Wait for another character
-
- GETB14: Loop GETB10 ;Repeat until CX = 0
- Stc ;Set the carry
- Ret ;And return
-
- GETB15: Stosb ;Store the EOT
- Clc ;Clear carry...
- Ret ;...and return
-
- GETB20: Mov CX,(Size BLOCK-1) ;Repeat for the entire block
- Stosb ;Store the SOH
- GETB22: Mov SI,4 ;Use SI for a timeout count
- GETB24: Mov AH,02H ;Wait for another character
- Xor DX,DX ;
- Int 014H ;
- Test AH,080H ;Time-out??
- Jz GETB26 ;Nope.
- Dec SI ;Decrement the time-out count
- Jnz GETB24 ;And try again
- Jmp SEND_RETRY ;Send a retry
-
- GETB26: Stosb ;Store the character
- Loop GETB22 ;And try again
-
- Mov AL,BLK_NUM ;Get the expected block number
- Cmp AL,BUFFER.B_BLK1 ;Is this it??
- Jne SEND_RETRY ;Nope.
- Xor AL,0FFH ;Complement AL
- Cmp AL,BUFFER.B_BLK2 ;Double check
- Jne SEND_RETRY ;Nope.
-
- Lea SI,BUFFER.B_DATA ;Compute the checksum
- Xor AH,AH ;Clear AH
- Xor DX,DX ;Keep the checksum in DX
- Mov CX,128 ;Repeat for 128 bytes
- GETB30: Lodsb ;Get a byte
- Add DX,AX ;Add it to DX
- Loop GETB30 ;And repeat
- Mov AX,DX ;Put the sum in AX
- Mov DL,255 ;Now divide by 255
- Div DL ;
- Cmp BUFFER.B_CHKSUM,AH ;See if the check sum is O.K.
- Jne SEND_RETRY ;Nope. Send a retry
-
- Inc BLK_NUM ;Increment the expected block number
- Inc BLOCK_COUNT ;And the block count
- Clc ;
- Ret ;Otherwise return with carry clear
-
- SEND_RETRY:
- Mov AX,0115H ;Send a NAK
- Xor DX,DX ;
- Int 014H ;
- Inc RETRY_COUNT ;Increment the retry count
- Jmp GET_BLOCK ;And try all over again
- GET_BLOCK Endp
-
- CODE Ends
- End MAIN