Hardware Reference
In-Depth Information
After returning from
fillbuf
, line 24 checks whether anything was actually read.
If not, we jump out of the buffered read loop to the second part of the program in
line 25.
Now we are ready to scan the buffer. The symbol \n (line feed) is loaded into
AL
on line 26, and in line 27 this value is scanned for by
REP SCASB
and com-
pared to the symbols in the buffer. There are two ways to exit the loop: either
when
CX
hits zero or when a scanned symbol is a new line character. If the zero
flag is set, then the last symbol scanned was a \n and the file position of the current
symbol (one after the new line), is to be stored in the
linh
array. The count is then
incremented and the file position is computed from
BX
and the number of charac-
ters still available is in
CX
(lines 29 through 31). Lines 32 through 34 perform the
actual store, but since
STOS
assumes that the destination is in
DI
instead of in
SI
,
these registers are exchanged before and after the
STOS
. Lines 35 through 37
check whether more data is available in the buffer, and jump according to the value
of
CX
.
When the end of the file is reached, we have a complete list of file positions of
the heads of the lines. Because we started the
linh
array witha0word, we know
that the first line started at address 0, and that the next line starts at the position
given by
linh
+
2 etc. The size of line
n
can be found from the starting address of
line
n
1 minus the start address of line
n
.
The aim of the rest of the program is to read the number of a line, to read that
line into the buffer, and to output it by means of a
write
call. All the necessary
information can be found in the
linh
array, whose
n
th entry contains the position of
the start of line
n
in the file. If the line number requested is either 0 or out of
range, the program exits by jumping to label 7.
This part of the program starts with a call to the
getnum
subroutine on line 46.
This routine reads a line from standard input and stores it in the
linein
buffer, (on
lines 95 through 103). Next, we prepare for the
SSCANF
call. Considering the
reverse order of the arguments, we first push the address of
curlin
, which can hold
an integer value, then the address of the integer format string
numfmt
, and finally
the address of the buffer
linein
containing the number in decimal notation. The
system subroutine
SSCANF
puts the binary value in
curlin
if possible. On failure, it
returnsa0in
AX
. This return value is tested on line 48; on failure, the program
generates an error message through label 8.
If the
getnum
subroutine returns a valid integer in
curlin
, then we first copy it
in
BX
. Next we test the value against the range in lines 49 through 53, generating
an
EXIT
if the line number is out of range.
Then we must find the end of the selected line in the file and the number of
bytes to be read, so we multiply
BX
by 2 with a left shift
SHL
. The file position of
the intended line is copied to
AX
on line 55. The file position of the next line is in
CX
and will be used to compute the number of bytes in the current line.
To do a random read from a file, an
lseek
call is needed to set the file offset to
the byte to be read next. The
lseek
is performed with respect to the start of the file,
+