UMBC CMSC 211

UMBC | CSEE


Tail Command

To partially emulate the UNIX tail command, we will let the user see the the last ten lines of a file:
.MODEL SMALL
INCLUDE PCMAC.INC
ASSUME SS:NOTHING
;
.STACK 100
; ; Constants
BUFLEN EQU 512 ; Must be a power of 2
CR EQU 13
LF EQU 10
WANTED EQU 20 ; Number of lines of tail desired
CtrlZ EQU 26 ; Sometimes used to end text files
;
.DATA
Buffer DB BUFLEN DUP (?)
Handle DW ? ; The file handle
LCount DW ? ; Number of Line Feeds encountered
Start DD ? ; loc of buf srart in file; least sig first
UsageMsg DB 'usage: tail filename',CR,LF,'$'
;
.CODE
EXTRN ParseCmd : NEAR, CseCmd : NEAR, CCheck : NEAR
Tail PROC
mov ax, @data
mov ds, ax
call ParseCmd ; Get filename from command line
test si, si
jnz DoOpen
_PutStr UsageMsg
_Exit 2
DoOpen:
push ds
_Open si, Read, es
pop ds
call CCheck
mov Handle, ax
mov LCount, Wanted + 1 ; Initialize line count
_LSeek Handle, FromEnd, 0 ; Find length of file
call CCheck
add ax, BufLEN - 1 ; Round end of file to next
; even multiple
adc dx, 0; ; of BUFLEN (NOTE
and ax, NOT (BUFLEN - 1) ; MULTIPLE PRECISION
mov WORD PTR [Start], ax ; BUFLEN must be a pwr
mov WORD PTR [Start + 2], dx ; of 2 FOR THE 'AND'
; TO WORK
mov ax, ds
mov es, ax
pushf
std
ReadNextRecord:
sub WORD PTR [Start], BUFLEN
sbb WORD PTR [Start + 2], 0
jge DoRead
mov WORD PTR [Start], 0 ; If < 0, we're at start
mov WORD PTR [Start + 2], 0;
jmp Done
DoRead:
_LSeek Handle, FromStart, <WORD PTR Start>, <WORD PTR Start+2>
call CCheck
_Read Handle, buffer, BUFLEN
call CCheck
mov cx, ax ; save number of characters read
jcxz ReadNextRecord ; shouldn't happen
mov di, OFFSET Buffer -1 ; Set up ptr to end of buffer
add di, cx
mov al, LF Character to search for
LineLoop:
repne scasb ; stop on LF or start of buffer
jne ReadNextRecord ; LF not found
dec LCount
jnz LineLoop
sub di, OFFSET Buffer - 2 ; di already one past LF
add WORD PTR [Start], di ; update to start of tail
adc WORD PTR [Start + 2], 0
Done:
_Lseek Handle, FromSTart, <WORD PTR Start>, <WORD PTR Start + 2> + 2>
call CCheck
cld ; Reset direction up
OutputLoop:
_Read Handle, buffer, BUFLEN
call CCheck
mov cx, ax; ; number of bytes read => cx
jcxz EOF
mov si, OFFSET Buffer
DisplayLoop:
lodsb
cmp al, CtrlZ ; Sometimes text file terminator
je EOF
_PutCh al
loop DisplayLoop
jmp OutputLoop
EOF:
popf
_Exit 0 ; normal termination
Tail ENDP
END Tail


UMBC | CSEE