|
|||||
7
String
Instructions
7.1.
STRING PROCESSING
Till
now very simple instructions of
the 8088 microprocessor have
been
introduced.
In this chapter we will discuss a bit
more powerful
instructions
that
can process blocks of data
in one go. They are
called block processing
or
string
instructions. This is the
appropriate place to discuss
these
instructions
as we have just introduced a
block of memory, which is
the
video
memory. The vision of this
memory for the processor is
just a block of
memory
starting at a special address.
For example the clear
screen operation
initializes
this whole block to
0741.
There
are just 5 block processing
instructions in 8088. In the
primitive
form,
the instructions themselves
operate on a single cell of
memory at one
time.
However a special prefix
repeats the instruction in
hardware called the
REP
prefix. The REP prefix
allows these instructions to
operate on a number
of data
elements in one instruction.
This is not like a loop;
rather this
repetition
is hard coded in the
processor. The five
instructions are
STOS,
LODS,
CMPS, SCAS, and MOVS
called store string, load
string, compare
string,
scan string, and move
string respectively. MOVS is
the instruction
that
allows memory to memory
moves, as was discussed in
the exceptions to
the
memory to memory movement
rules. String instructions
are complex
instruction
in that they perform a
number of tasks against one
instruction.
And with
the REP prefix they
perform the task of a
complex loop in one
instruction.
This causes drastic speed
improvements in operations on
large
blocks
of memory. The reduction in
code size and the
improvement in speed
are
the two reasons why these
instructions were introduced in
the 8088
processor.
There
are a number of common
things in these instructions.
Firstly they
all
work on a block of data. DI and SI
are used to access memory.
SI and DI
are
called source index and
destination index because of
string instructions.
Whenever
an instruction needs a memory
source, DS:SI holds the
pointer to
it. An
override is possible that
can change the association
from DS but the
default
is DS. Whenever a string
instruction needs a memory
destination,
ES:DI
holds the pointer to it. No
override is possible in this
case. Whenever a
byte
register is needed, AL holds
the value. Whenever a word
register is used
AX
holds the value. For
example STOS stores a
register in memory so AL or
AX is
the register used and
ES:DI points to the
destination. The LODS
instruction
loads from memory to
register so the source is
pointed to by
DS:SI
and the register used is AL
or AX.
String
instructions work on a block of data. A
block has a start and
an
end.
The instructions can work
from the start towards
the end and from
the
end
towards the start. In fact
they can work in both
directions, and they
must be
allowed to work in both directions
otherwise certain operations
with
overlapping
blocks become impossible.
This problem is discussed in
detail
later.
The direction of movement is
controlled with the Direction
Flag (DF) in
the
flags register. If this flag
is cleared the direction is
from lower addresses
towards
higher addresses and if this
flag is set the direction is
from higher
addresses
to lower addresses. If DF is cleared,
this is called the
auto-
increment
mode of string instruction,
and if DF is set, this is
called the auto-
decrement
mode. There are two
instructions to set and
clear the direction
flag.
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
cld
; clear direction
flag
std
; set direction
flag
Every
string instruction has two
variants; a byte variant and
a word
variant.
For example the two variants
of STOS are STOSB and
STOSW.
Similarly
the variants for the
other string instructions
are attained by
appending
a B or a W to the instruction name.
The operation of each of
the
string
instructions and each of the
repetition prefixes is discussed
below.
STOS
STOS
transfers a byte or word
from register AL or AX to the
string element
addressed
by ES:DI and updates DI to
point to the next location.
STOS is
often
used to clear a block of
memory or fill it with a
constant.
The
implied source will always be in AL or
AX. If DF is clear, SI will be
incremented
by one or two depending of whether
STOSB or STOSW is
used.
If DF is
set SI will be decremented by one or two
depending of whether
STOSB
or STOSW is used. If REP is
used before this
instruction, the
process
will be
repeated CX times. CX is called
the counter register because
of the
special
treatment given to it in the
LOOP and JCXZ instructions
and the REP
set of
prefixes. So if REP is used with
STOS the whole block of
memory will
be
filled with a constant value.
REP will always decrement CX
like the LOOP
instruction
and this cannot be changed
with the direction flag. It is
also
independent
of whether the byte or the
word variant is used. It
always
decrements
by one; therefore CX has
count of repetitions and not
the count
of
bytes.
LODS
LODS
transfers a byte or word
from the source location
DS:SI to AL or AX
and
updates SI to point to the
next location. LODS is
generally used in a
loop
and
not with the REP prefix
since the value previously
loaded in the
register
is
overwritten if the instruction is
repeated and only the
last value of the
block
remains in the
register.
SCAS
SCAS
compares a source byte or
word in register AL or AX with
the
destination
string element addressed by
ES:DI and updates the
flags. DI is
updated
to point to the next
location. SCAS is often used
to locate equality or
in-equality
in a string through the use
of an appropriate prefix.
SCAS is
a bit different from the
other instructions. This is
more like the
CMP
instruction in that it does
subtraction of its operands.
The prefixes
REPE
(repeat while equal) and
REPNE (repeat while not
equal) are used with
this
instruction. The instruction is
used to locate a byte in AL in
the block of
memory.
When the first equality or
inequality is encountered; both
have
uses.
For example this instruction
can be used to search for a
0 in a null
terminated
string to calculate the
length of the string. In
this form REPNE
will be
used to repeat while the
null is not there.
MOVS
MOVS
transfers a byte or word
from the source location
DS:SI to the
destination
ES:DI and updates SI and DI
to point to the next
locations.
MOVS is
used to move a block of
memory. The DF is important in
the case of
overlapping
blocks. For example when the
source and destination
blocks
overlap
and the source is below
the destination copy must be
done upwards
while
if the destination is below
the source copy must be done
downwards.
We
cannot perform both these
copy operations properly if
the direction flag
was not
provided. If the source is
below the destination and an
upwards copy
is used
the source to be copied is
destroyed. If however the
copy is done
downwards
the portion of source
destroyed is the one that
has already been
84
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
copied.
Therefore we need the
control of the direction
flag to handle this
problem.
This problem is further
detailed in a later
example.
CMPS
CMPS
subtracts the source
location DS:SI from the
destination location
ES:DI.
Source and Destination are
unaffected. SI and DI are
updated
accordingly.
CMPS compares two blocks of
memory for equality or
inequality
of the
block. It subtracts byte by
byte or word by word. If
used with a REPE
or a
REPNE prefix is repeats as
long as the blocks are
same or as long as
they
are different. For example
it can be used for find a
substring. A
substring
is a string that is contained in
another string. For example
"has" is
contained
in "Mary has a little lamp."
Using CMPS we can do the
operation of
a
complex loop in a single
instruction. Only the REPE
and REPNE prefixes
are
meaningful with this
instruction.
REP
Prefix
REP
repeats the following string
instruction CX times. The
use of CX is
implied
with the REP prefix. The
decrement in CX doesn't affect
any flags and
the
jump is also independent of the
flags, just like
JCXZ.
REPE
and REPNE Prefixes
REPE or
REPZ repeat the following
string instruction while the
zero flag is
set
and REPNE or REPNZ repeat
the following instruction
while the zero
flag
is not
set. REPE or REPNE are
used with the SCAS or CMPS
instructions.
The
other string instructions
have nothing to do with the
condition since
they
are performing no comparison.
Also the initial state of
flags before the
string
instruction does not affect
the operation. The most
complex operation
of the
string instruction is with these
prefixes.
7.2.
STOS EXAMPLE CLEARING
THE SCREEN
We take
the example of clearing the
screen and observe that how
simple
and
fast this operation is with
the string instructions.
Even if there are
three
instructions
in a loop they have to be
fetched and decoded with
every
iteration
and the time of three
instructions is multiplied by the
number of
iterations
of the loop. In the case of
string instructions, many operations
are
short
circuited. The instruction is
fetched and decoded once
and only the
execution
is repeated CX times. That is why
string instructions are
so
efficient
in their operation. The
program to clear the screen
places 0720 on
the
2000 words on the
screen.
Example
7.1
001
; clear screen
using string instructions
002
[org
0x0100]
003
jmp
start
004
005
; subroutine to clear the
screen
006
clrscr:
push
es
007
push
ax
008
push
cx
009
push
di
010
011
mov
ax,
0xb800
012
mov
es,
ax
;
point es to video
base
013
xor
di,
di
;
point di to top left
column
014
mov
ax,
0x0720
;
space char in
normal attribute
015
mov
cx,
2000
;
number of
screen locations
016
017
cld
; auto increment
mode
018
rep
stosw
; clear the whole
screen
019
020
pop
di
85
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
021
pop
cx
022
pop
ax
023
pop
es
024
ret
025
026
start:
call clrscr
; call clrscr
subroutine
027
028
mov
ax,
0x4c00
; terminate
program
029
int
0x21
A space
efficient way to zero a 16bit
register is to XOR it with itself.
013
Remember
that exclusive or results in a
zero whenever the bits
at
the
source and at the
destination are same. This
instruction takes
just two
bytes compared to "mov di,
0" which would take three.
This
is a
standard way to zero a 16bit
register.
Inside
the debugger the operation
of the string instruction
can be
monitored.
The trace into command
can be used to monitor every
repetition
of the
string instruction. However
screen will not be cleared
inside the
debugger
as the debugger overwrites
its display on the screen so
CX
decrements
with every iteration, DI increments by 2.
The first access is
made
at
B800:0000 and the second at
B800:0002 and so on. A
complex and
inefficient
loop is replaced with a fast
and simple instruction that
does the
same
operation many times
faster.
7.3.
LODS EXAMPLE STRING
PRINTING
The
use of LODS with the REP
prefix is not meaningful as
only the last
value
loaded will remain in the
register. It is normally used in a
loop paired
with a
STOS instruction to do some
block processing. We use
LODS to pick
the
data, do the processing, and
then use STOS to put it back
or at some
other
place. For example in string
printing, we will use LODS to
read a
character
of the string, attach the
attribute byte to it, and
use STOS to write
it on
the video memory.
The
following example will print
the string using string
instructions.
Example
7.2
001
; hello world
printing using string instructions
002
[org
0x0100]
003
jmp
start
004
005
message:
db
'hello
world'
; string to be
printed
006
length:
dw
11
; length of
string
007
008-027
;;;;; COPY LINES
005-024 FROM EXAMPLE 7.1 (clrscr)
;;;;;
028
029
; subroutine to print a
string
030
; takes the x position, y
position, attribute, address of string
and
031
; its length as
parameters
032
printstr:
push
bp
033
mov bp,
sp
034
push
es
035
push
ax
036
push
cx
037
push
si
038
push
di
039
040
mov
ax,
0xb800
041
mov
es, ax
;
point es to video
base
042
mov
al, 80
;
load al with
columns per row
043
mul
byte
[bp+10]
;
multiply with y
position
044
add
ax, [bp+12]
;
add x
position
045
shl
ax, 1
;
turn into byte
offset
046
mov
di,ax
;
point di to required
location
047
mov
si, [bp+6]
;
point si to
string
048
mov
cx, [bp+4]
;
load length of string in
cx
049
mov
ah, [bp+8]
;
load attribute in
ah
86
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
050
051
cld
;
auto increment
mode
052
nextchar:
lodsb
;
load next char in
al
053
stosw
;
print char/attribute
pair
054
loop
nextchar
;
repeat for the
whole string
055
056
pop
di
057
pop
si
058
pop
cx
059
pop
ax
060
pop
es
061
pop
bp
062
ret
10
063
064
start:
call clrscr
; call the clrscr
subroutine
065
066
mov
ax, 30
067
push
ax
; push x
position
068
mov
ax, 20
069
push
ax
; push y
position
070
mov
ax, 1
; blue on black
attribute
071
push
ax
; push
attribute
072
mov
ax,
message
073
push
ax
; push
address of message
074
push
word
[length]
; push
message length
075
call
printstr
; call the printstr
subroutine
076
077
mov
ax,
0x4c00
; terminate
program
078
int
0x21
Both
operations are in auto
increment mode.
051
DS is
automatically initialized to our segment.
ES points to video
052-053
memory.
SI points to the address of our
string. DI points to
the
screen
location. AH holds the
attribute. Whenever we read
a
character
from the string in AL,
the attribute byte is
implicitly
attached
and the pair is present in
AX. The same effect could
not be
achieved
with a REP prefix as the REP
will repeat LODS and
then
start
repeating STOS, but we need to
alternate them.
CX
holds the length of the
string. Therefore LOOP
repeats for each
054
character
of the string.
Inside
the debugger we observe how
LODS and STOS alternate
and CX is
only
used by the LOOP
instruction. In the original
code there were
four
instructions
inside the loop; now there
are only two. This is how
string
instructions
help in reducing code
size.
7.4.
SCAS EXAMPLE STRING
LENGTH
Many
higher level languages do
not explicitly store string
length; rather
they
use a null character, a character with an
ASCII code of zero, to
signal
the
end of a string. In assembly
language programs, it is also
easier to store
a zero
at the end of the string,
instead of calculating the
length of string,
which is
very difficult process for
longer strings. So we delegate
length
calculation
to the processor and modify
our string printing subroutine
to
take a
null terminated string and no
length. We use SCASB with
REPNE and
a zero
in AL to find a zero byte in
the string. In CX we load
the maximum
possible
size, which is 64K bytes. However
actual strings will be much
smaller.
An important thing regarding
SCAS and CMPS is that if
they stop
due to
equality or inequality, the
index registers have already
incremented.
Therefore
when SCAS will stop DI would be
pointing past the null
character.
Example
7.3
001
; hello world
printing with a null terminated string
002
[org
0x0100]
87
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
003
jmp
start
004
005
message:
db
'hello world',
0
; null terminated
string
006
007-026
;;;;; COPY LINES
005-024 FROM EXAMPLE 7.1 (clrscr)
;;;;;
027
028
; subroutine to print a
string
029
; takes the x position, y
position, attribute, and address of a
null
030
; terminated string as
parameters
031
printstr:
push
bp
032
mov bp,
sp
033
push
es
034
push
ax
035
push
cx
036
push
si
037
push
di
038
039
push
ds
040
pop
es
;
load ds in
es
041
mov di,
[bp+4]
;
point di to
string
042
mov cx,
0xffff
;
load maximum
number in cx
043
xor al,
al
;
load a zero in
al
044
repne
scasb
;
find zero in the
string
045
mov ax,
0xffff
;
load maximum
number in ax
046
sub ax,
cx
;
find change in
cx
047
dec
ax
;
exclude null from
length
048
jz
exit
;
no printing if string is
empty
049
050
mov
cx, ax
; load string length in
cx
051
mov
ax,
0xb800
052
mov
es, ax
;
point es to video
base
053
mov
al, 80
;
load al with
columns per row
054
mul
byte [bp+8]
;
multiply with y
position
055
add
ax, [bp+10]
;
add x
position
056
shl
ax, 1
;
turn into byte
offset
057
mov
di,ax
;
point di to required
location
058
mov
si, [bp+4]
;
point si to
string
059
mov
ah, [bp+6]
;
load attribute in
ah
060
061
cld
;
auto increment
mode
062
nextchar:
lodsb
;
load next char in
al
063
stosw
;
print char/attribute
pair
064
loop
nextchar
;
repeat for the
whole string
065
066
exit:
pop
di
067
pop
si
068
pop
cx
069
pop
ax
070
pop
es
071
pop
bp
072
ret
8
073
074
start:
call clrscr
; call the clrscr
subroutine
075
076
mov
ax, 30
077
push
ax
; push x
position
078
mov
ax, 20
079
push
ax
; push y
position
080
mov
ax, 1
; blue on black
attribute
081
push
ax
; push
attribute
082
mov
ax,
message
083
push
ax
; push
address of message
084
call
printstr
; call the printstr
subroutine
085
086
mov
ax,
0x4c00
; terminate
program
int
0x21
Another
way to load a segment register is to
use a combination of
039-040
push
and pop. The processor
doesn't match pushes and
pops. ES is
equalized
to DS in this pair of
instructions.
Inside
the debugger observe the
working of the code for
length calculation
after
SCASB has completed its
operation.
88
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
LES
and LDS
Instructions
Since
the string instructions need
their source and destination
in the form
of a
segment offset pair, there
are two special instructions
that load a
segment
register and a general
purpose register from two
consecutive
memory
locations. LES loads ES
while LDS loads DS.
Both these
instructions
have
two parameters, one is the
general purpose register to be
loaded and
the
other is the memory location
from which to load these
registers. The
major
application of these instructions is when
a subroutine receives a
segment
offset pair as an argument
and the pair is to be loaded
in a segment
and an
offset register. According to
Intel rules of significance
the word at
higher
address is loaded in the
segment register while the
word at lower
address
is loaded in the offset
register. As parameters segment
should be
pushed
first so that it ends up at a
higher address and the
offset should be
pushed
afterwards. When loading the
lower address will be given.
For
example
"lds si, [bp+4]" will load
SI from BP+4 and DS from
BP+6.
7.5.
LES AND LDS
EXAMPLE
We
modify the string length
calculation subroutine to take
the segment
and
offset of the string and
use the LES instruction to
load that segment
offset
pair in ES and DI.
Example
7.4
001
; hello world
printing with length calculation subroutine
002
[org
0x0100]
003
jmp
start
004
005
message:
db
'hello world',
0
; null terminated
string
006
007-026
;;;;; COPY LINES
005-024 FROM EXAMPLE 7.1 (clrscr)
;;;;;
027
028
; subroutine to calculate the
length of a string
029
; takes the
segment and offset of a string as
parameters
030
strlen:
push
bp
031
mov
bp,sp
032
push
es
033
push
cx
034
push
di
035
036
les di,
[bp+4]
;
point es:di to
string
037
mov cx,
0xffff
;
load maximum
number in cx
038
xor al,
al
;
load a zero in
al
039
repne
scasb
;
find zero in the
string
040
mov ax,
0xffff
;
load maximum
number in ax
041
sub ax,
cx
;
find change in
cx
042
dec
ax
;
exclude null from
length
043
044
pop
di
045
pop
cx
046
pop
es
047
pop
bp
048
ret
4
049
050
; subroutine to print a
string
051
; takes the x position, y
position, attribute, and address of a
null
052
; terminated string as
parameters
053
printstr:
push
bp
054
mov bp,
sp
055
push
es
056
push
ax
057
push
cx
058
push
si
059
push
di
060
061
push
ds
; push
segment of string
062
mov
ax, [bp+4]
063
push
ax
; push offset of
string
064
call
strlen
; calculate string
length
89
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
065
cmp
ax, 0
; is the string
empty
066
jz
exit
; no printing if string is
empty
067
mov
cx, ax
; save length in
cx
068
069
mov
ax,
0xb800
070
mov
es, ax
;
point es to video
base
071
mov
al, 80
;
load al with
columns per row
072
mul
byte [bp+8]
;
multiply with y
position
073
add
ax, [bp+10]
;
add x
position
074
shl
ax, 1
;
turn into byte
offset
075
mov
di,ax
;
point di to required
location
076
mov
si, [bp+4]
;
point si to
string
077
mov
ah, [bp+6]
;
load attribute in
ah
078
079
cld
;
auto increment
mode
080
nextchar:
lodsb
;
load next char in
al
081
stosw
;
print char/attribute
pair
082
loop
nextchar
;
repeat for the
whole string
083
084
exit:
pop
di
085
pop
si
086
pop
cx
087
pop
ax
088
pop
es
089
pop
bp
090
ret
8
091
092
start:
call clrscr
; call the clrscr
subroutine
093
094
mov
ax, 30
095
push
ax
; push x
position
096
mov
ax, 20
097
push
ax
; push y
position
098
mov
ax,
0x71
; blue on white
attribute
099
push
ax
; push
attribute
100
mov
ax,
message
101
push
ax
; push
address of message
102
call
printstr
; call the printstr
subroutine
103
104
mov
ax,
0x4c00
; terminate
program
105
int
0x21
The
LES instruction is used to
load the DI register from
BP+4 and
036
the ES
register from BP+6.
The
convention to return a value
from a subroutine is to use
the AX
065
register.
That is why AX is not saved
and restored in the
subroutine.
Inside
the debugger observe that
the segment register is
pushed followed
by the
offset. The higher address
FFE6 contains the segment
and the lower
address
FFE4 contains the offset.
This is because we have a
decrementing
stack.
Then observe the loading of
ES and DI from the
stack.
7.6.
MOVS EXAMPLE SCREEN
SCROLLING
MOVS
has the two forms MOVSB
and MOVSW. REP allows
the instruction
to be
repeated CX times allowing
blocks of memory to be copied. We
will
perform
this copy of the video
screen.
Scrolling
is the process when all the
lines on the screen move
one or more
lines
towards the top of towards
the bottom and the new
line that appears on
the
top or the bottom is
cleared. Scrolling is a process on which
string
movement
is naturally applicable. REP with
MOVS will utilize the
full
processor
power to do the scrolling in minimum
time.
In this
example we want to scroll a variable
number of lines given
as
argument.
Therefore we have to calculate
the source address, which is
160
times
the number of lines to
clear. The destination
address is 0, which is the
top
left of the screen. The
lines that scroll up are
discarded so the
source
pointer
is placed after them. An
equal number of lines at the
bottom are
cleared.
These lines have actually
been copied above.
90
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
Example
7.5
001
; scroll up the
screen
002
[org
0x0100]
003
jmp
start
004
005
; subroutine to scroll up the
screen
006
; take the number
of lines to scroll as parameter
007
scrollup:
push
bp
008
mov
bp,sp
009
push
ax
010
push
cx
011
push
si
012
push
di
013
push
es
014
push
ds
015
016
mov
ax, 80
;
load chars per
row in ax
017
mul
byte [bp+4]
;
calculate source
position
018
mov
si, ax
;
load source
position in si
019
push
si
;
save position for
later use
020
shl
si, 1
;
convert to byte
offset
021
mov
cx,
2000
;
number of
screen locations
022
sub
cx, ax
;
count of words to
move
023
mov
ax,
0xb800
024
mov
es, ax
;
point es to video
base
025
mov
ds, ax
;
point ds to video
base
026
xor
di, di
;
point di to top left
column
027
cld
;
set auto increment
mode
028
rep
movsw
;
scroll up
029
mov
ax,
0x0720
;
space in normal
attribute
030
pop
cx
;
count of positions to
clear
031
rep
stosw
;
clear the scrolled
space
032
033
pop
ds
034
pop
es
035
pop
di
036
pop
si
037
pop
cx
038
pop
ax
039
pop
bp
040
ret
2
041
042
start:
mov
ax,5
043
push
ax
; push
number of lines to scroll
044
call
scrollup
; call the scroll up
subroutine
045
046
mov
ax,
0x4c00
; terminate
program
047
int
0x21
The
beauty of this example is
that the two memory blocks
are overlapping.
If the
source and destination in
the above algorithm are
swapped in an
expectation
to scroll down the result is
strange. For example if 5
lines were to
scroll
down, the top five
lines of the screen are
repeated on the whole
screen.
This is
where the use of the
direction flag comes
in.
When
the source is five lines
below the destination, the
first five lines
are
copied
on the first five lines of
the destination. However the
next five lines to
be
copied from the source
have been destroyed in the
process; because they
were
the same as the first
five lines of the
destination. The same is
the
problem
with every set of five lines
as the source is destroyed
during the
previous
copy. In this situation we must go
from bottom of the
screen
towards
the top. Now the last
five lines are copied to
the last five lines of
the
destination.
The next five lines
are copied to next five
lines of the
destination
destroying
the last five lines of
source; but now these lines
are no longer
needed
and have been previously
copied. Therefore the copy
will be
appropriately
done in this case.
We give
an example of scrolling down with this
consideration. Now we have
to
calculate the end of the
block instead of the
start.
91
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
Example
7.6
001
; scroll down the
screen
002
[org
0x0100]
003
jmp
start
004
005
; subroutine to scrolls
down the screen
006
; take the number
of lines to scroll as parameter
007
scrolldown:
push
bp
008
mov
bp,sp
009
push
ax
010
push
cx
011
push
si
012
push
di
013
push
es
014
push
ds
015
016
mov
ax, 80
;
load chars per
row in ax
017
mul
byte [bp+4]
;
calculate source
position
018
push
ax
;
save position for
later use
019
shl
ax, 1
;
convert to byte
offset
020
mov
si,
3998
;
last location on the
screen
021
sub
si, ax
;
load source
position in si
022
mov
cx,
2000
;
number of
screen locations
023
sub
cx, ax
;
count of words to
move
024
mov
ax,
0xb800
025
mov
es, ax
;
point es to video
base
026
mov
ds, ax
;
point ds to video
base
027
mov
di,
3998
;
point di to lower
right column
028
std
;
set auto decrement
mode
029
rep
movsw
;
scroll up
030
mov
ax,
0x0720
;
space in normal
attribute
031
pop
cx
;
count of positions to
clear
032
rep
stosw
;
clear the scrolled
space
033
034
pop
ds
035
pop
es
036
pop
di
037
pop
si
038
pop
cx
039
pop
ax
040
pop
bp
041
ret
2
042
043
start:
mov
ax,5
044
push
ax
; push
number of lines to scroll
045
call
scrolldown
; call scroll down
subroutine
046
047
mov
ax,
0x4c00
; terminate
program
048
int
0x21
7.7.
CMPS EXAMPLE STRING
COMPARISON
For
the last string instruction,
we take string comparison as an
example.
The
subroutine will take two segment
offset pairs containing the
address of
the two
null terminated strings. The
subroutine will return 0 if the
strings
are
different and 1 if they are
same. The AX register will be
used to hold the
return
value.
Example
7.7
001
; comparing null
terminated strings
002
[org
0x0100]
003
jmp
start
004
005
msg1:
db
'hello world',
0
006
msg2:
db
'hello WORLD',
0
007
msg3:
db
'hello world',
0
008
009-031
;;;;; COPY LINES
028-050 FROM EXAMPLE 7.4 (strlen)
;;;;;
032
033
; subroutine to
compare two strings
034
; takes segment
and offset pairs of two strings to
compare
92
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
035
; returns 1 in ax if they
match and 0 other
wise
036
strcmp:
push
bp
037
mov
bp,sp
038
push
cx
039
push
si
040
push
di
041
push
es
042
push
ds
043
044
lds
si, [bp+4]
; point ds:si to first
string
045
les
di, [bp+8]
; point es:di to
second string
046
047
push
ds
;
push
segment of first string
048
push
si
;
push offset of
first string
049
call
strlen
;
calculate string
length
050
mov
cx, ax
;
save length in
cx
051
052
push
es
;
push
segment of second string
053
push
di
;
push offset of
second string
054
call
strlen
;
calculate string
length
055
cmp
cx, ax
;
compare length of
both strings
056
jne
exitfalse
;
return 0 if they are
unequal
057
058
mov ax,
1
; store 1 in ax to be
returned
059
repe
cmpsb
; compare both
strings
060
jcxz
exitsimple
; are they successfully
compared
061
062
exitfalse:
mov
ax, 0
; store 0 to mark
unequal
063
064
exitsimple:
pop
ds
065
pop
es
066
pop
di
067
pop
si
068
pop
cx
069
pop
bp
070
ret
8
071
072
start:
push
ds
; push
segment of first string
073
mov
ax,
msg1
074
push
ax
; push offset of
first string
075
push
ds
; push
segment of second string
076
mov
ax,
msg2
077
push
ax
; push offset of
second string
078
call
strcmp
; call strcmp
subroutine
079
080
push
ds
; push
segment of first string
081
mov
ax,
msg1
082
push
ax
; push offset of
first string
083
push
ds
; push
segment of third string
084
mov
ax,
msg3
085
push
ax
; push offset of
third string
086
call
strcmp
; call strcmp
subroutine
087
088
mov
ax,
0x4c00
; terminate
program
089
int
0x21
Three
strings are declared out of which two
are equal and one
is
005-007
different.
LDS
and LES are used to
load the pointers to the two
strings in
044-045
DS:SI
and ES:DI.
Since
there are 4 parameters to
the subroutine "ret 8" is
used.
070
Inside
the debugger we observe that
REPE is shown as REP. This
is
because
REP and REPE are
represented with the same
prefix byte. When
used
with STOS, LODS, and MOVS it
functions as REP and when
used with
SCAS
and CMPS it functions as
REPE.
EXERCISES
1.
Write code to find the
byte in AL in the whole
megabyte of memory
such
that each memory location is
compared to AL only
once.
93
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
2.
Write a far procedure to
reverse an array of 64k words
such that the
first
element becomes the last
and the last becomes
the first and so
on.
For example if the first
word contained 0102h, this
value is
swapped
with the last word. The
next word is swapped with
the
second
last word and so on.
The routine will be passed
two
parameters
through the stack; the
segment and offset of the
first
element
of the array.
3.
Write a near procedure to
copy a given area on the
screen at the
center
of the screen without using
a temporary array. The
routine will
be
passed top, left, bottom,
and right in that order
through the stack.
The
parameters passed will always be within
range the height will
be
odd
and the width will be even so
that it can be exactly
centered.
4.
Write code to find two
segments in the whole memory
that are exactly
the
same. In other words find
two distinct values which if loaded
in
ES and
DS then for every value of
SI [DS:SI]=[ES:SI].
5.
Write a function writechar
that takes two parameters.
The first
parameter
is the character to write
and the second is the
address of a
memory
area containing top, left,
bottom, right, current row,
current
column,
normal attribute, and cursor
attribute in 8 consecutive
bytes.
These define a virtual window on
the screen.
The
function writes the passed
character at (current row,
current
column)
using the normal attribute.
It then increments
current
column,
If current column goes
outside the window, it makes
it zero
and
increments current row. If
current row gets out of window,
it
scrolls
the window one line up, and
blanks out the new line in
the
window.
In the end, it sets the
attribute of the new (current
row,
current
column) to cursor
attribute.
6.
Write a function "strcpy"
that takes the address of
two parameters via
stack,
the one pushed first is
source and the second is
the
destination.
The function should copy
the source on the
destination
including
the null character assuming
that sufficient space
is
reserved
starting at destination.
94
Table of Contents:
|
|||||