A character string is a special kind of array, i.e. an array of characters.
In general, an array of size N looks like the following:
int arry[25];
.data table SBYTE 5 dup(0)
int i,arry[5]; for(i = 0;i <= 4;i++) arry[i]=i;
P#4: Write an assembly language subprocedure Large that returns the largest value in the array nums (a signed array). The number of elements in the array can be found in the first element of the array. Assume the array was defined as:
nums SWORD 25 dup(?)
(1) Source elements are DS:SI
(2) Destination elements are ES:DI
(3) At the end of the string instruction, the DI and SI are automatically updated by 1 (byte) or 2 (word).
(4) The DF flag is used to determine increment or decrement. If DF=0 then increment; otherwise, decrement.
(5) In Protected Mode, ESI is an offset from DS and EDI is an offset from ES and ES & DS are set to point to the same segment. In Real Mode, ES and DS do not necessarily point to the same location.
(i62) [<label>] CLD
(i63) [<label>] STD
The MOVSB instruction causes the microprocessor to replace the byte at ES:DI by the byte at DS:SI and update DI and SI to point to the next byte in the strings pointed to by DI and SI. The general form is:
(i64) [<label>] MOVSB
A similar instruction exists for moving words as follows:
(i65) [<label>] MOVSW
The two load instructions cause AL and AX-registers to be loaded with a copy of the byte and word addressed by the DS:SI. Notice that these two instructions work with the SI, i.e. we are loading from a source. Also, the SI register is automatically updated as with all string instructions so I will quit mentioning this from now on.
(i66) [<label>] LODSB ; al <- ds:si
(i67) [<label>] LODSW ; ax <- ds:si
The two store instructions cause AL and AX-registers to be stored in the byte and word addressed by the ES:DI. Notice that these two instructions work with the DI, i.e. we are storing to a destination.
(i68) [<label>] STOSB ; al -> es:di
(i69) [<label>] STOSW ; ax -> es:di
Compare and scan string instructions are as follows:
(i70) [<label>] CMPSB ; ds:si - es:di
(i71) [<label>] CMPSW ; ds:si - es:di
(i72) [<label>] SCASB ; al - es:di
(i73) [<label>] SCASW ; ax - es:di
If you are reading the book you will notice that there are generic forms of these string instructions and I don't even want to discuss this. If you would like to read up on these and use them at any point, feel free. You will not be tested on these instructions.
P#5: Assume two strings st1 and st2 are defined as follows:
st1 BYTE 25 dup(?) st2 BYTE 25 dup(?)
Write a program segment that will place a copy of st1 into st2. The size of each string in the first element of the array.
We can use repeat instructions to aid in the counting process. The repeat prefixes for string instructions are as follows:
(1) REP
(2) REPE/REPZ
(3) REPNE/REPNZ
(i74) [<label>] REP <string-op> where <string-op> is the opcode of one of the string instructions just discussed. In all cases, the CX-register is used as a counter and is decremented after execution of the string instruction.
The pseudo-code for the REP is as follows:
repeat Execute the string instruction & update di/si as before Decrement CX by 1 until (CX==0)
P#6: Repeat P#1 using the REP instruction.
(i75) [<label>] REPE <string-op>
[<label>] REPZ <string-op>
Translates into the following pseudo-code:
repeat Execute the string instruction & update di/si as before Decrement CX by 1 until (CX==0) || (ZF==0)
Again, this can be thought of as repeat while equal.
(i76) [<label>] REPNE <string-op>
[<label>] REPNZ <string-op>
Translates into the following pseudo-code:
repeat Execute the string instruction & update di/si as before Decrement CX by 1 until (CX==0) || (ZF==1)
Again, this can be thought of as repeat while not equal.
P#7: Declare a word array of size 100. Accept a search value from the keyboard and return its' index value. If the value is not found, then return -1. Return the value in the AX-register.
(1) Register
(2) Direct
(3) Immediate
Let's introduce a few more:
(4) Register Indirect Addressing - the effective address is the 16-bit contents of the BX, DI, or SI register.
Consider the following:
name BYTE 8,'JOHN DOE'
Internally, this looks like the following:
Offset MEM 0 08 1 4A 2 4F 3 48 4 4E 5 20 6 44 7 4F 8 45
P#8: Show two different ways of moving the size of the array into the CL-registe r.
Solution1 Solution2 mov cl,name lea di,name mov cl,[di]
Q#1: What addressing modes are being used in Solutions 1 & 2?
Note: When the BX, DI, or SI registers are used as an indirect address, the DS contents are assumed to specify the segment portion of the address unless a segment override is given as follows:
mov cx,es:[di]
(5) Indexed Addressing - the effective address of the memory operand is the sum of the displacement and the 16-bit contents of an index register (DI or SI).
Example:
mov di,1 mov al,name[di]
Note1: The offset of name within the data segment is the displacement in the mac hine language representation.
Note2: Effective Address (EA) = sum of displacement + DI
(6) Base addressing implies: EA = sum of displacement + (BP or BX) register.
Consider the following: Argument to a subprocedure are passed via the stack as follows:
push <arg1> push <arg2> call subproc
The stack is as follows:
Return Offset <- SS:Sp Return Segment <arg2> <arg1>
If the first two instructions of the subprocedure were:
push bp mov bp,sp
The stack would look like:
ss:bp -> bp <- ss:sp Offset Segment <arg2> <arg1>
Note: The ss:bp register pair is not modified by further push and pop operations . The bp simply provided a reference point in the stack to access certain values .
P#9: Move a copy of <arg2> into the DX-register.