Hardware Reference
In-Depth Information
the main program, which determines the names of the executable and the auxiliary
files. For example, for the program of Fig. C-17(a) use
as88 strngcpy.s stringpr.s
The program of Fig. C-17(b) outputs strings in reverse order. We will now look at
them in turn.
To demonstrate that the line numbers are really just comments, in Fig. C-17(a)
we have numbered the lines starting with the first label, omitting what comes
before them. The main program, on lines 2 through 8, first calls
strngcpy
with two
arguments, the source string,
mesg2
, and the destination string,
mesg1
, in order to
copy the source to the destination.
Now let us look at
strngcpy
, starting on line 9. It expects that the addresses of
the destination buffer and the string source have been pushed onto the stack just
before the subroutine is called. On lines 10 to 13, the registers used are saved by
pushing them onto the stack so that they can be restored later on lines 27 to 30. On
line 14, we copy
SP
to
BP
in the usual way. Now
BP
can be used to load the argu-
ments. Again, on line 26, we clean the stack by copying
BP
to
SP
.
The heart of the subroutine is the instruction
REP MOVSB
, on line 24. The
instruction
MOVSB
moves the byte pointed to by
SI
to the memory address pointed
to by
DI
. Both
SI
and
DI
are then incremented by 1. The
REP
creates a loop in
which this instruction is repeated, decrementing
CX
by 1 for each byte moved. The
loop is terminated when
CX
reaches 0.
Before we can run the
REP MOVSB
loop, however, we have to set up the regis-
ters, which is done in lines 15 through 22. The source index,
SI
, is copied from the
argument on the stack on line 21; the destination index,
DI
, is set up on line 22.
Obtaining the value of
CX
is more involved. Note that the end of a string is indi-
cated by a zero byte. The
MOVSB
instruction does not affect the zero flag, but the
instruction
SCASB
(scan byte string) does. It compares the value pointed to by
DI
with the value in
AL
, and it increments
DI
on the fly. Moreover, it is repeatable like
MOVSB
. So, on line 15
AX
and hence
AL
is cleared, on line 16 the pointer for
DI
is
fetched from the stack, and
CX
is initialized to
1 on line 17. On line 18, we have
the
REPNZ SCASB
, which does the comparison in loop context, and sets the zero
flag on equality. At each step of the loop,
CX
is decremented, and the loop stops
when the zero flag is set, because the
REPNZ
checks both the zero flag and
CX
.
The number of steps for the
MOVSB
loop is now computed as the difference of the
current value of
CX
and the previous
−
1 on lines 19 and 20.
It is cumbersome that there are two repeatable instructions necessary, but this
is the price for the design choice that move instructions never affect the condition
codes. During the loops, the index registers have to be incremented, and to this
end it is necessary that the direction flag is cleared.
Lines 23 and 25 print the copied string by means of a subroutine,
stringpr
,
which is in the
examples
directory. It is straightforward and will not be discussed
here.
−