ZeePedia

String Instructions: String Processing, Clearing Screen, String Printing, Length

<< Display Memory: ASCII Codes, Display Memory Formation, Assembly Language
Software Interrupts: Hooking an Interrupt, BIOS and DOS Interrupts >>
img
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.
img
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
img
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
img
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
img
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
img
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
img
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
img
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
img
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
img
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
img
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
img
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