📄 receive.asm
字号:
; RECEIVE.ASM
;
; This program is the receiver portion of the programs that transmit files
; across a Laplink compatible parallel cable.
;
; This program assumes that the user want to use LPT1: for transmission.
; Adjust the equates, or read the port from the command line if this
; is inappropriate.
.286
.xlist
include stdlib.a
includelib stdlib.lib
.list
dseg segment para public 'data'
TimeOutConst equ 100 ;About 1 min on 66Mhz 486.
PrtrBase equ 8 ;Offset to LPT1: adrs.
MyPortAdrs word ? ;Holds printer port address.
FileHandle word ? ;Handle for output file.
FileBuffer byte 512 dup (?) ;Buffer for incoming data.
FileSize dword ? ;Size of incoming file.
FileName byte 128 dup (0) ;Holds filename
dseg ends
cseg segment para public 'code'
assume cs:cseg, ds:dseg
; TestAbort- Reads the keyboard and gives the user the opportunity to
; hit the ctrl-C key.
TestAbort proc near
push ax
mov ah, 1
int 16h ;See if keypress.
je NoKeypress
mov ah, 8 ;Read char, chk for ctrl-C
int 21h
NoKeyPress: pop ax
ret
TestAbort endp
; GetByte- Reads a single byte from the parallel port (four bits at
; at time). Returns the byte in AL.
GetByte proc near
push cx
push dx
; Receive the L.O. Nibble.
mov dx, MyPortAdrs
mov al, 10h ;Signal not busy.
out dx, al
inc dx ;Point at status port
W4DLp: mov cx, 10000
Wait4Data: in al, dx ;See if data available.
test al, 80h ; (bit 7=0 if data available).
loopne Wait4Data
je DataIsAvail ;Is data available?
call TestAbort ;If not, check for ctrl-C.
jmp W4DLp
DataIsAvail: shr al, 3 ;Save this four bit package
and al, 0Fh ; (This is the L.O. nibble
mov ah, al ; for our byte).
dec dx ;Point at data register.
mov al, 0 ;Signal data taken.
out dx, al
inc dx ;Point at status register.
W4ALp: mov cx, 10000
Wait4Ack: in al, dx ;Wait for transmitter to
test al, 80h ; retract data available.
loope Wait4Ack ;Loop until data not avail.
jne NextNibble ;Branch if data not avail.
call TestAbort ;Let user hit ctrl-C.
jmp W4ALp
; Receive the H.O. nibble:
NextNibble: dec dx ;Point at data register.
mov al, 10h ;Signal not busy
out dx, al
inc dx ;Point at status port
W4D2Lp: mov cx, 10000
Wait4Data2: in al, dx ;See if data available.
test al, 80h ; (bit 7=0 if data available).
loopne Wait4Data2 ;Loop until data available.
je DataAvail2 ;Branch if data available.
call TestAbort ;Check for ctrl-C.
jmp W4D2Lp
DataAvail2: shl al, 1 ;Merge this H.O. nibble
and al, 0F0h ; with the existing L.O.
or ah, al ; nibble.
dec dx ;Point at data register.
mov al, 0 ;Signal data taken.
out dx, al
inc dx ;Point at status register.
W4A2Lp: mov cx, 10000
Wait4Ack2: in al, dx ;Wait for transmitter to
test al, 80h ; retract data available.
loope Wait4Ack2 ;Wait for data not available.
jne ReturnData ;Branch if ack.
call TestAbort ;Check for ctrl-C
jmp W4A2Lp
ReturnData: mov al, ah ;Put data in al.
pop dx
pop cx
ret
GetByte endp
; Synchronize- This procedure waits until it sees all zeros on the input
; bits we receive from the transmiting site. Once it receives
; all zeros, it writes all ones to the output port. When
; all ones come back, it writes all zeros. It repeats this
; process until the transmiting site writes the value 05h.
Synchronize proc near
print
byte "Synchronizing with transmitter program"
byte cr,lf,0
mov dx, MyPortAdrs
mov al, 0 ;Initialize our output port
out dx, al ; to prevent confusion.
mov bx, TimeOutConst ;Time out condition.
SyncLoop: mov cx, 0 ;For time out purposes.
SyncLoop0: inc dx ;Point at input port.
in al, dx ;Read our input bits.
dec dx
and al, 78h ;Keep only the data bits.
cmp al, 78h ;Check for all ones.
je Got1s ;Branch if all ones.
cmp al, 0 ;See if all zeros.
loopne SyncLoop0
; Since we just saw a zero, write all ones to the output port.
mov al, 0FFh ;Write all ones
out dx, al
; Now wait for all ones to arrive from the transmiting site.
SyncLoop1: inc dx ;Point at status register.
in al, dx ;Read status port.
dec dx ;Point back at data register.
and al, 78h ;Keep only the data bits.
cmp al, 78h ;Are they all ones?
loopne SyncLoop1 ;Repeat while not ones.
je Got1s ;Branch if got ones.
; If we've timed out, check to see if the user has pressed ctrl-C to
; abort.
call TestAbort ;Check for ctrl-C.
dec bx ;See if we've timed out.
jne SyncLoop ;Repeat if time-out.
print
byte "Receive: connection timed out during synchronization"
byte cr,lf,0
clc ;Signal time-out.
ret
; Jump down here once we've seen both a zero and a one. Send the two
; in combinations until we get a 05h from the transmiting site or the
; user presses Ctrl-C.
Got1s: inc dx ;Point at status register.
in al, dx ;Just copy whatever appears
dec dx ; in our input port to the
shr al, 3 ; output port until the
and al, 0Fh ; transmiting site sends
cmp al, 05h ; us the value 05h
je Synchronized
not al ;Keep inverting what we get
out dx, al ; and send it to xmitter.
call TestAbort ;Check for CTRL-C here.
jmp Got1s
; Okay, we're synchronized. Return to the caller.
Synchronized:
and al, 0Fh ;Make sure busy bit is one
out dx, al ; (bit 4=0 for busy=1).
print
byte "Synchronized with transmiting site"
byte cr,lf,0
stc
ret
Synchronize endp
; GetFileInfo- The transmitting program sends us the file length and a
; zero terminated filename. Get that data here.
GetFileInfo proc near
mov dx, MyPortAdrs
mov al, 10h ;Set busy bit to zero.
out dx, al ;Tell xmit pgm, we're ready.
; First four bytes contain the filesize:
call GetByte
mov byte ptr FileSize, al
call GetByte
mov byte ptr FileSize+1, al
call GetByte
mov byte ptr FileSize+2, al
call GetByte
mov byte ptr FileSize+3, al
; The next n bytes (up to a zero terminating byte) contain the filename:
mov bx, 0
GetFileName: call GetByte
mov FileName[bx], al
call TestAbort
inc bx
cmp al, 0
jne GetFileName
ret
GetFileInfo endp
; GetFileData- Receives the file data from the transmitting site
; and writes it to the output file.
GetFileData proc near
; First, see if we have more than 512 bytes left to go
cmp word ptr FileSize+2, 0 ;If H.O. word is not
jne MoreThan512 ; zero, more than 512.
cmp word ptr FileSize, 512 ;If H.O. is zero, just
jbe LastBlock ; check L.O. word.
; We've got more than 512 bytes left to go in this file, read 512 bytes
; at this point.
MoreThan512: mov cx, 512 ;Receive 512 bytes
lea bx, FileBuffer ; from the xmitter.
ReadLoop: call GetByte ;Read a byte.
mov [bx], al ;Save the byte away.
inc bx ;Move on to next
loop ReadLoop ; buffer element.
; Okay, write the data to the file:
mov ah, 40h ;DOS write opcode.
mov bx, FileHandle ;Write to this file.
mov cx, 512 ;Write 512 bytes.
lea dx, Filebuffer ;From this address.
int 21h
jc BadWrite ;Quit if error.
; Decrement the file size by 512 bytes:
sub word ptr FileSize, 512 ;32-bit subtraction
sbb word ptr FileSize, 0 ; of 512.
jmp GetFileData
; Process the last block, that contains 1..511 bytes, here.
LastBlock:
mov cx, word ptr FileSize ;Receive the last
lea bx, FileBuffer ; 1..511 bytes from
ReadLB: call GetByte ; the transmitter.
mov [bx], al
inc bx
loop ReadLB
mov ah, 40h ;Write the last block
mov bx, FileHandle ; of bytes to the
mov cx, word ptr FileSize ; file.
lea dx, Filebuffer
int 21h
jnc Closefile
BadWrite: print
byte "DOS error #",0
puti
print
byte " while writing data.",cr,lf,0
; Close the file here.
CloseFile: mov bx, FileHandle ;Close this file.
mov ah, 3Eh ;DOS close opcode.
int 21h
ret
GetFileData endp
; Here's the main program that gets the whole ball rolling.
Main proc
mov ax, dseg
mov ds, ax
meminit
; First, get the address of LPT1: from the BIOS variables area.
mov ax, 40h ;Point at BIOS variable segment.
mov es, ax
mov ax, es:[PrtrBase]
mov MyPortAdrs, ax
call Synchronize ;Wait for the transmitter program.
jnc Quit
call GetFileInfo ;Get file name and size.
printf
byte "Filename: %s\nFile size: %ld\n",0
dword Filename, FileSize
mov ah, 3Ch ;Create file.
mov cx, 0 ;Standard attributes
lea dx, Filename
int 21h
jnc GoodOpen
print
byte "Error opening file",cr,lf,0
jmp Quit
GoodOpen: mov FileHandle, ax
call GetFileData ;Get the file's data.
Quit: ExitPgm ;DOS macro to quit program.
Main endp
cseg ends
sseg segment para stack 'stack'
stk byte 1024 dup ("stack ")
sseg ends
zzzzzzseg segment para public 'zzzzzz'
LastBytes byte 16 dup (?)
zzzzzzseg ends
end Main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -