Chapter 6 Integer Manipulation and Iteration Instructions
This chapter discusses some integer manipulation and iteration instructions available on the Intel 8086 processor. Integer manipulation instructions are provided to perform the transfer of signed and unsigned integers from one location inside the computer to another, to perform the conversion of signed integers between 8 and 16-bit representations, and to perform arithmetic operations on signed and unsigned integers. Iteration instructions are used to repeat the execution of one or more instructions a certain number of times. These instructions are discussed by first providing their general syntax in which an operand is labeled source, destination, or ShortOffset. A source operand is an immediate data, a register, or a memory location whose contents are not affected by the execution of the instruction. A destination operand is a register or a memory location whose contents are affected by the execution of the instruction.
© 2015 Gilbert Ndjatou
135
136 A ShortOffset operand is the offset of an instruction such that the corresponding relative address can be specified as a byte. When both operands of an instruction are affected by its execution, they are labeled destination1 for the first and destination2 for the second. It is important to note that the previous contents of a destination operand are lost after the execution of an instruction. Information about the settings of the flags register by each of these instruction is also provided. Additional information about an instruction such as the format of its operands, its opcode, and if a ‘mod r/m byte’ is used in its machine language translation are provided in Appendix 2. As new instructions are presented, we use C language like assignment statement and arithmetic operators to describe the operation(s) that they perform on operand(s).
6.1
Data-Transfer Instructions
Data-transfer instructions are instructions that copy a signed or an unsigned integer into a register or a memory location. In this chapter, we discuss the MOV (move) and the XCHG (exchange) instructions.
MOV Instructions The MOV (move) instructions copy an immediate data into a memory location or a register. They also copy the contents of a register or a memory location into another register, or the contents of a register into a memory location. They are defined as follows:
syntax:
MOV destination , source
Operation:
destination = source
Flags status:
unchanged
Both operands of MOV instructions can either be a byte or a word. However, they must have the same size. Furthermore, the destination operand can only be a register or a memory location. Example 6.1 illustrates the execution of these instructions.
© 2015 Gilbert Ndjatou
137 There is no MOV instructions to perform each of the following operations: C
copy data into the code segment register CS
C
copy data into the instruction pointer register IP
C
copy a segment register into another segment register
C
copy an immediate data into a segment register
C
copy a memory location into another memory location.
Example 6.1
Execution of the MOV instructions
In these examples, it is assumed that the initial data are moved into the registers or the memory locations before the execution of the instructions. a) MOV BX , 5 Register BX Before execution:
F1F2
After execution:
0005
b) MOV WORD PTR [DS:200h] , 5 Memory locations Offset:
0200
0201
Before execution:
F1
F2
After execution:
05
00
c) MOV BYTE PTR [DS:200h] , 5 Memory locations Offset:
0200
Before execution:
F1
After execution:
05
d) MOV CX , AX Registers
© 2015 Gilbert Ndjatou
CX
AX
Before execution:
F1F2
000A
After execution:
000A
000A
138 e)
MOV [DS:200h] , BX Memory locations
Register
0200
0201
BX
Before execution:
F1
F2
000A
After execution:
0A
00
000A
Offset:
f) MOV AH , [DS:200h] Memory locations Register Offset:
0200
AH
Before execution:
0B
F1
After execution:
0B
0B
To copy an immediate data into a segment register (DS, ES, or SS), one may do the following: 1. first copy the immediate data into a 16-bit register or a word memory location 2. then copy the contents of that register or memory location to the segment register. For example, to copy 2A5Ch into the segment register DS, we may use the following two instructions: MOV AX, 2A5Ch MOV DS, AX
Similarly, you copy the contents of a memory location into another memory location by first copying it into a register.
XCHG Instructions The XCHG (exchange) instructions exchange the contents of two registers, or the contents of a register and a memory location. They are defined as follows:
© 2015 Gilbert Ndjatou
139 syntax:
XCHG destination1, destination2
operation:
destination1
= destination2
destination2
= destination1
and
Flags status: unchanged The operands of the XCHG instructions are either byte or word registers or memory locations. However, both operands must have the same size and at least one of the two operands must be a register. Example 6.2 illustrates the execution of these instructions. The contents of two memory locations may be interchanged by using a register and three XCHG instructions as in the following example in which the word at offset 0200h is interchanged with the word at offset 0210h. XCHG AX , [DS:200h] XCHG AX , [DS:210h] XCHG AX , [DS:200h]
Example 6.2
Execution of the XCHG Instructions
In these examples, it is assumed that the initial data are moved into the registers or the memory locations before the execution of the instructions. a) XCHG BX , CX Registers BX
CX
Before execution:
F1F2
A0B0
After execution:
A0B0
F1F2
b) XCHG [DS:200h] , BX Memory locations Register Offset:
© 2015 Gilbert Ndjatou
0200
0201
BX
Before execution:
F1
F2
000A
After execution:
0A
00
F2F1
140 c) XCHG BL , AL Registers BL
AL
Before execution:
F1
A0
After execution:
A0
F1
d) XCHG AH , [DS:200h] Memory locations Register Offset:
0200
AH
Before execution:
0B
F1
After execution:
F1
0B
Exercise 6.1 1. Assume that before the execution of each of the following instructions, the contents of the registers AX, BX, and CX, and the memory locations at offsets 0120 and 0121 in the data segmentare given as follows: AX:
0001
Offset:
BX:
0002
Contents:
CX:
0003
0120 0A
0121 0B
Show the contents of the register or memory location operands of each of the following instructions after its execution: a. MOV AX, -2
d. MOV CX, BX
g. MOV AX, [DS:120]
b. MOV AL, -3
e. MOV AH, CL
h. MOV WORD PTR [DS:120], 13
c. MOV [DS:120], BX
f.
MOV [DS:120], BL
i.
MOV BYTE PTR [DS:120], -4
2. Write one or more MOV instructions to accomplish each of the following operations: a. Copy 10 into register BX. b. Copy 7 into the word in the data segment starting at offset 015Ah. c. Copy 15A3h into register DS. d. Copy 9 into the byte in memory at offset 015Ah. e. Copy the contents of register CX into the word in memory starting at offset 014Bh. f.
Copy the byte in memory at offset 014Ch to the memory at offset 013Eh.
© 2015 Gilbert Ndjatou
141 3. Write one or more XCHG instructions to exchange the contents of the word memory location at offset 013Ah and the word memory location at offset 012Bh.
6.2
Conversion Instructions
The Intel 8086 processor has an instruction, the CBW (convert byte to word) instruction, to convert an 8-bit signed integer to 16 bits and another one, the CWD (convert word to double word) instruction to convert a 16-bit signed integer to 32 bits. The CBW instruction converts the 8-bit signed integer in register AL to 16 bits by extending its sign bit to register AH; and the CWD instruction converts the 16-bit signed integer in register AX to 32 bit by extending its sign bit to register DX.
CBW Instruction The CBW instruction extends the sign bit of the 8-bit signed integer in register AL into register AH. It is defined as follows: Syntax:
CBW
Operation:
AH = FFh (if contents of AL is negative); 00h (otherwise).
Flag status:
unchanged
CWD Instruction The CWD instruction extends the sign bit of the 16-bit signed integer in register AX into register DX. It is defined as follows: Syntax:
CWD
Operation:
DX = FFFFh (if contents of AX is negative); 0000h (otherwise).
Flag status: © 2015 Gilbert Ndjatou
unchanged
142 There are no instructions to convert a 32-bit signd integer to 16 bits or a 16-bit signed integers to 8 bits. However, this could be done by just dropping the high order bits of the integer. To verify that the conversion is correct, one can verify that the bits dropped are the sign bit of the result of the conversion. Example 6.3 illustrates the execution of these instructions.
Example 6.3
Execution of the CBW and CWD instructions
In these examples, it is assumed that the initial data are moved into the registers or the memory locations before the execution of each instruction. a) CBW Registers AX Before execution:
1A5F
After execution:
005F
b) CBW Registers AX Before execution:
1A9A
After execution:
FF9A
c) CWD Registers DX
AX
Before execution:
A0B0
5A2F
After execution:
0000
5A2F
d) CWD Registers
© 2015 Gilbert Ndjatou
DX
AX
Before execution:
A0B0
A123
After execution:
FFFF
A123
143
6.3 Arithmetic Instructions The Intel 8086 processor has instructions to add, subtract, multiply, and divide signed and unsigned integers. The instructions discussed in this chapter are the ADD (addition of sign and unsigned integers) instructions, the SUB (subtraction of signed and unsigned integers) instructions, the IMUL (multiplication of signed integers) instructions, the MUL (multiplication of unsigned integers) instructions, the IDIV (division of signed integers) instructions, and the DIV (division of unsigned integers) instructions. We also discuss the INC (increment a signed or unsigned integer) instructions, the DEC (decrement a signed or unsigned integer) instructions, and the NEG (negation: take the two’s complement of a signed integer) instructions.
ADD Instructions The ADD instructions add the second (source) operand to the first (destination) operand and the result is assigned to the destination operand. Both operands are either signed or unsigned integers. The instructions are defined as follows:
Syntax:
ADD destination , source
Operation:
destination = destination + source
Flags status: ZF, SF, OF, CF, AF, and PF may be modified. The operands are either 8-bit or 16-bit integers. However, register and memory operands must have the same size. When the source operand is an immediate data, it is represented as a byte if it is in the range, - 128 to 127; otherwise, it is represented as a 16-bit integer value. Example 6.4 illustrates the execution of these instructions.
© 2015 Gilbert Ndjatou
144 Example 6.4
Execution of the ADD Instructions
In these examples, it is assumed that the initial data are moved into the registers or the memory locations before the execution of the instructions. a) ADD BX , 5 Register BX Before execution:
0004
After execution:
0009
b) ADD WORD PTR [DS:200h] , 5 Memory locations Offset:
0200
0201
Before execution:
04
00
After execution:
09
00
c) ADD BYTE PTR [DS:200h] , 5 Memory locations Offset:
0200
Before execution:
04
After execution:
09
d) ADD CX , AX Registers
e) ADD
CX
AX
Before execution:
0004
000B
After execution:
000F
000B
[DS:200h] , BX Memory locations Register Offset:
f) ADD
0200
0201
BX
Before execution:
04
00
000B
After execution:
0F
00
000B
AH , [DS:200h] Memory locations Register Offset:
© 2015 Gilbert Ndjatou
0200
AH
Before execution:
0B
04
After execution:
0B
0F
145 SUB Instructions The SUB instructions subtract the second (source) operand from the first (destination) operand and the difference is assigned to the destination operand. Both operands are either signed or unsigned integers. The instructions are defined as follows:
Syntax:
SUB destination , source
Operation:
destination = destination - source
Flags status: ZF, SF, OF, CF, AF, and PF may be modified. As with the ADD instructions, the operands are either 8-bit or 16-bit integers. However, register and memory operands must have the same size. When the source operand is an immediate data, it is represented as a byte if it is in the range - 128 to 127); otherwise, it is represented as a 16-bit integer. Example 6.5 illustrates the execution of these instructions.
Example 6.5
Execution of SUB Instructions
In these examples, it is assumed that the initial data are moved into the registers or the memory locations before the execution of each instruction. a) SUB BX , 5 Register BX Before execution:
0009
After execution:
0004
b) SUB WORD PTR [DS:200h] , 5 Memory locations Offset:
© 2015 Gilbert Ndjatou
0200
0201
Before execution:
09
00
After execution:
04
00
146 c) SUB BYTE PTR [DS:200h] , 5 Memory locations Offset:
0200
Before execution:
09
After execution:
04
d) SUB CX , AX Registers
e) SUB
CX
AX
Before execution:
000B
0004
After execution:
0007
0004
[DS:200h] , BX Memory locations Offset:
f) SUB
Register
0200
0201
BX
Before execution:
0B
00
0004
After execution:
07
00
0004
AH , [DS:200h] Memory locations Offset:
Register
0200
AH
Before execution:
04
0B
After execution:
04
07
Figure 6.1 illustrates a Debug program that uses MOV, ADD and SUB instructions.
Figure 6.1
A Sample Debug Program (using MOV, ADD and SUB instructions)
The following sequence of assembly language instructions computes the arithmetic expression: 6 - 10 + (-15) + 20 - (-7), and stores the result in register DX.
© 2015 Gilbert Ndjatou
147 Instructions
Remarks
MOV AX, 6
; AX = 6
SUB AX, 0A
; AX = 6 - 10
ADD AX, -0F
; AX = 6 - 10 + (-15)
ADD AX, 14
; AX = 6 - 10 + (-15) + 20
SUB AX, -7
; AX = 6 - 10 + (-15) + 20 - (-7)
MOV DX, AX
; DX = AX
INT 20
Exercise 6.2 1. Write the arithmetic expression to be evaluated by the execution of the following sequence of instructions: MOV AX, 9 MOV BX, 6 ADD
AX, 3
SUB
BX, 4
SUB
AX, BX
2. Trace the execution of the above sequence of statements and show the contents of the registers AX and BX. 3. Write a sequence of assembly language instructions to evaluate each of the following arithmetic expressions: a. 8 + 25 - 11 + (-5) - 7 + 2
b. 12 - 5 + 9 - ( 4 + 11 - 9) + 2
Signed and Unsigned Multiplications The Intel 8086 processor has signed and unsigned multiplication instructions for the multiplication of 8-bit values or 16-bit values. 8-bit multiplication instructions expect the first operand to be in register AL and the second to be in an 8-bit register or a memory location. 16-bit multiplication instructions expect the first operand to be in register AX, and the second operand to be in a 16-bit register or a memory location.
© 2015 Gilbert Ndjatou
148 The result of an 8-bit multiplication instruction is a 16-bit value that is stored in register AX. The overflow and the carry flags are set if the product is larger than a byte. The result of a 16-bit multiplication instruction is a 32-bit value that is stored in the register pair (DX, AX): The high order bytes are stored in register DX, and the low order bytes in register AX. The overflow and the carry flags are set if the result is larger than a word. The difference between signed and unsigned multiplications is that signed multiplication instructions extend the sign bit of the result through the leading bits, while the unsigned instructions set the leading bits to 0. The first operand of a multiplication instruction (register AL for 8-bit multiplications and register AX for 16-bit multiplications) is implicit: only the second operand is specified in the instruction. These instructions are specified as follows:
IMUL (signed multiplication) Instructions Syntax:
IMUL source-16
or IMUL source-8
Operation:
(DX, AX) = AX * source-16
|
AX = AL * source-8
Flags status: OF and CF may be modified. source-16 is a 16-bit register or memory location and source-8 is an 8-bit register or memory location.
MUL (unsigned multiplication) Instructions Syntax:
MUL source-16
Operation:
same as for IMUL instructions
or MUL source-8
Flags status: OF and CF may be modified. Example 6.6 illustrates the execution of IMUL (signed multiplication) instructions and Example 6.7 illustrates the execution of MUL (unsigned multiplication) instructions. © 2015 Gilbert Ndjatou
149
Example 6.6
Execution of IMUL (signed multiplication) Instructions
In these examples, it is assumed that the initial data are moved into the registers or the memory locations before the execution of each instruction. a) IMUL BX
; 0005 * 0002 (decimal 5 * 2) Registers DX
b) IMUL CX
AX
BX
Before execution:
A1B2 0005
0002
After execution:
0000
0002
000A
Result =
0000 000A
Result =
FFFF FFF6
Result =
000A
; 0005 * FFFE (decimal 5 * -2) Registers DX
c) IMUL BL
AX
CX
Before execution:
A1B2 0005
FFFE
After execution:
FFFF
FFFE
FFF6
; 05 * 02 (decimal 5 * 2) Registers
d) IMUL CL
AX
BX
Before execution:
1B05
2C02
After execution:
000A
2C02
; 05 * FE (decimal 5 * -2) Registers
© 2015 Gilbert Ndjatou
AX
CX
Before execution:
1B05
2CFE
After execution:
FFF6
2CFE
Result:
FFF6
150 e) IMUL WORD PTR [DS:200h]
; 0005 * 0002
Memory locations Registers Offset:
0200
0201
DX
Before execution:
02
00
A1B2 0005
After execution:
02
00
0000
f)
AX
IMUL BYTE PTR [DS:200h]
000A
Result:
0000 000A
; 05 * FE
Memory locations Registers Offset:
0200
AX
Before execution:
FE
1B05
After execution:
FE
FFF6
Example 6.7
Result:
FFF6
Execution of MUL (unsigned multiplication) Instructions
In these examples, it is assumed that the initial data are moved into the registers or the memory locations before the execution of each instruction. a) MUL BX
; 0005 * 0002 (decimal 5 * 2) Registers DX
AX
BX
Before execution:
A1B2 0005
0002
After execution:
0000
0002
b) MUL CX
000A
Result =
0000 000A
Result =
0004 FFF6
; 0005 * FFFE (decimal 5 * 65534) Registers DX
AX
CX
Before execution:
A1B2 0005
FFFE
After execution:
0004
FFFE
© 2015 Gilbert Ndjatou
FFF6
151 c) MUL BL
; 05 * 02 (decimal 5 * 2) Registers AX
BX
Before execution:
1B05
2C02
After execution:
000A
2C02
d) MUL CL
Result =
000A
Result =
04F6
; 05 * FE (decimal 5 * 254) Registers AX
CX
Before execution:
1B05
2CFE
After execution:
04F6
2CFE
Figure 6.2 illustrates a Debug program that uses IMUL (signed multiplication), MOV, ADD and SUB instructions.
Figure 6.2
A sample Debug program that uses MOV, ADD, SUB, and IMUL instructions
The following sequence of assembly language instructions computes the arithmetic expression: 6 - 10 * (-15) + 20, and stores the result in register CX.
© 2015 Gilbert Ndjatou
Instructions
Remarks
MOV
CX, 6
; CX = 6
MOV
AX, 0A
; AX = 10
MOV
BX, -0F
IMUL
BX
; (DX, AX) = 10 * (-15)
SUB
CX, AX
; CX = 6 - 10 * (-15)
ADD
CX, 14
; CX = 6 - 10 * (-15) + 20
INT
20
152 Exercise 6.3 1. Write a sequence of assembly language instructions to compute each of the following arithmetic expressions: a. 5 + 7 * 9
b. 6 * 7 - 8
2. Write the arithmetic expression to be evaluated by the execution of the following sequence of instructions: MOV AX, 9 MOV BX, 6 IMUL BX ADD
BX, 2
SUB
AX, BX
3. Trace the execution of the above sequence of instructions and show the contents of the registers AX and BX. 4. Write a sequence of assembly language instructions to evaluate each of the following arithmetic expressions: a. 8 + 11 * (-5) + 25 - 7 * 2
b. 12 * 5 + 9 * ( 4 + 11 - 9) + 2
Signed and Unsigned Divisions The Intel 8086 processor has signed and unsigned division instructions to divide 32-bit values by 16-bit values, and 16-bit values by 8-bit values. Instructions to divide16-bit values by 8-bit values expect the dividend to be in register AX and the divisor to be in an 8-bit register or memory location; and instructions to divide 32-bit values by 16-bit values expect the dividend to be in the register pair (DX, AX), and the divisor to be in a 16-bit register or memory location. Division instructions produce a quotient and a remainder: the quotient of a 16-bit by 8-bit division instructions is stored in register AL, and the remainder in register AH; for 32-bit by 16-bit division instructions, the quotient is stored in register AX, and the remainder in register DX. © 2015 Gilbert Ndjatou
153 As with multiplication instructions, the first operand, (register AX for the 16-bit by 8-bit division, and the register pair (DX, AX) for the 32-bit by 16bit division) is implicit: only the second operand is specified in the instruction. These instructions are specified as follows:
IDIV (signed division) Instructions Syntax:
IDIV source-16
or
IDIV source-8 Operation: AX = quotient, DX = remainder of (DX, AX) ÷ source-16 AL = quotient, AH = remainder of AX ÷ source-8 Flags status: OF, SF, ZF, AF, PF and CF are undefined. DF, IF, and TF are unchanged source-16 is a 16-bit register or memory location, and source-8 is an 8-bit register or memory location.
DIV (unsigned division) Instructions Syntax:
IDIV source-16
or
IDIV source-8 Operation:
same as for IDIV instructions
Flags status: same as for IDIV instructions.
Example 6.8 illustrates the execution of IDIV (signed division) instructions and Example 6.9 illustrates the executions of DIV (unsigned division) instructions.
© 2015 Gilbert Ndjatou
154
Example 6.8
Execution of IDIV (signed division) instructions
In these examples, it is assumed that the initial data are moved into the registers or the memory locations before the execution of the instructions. a) IDIV BX
; 0000 000B ÷ 0004 (decimal 11 ÷ 4) Registers DX
AX
BX
Before execution:
0000
000B
0004
After execution:
0003
0002
0004
Remainder: b) IDIV CX
0003 (decimal 3) Quotient:
0002
(Decimal 2)
; FFFF FFF5 ÷ 0004 (decimal -11 ÷ 4) Registers DX
AX
CX
Before execution:
FFFF
FFF5
0004
After execution:
FFFD FFFE 0004
Remainder:
FFFD (decimal -3)
Quotient: FFFE (Decimal - 2)
c) IDIV BX ; 0000 000B ÷ FFFC (decimal 11 ÷ -4) Registers DX
AX
BX
Before execution:
0000
000B
FFFC
After execution:
0003
FFFE FFFC
Remainder:
0003 (decimal 3) Quotient: FFFE
(Decimal - 2)
d) IDIV BL ; 000B ÷ 04 (decimal 11 ÷ 4) Registers AX
BX
Before execution:
000B
2C04
After execution:
0302
2C04
Remainder:
© 2015 Gilbert Ndjatou
03 (decimal 3)
Quotient: 02
(Decimal 2)
155 e) IDIV WORD PTR [DS:200h]
; 0000 000B ÷ 0004 (decimal 11 ÷ 4)
Memory locations Offset:
Registers
0200
0201
DX
AX
Before execution:
04
00
0000
000B
After execution:
04
00
0003
0002
Remainder:
0003 (decimal 3) Quotient: 0002
f) IDIV BYTE PTR [DS:200h]
Example 6.9
Registers
0200
AX
Before execution:
04
000B
After execution:
04
0302
Remainder:
2)
; 000B ÷ 04 (decimal 11 ÷ 4)
Memory locations Offset:
(Decimal
03 (decimal 3)
Quotient: 02
(Decimal 2)
Executions of DIV (unsigned division) instructions
In these examples, it is assumed that the initial data are moved into the registers or the memory locations before the execution of the instructions. a) DIV BX
; 0000 000B ÷ 0004 (decimal 11 ÷ 4) Registers DX
AX
BX
Before execution:
0000
000B
0004
After execution:
0003
0002
0004
Remainder:
© 2015 Gilbert Ndjatou
0003 (decimal 3) Quotient:
0002
(Decimal 2)
156 b) DIV CX
; 0000 FFF5 ÷ 0004 (decimal 65525 ÷ 4) Registers DX
AX
CX
Before execution:
0000
FFF5
0004
After execution:
0001
3FFD 0004
Remainder:
0001 (decimal 1) Quotient: 3FFD (Decimal 16381)
Note that when both the dividend and the divisor are positive, the IDIV (signed division) and DIV (unsigned division) instructions produce the same results. When the quotient is outside of the range of values that can be represented by the destination operand, an interrupt is generated. The handler for this interrupt usually terminates the program with an error message. An attempt to divide by 0 also generates this interrupt.
Signs of the Quotient and the Remainder In Arithmetic, the remainder of a division is always positive or zero, and is less than the divisor. However, as you may have noticed in Example 6.8 a) and b), the remainder of a signed division instruction may be a negative integer. In general, non-zero remainders have the same sign as the dividend. That means, a non-zero remainder is positive if the dividend is positive, and negative otherwise. You may also observe in Example 6.8 that the quotient is negative if the dividend and the divisor have opposite signs and positive if both the dividend and the divisor have the same sign. It is zero if the dividend is zero.
Preparing the Dividend of a 32-bit Division In order to specify a 32-bit by 16-bit division, an extra step must be taken to prepare the dividend because it extends over two registers. © 2015 Gilbert Ndjatou
157 For an unsigned division, if the dividend is a 16-bit value, zero must be moved into register DX. The dividend may then be prepared as follows: C
move the dividend into register AX
C
Move zero into register DX
For a signed division, if the dividend is a 16-bit value, its sign must be extended into register DX. This may be accomplished as follows: C
move the dividend into register AX
C
use the CWD instruction to extend its sign bit to register DX.
Example 6.10 provides the sequence of instructions to perform a 32-bit unsigned division and Example 6.11 provides the sequence of instructions to perform a 32-bit signed division.
Example 6.10
Instructions to perform unsigned divisions.
Write a Debug program to compute 35/ 4 using an unsigned division instruction.
Program using 32-bit division
Program using 16-bit division
MOV BX , 4
; BX = 4
MOV BL , 4
; BL = 4
MOV AX , 23
; AX = 35
MOV AX , 23
; AX = 35
MOV DX, 0
; (DX - AX) = 35
DIV BL
; AH = remain., AL = quot.
DIV BX
; DX = remain., AX = quot.
INT
INT
20
© 2015 Gilbert Ndjatou
20
158
Example 6.11
Instructions to perform signed divisions.
Write a Debug program to compute -35/ 4 using a signed division instruction.
Program using 32-bit division
Program using 16-bit division
MOV BX , 4
; BX = 4
MOV BL , 4
; BL = 4
MOV AX , -23
; AX = -35
MOV AX , -23
; AX = -35
CW D
; (DX - AX) = -35
IDIV BL
; AH = remain., AL = quot.
IDIV BX
; DX = remain., AX = quot.
INT
INT
20
20
Sample Computations The following programs illustrate the concepts introduced so far in this chapter. They combine data transfer instructions, conversion instructions, and integer arithmetic instruction to perform computations. Both programs compute arithmetic expressions.
Figure 6.3 Debug program to compute the arithmetic expression: 2 - 5 * 12 + 10 - (-30)/6 + 50 and load the result in register DX.
The remainder of the division is ignored. Instructions
Remarks
MOV CX, 2
; CX = 2
MOV AX, 5
; multiplication must be performed first
MOV BX, 0C IMUL BX SUB © 2015 Gilbert Ndjatou
; (DX AX) = 5 * 12 CX, AX
; CX = 2 - 5 * 12
159 ADD
CX, 0A
; CX = 2 - 5 * 12 + 10
MOV AX, -1E
; perform division first
CWD
; (DX AX) = -30
MOV BX, 6 IDIV
BX
; AX = quotient of -30 / 6
SUB
CX, AX
; CX = 2 - 5 * 12 + 10 - (-30)/6
ADD
CX, 32
; CX = 2 - 5 * 12 + 10 - (-30)/6 + 50
MOV DX, CX INT
; copy the result to DX
20
Figure 6.4
Suppose that there are signed integers n and m in the main memory at offsets 0120 and 0130 respectively. The following Debug program computes the arithmetic expression: n + m * n - (n + m) / m and load the result in register DX. The remainder of the division is ignored. It is also assumed that the product can be represented as a word (in register AX). Instructions
Remarks
MOV CX, [DS:120]
; CX = n
MOV AX, [DS:120]
; perform multiplication first
IMUL WORD PTR [DS:130] ; (DX, AX) = m * n ADD
CX, AX
; CX = n + m * n
MOV AX, [DS:120]
; perform the expression in parentheses first
ADD
; AX = n + m
AX, [DS:130]
; then perform the division ; (DX, AX) = n + m
CWD IDIV
WORD PTR [DS:130] ; AX = quotient of (n + m) / m
SUB
CX, AX
MOV DX, CX INT
© 2015 Gilbert Ndjatou
20
; CX = n + m * n - (n + m) / m ; copy the result to DX
160
Exercise 6.4
1. For each of the following contents of registers AX, BX, and DX, execute the instruction IDIV
BX
and show the contents of these registers after the execution: a. AX:
0007
BX:
0002
DX:
0000
b. AX:
FFF9
BX:
0002
DX:
FFFF
c. AX:
0007
BX:
FFFE DX:
0000
d. AX:
FFF9
BX:
FFFE DX:
FFFF
2. Write a sequence of assembly language instructions to execute each of the following operations in the Debug environment: a. 25 / 7
b. -38 / 11
3. Write a sequence of assembly language instructions to execute each of the following arithmetic expressions in the Debug environment and load the result in register CX: a. 15 + 19 / 6 - 4 * 7 - 13
b. 12 + 5 * 4 - (-38) /(11 + 6 - 3) + 5
4. Write a sequence of assembly language instructions (to be executed in the Debug environment) to convert the Fahrenheit temperature 89 to Celsius and load the result in register CX. The formula for this conversion is C = 5 / 9 x (F - 32) 5. Write a sequence of assembly language instructions (to be executed in the Debug environment) to load a three-digit positive integer value in register AX, and to add all its digits and load the result in register CX.
Increment, Decrement, and Negation Instructions The Intel 8086 processor also has instructions to add 1 to the contents of a register or memory location, to subtract 1 from the contents of a register or memory location, and to take the two’s complement of a signed integer. These instructions are named respectively, INC (increment instructions), DEC (decrement instructions), and NEG (negation instructions). © 2015 Gilbert Ndjatou
161 INC instructions The INC (increment) instructions add one to their operand. The operand is either a signed or unsigned integer in a register or a memory location. They are defined as follows:
Syntax:
INC destination
Operation:
destination = destination + 1
Flags status: ZF, SF, OF, AF, and PF may be modified. The destination operand is an 8-bit register or memory location, or a 16-bit register (that is not a segment register) or memory location. Example 6.12 illustrates the execution of these instructions.
DEC instructions The DEC (decrement) instructions subtract one from their operand. The operand is a signed or an unsigned integer in a register or a memory location. They are defined as follows:
Syntax:
DEC destination
Operation:
destination = destination - 1
Flags status: ZF, SF, OF, AF, and PF may be modified. The destination operand is an 8-bit register or memory location, or a 16-bit register (that is not a segment register) or memory location. Example 6.12 illustrates the execution of these instructions.
NEG instructions The NEG (negation) instructions subtract the contents of a register or a memory location operand from zero and then replaces the original contents with the result. These instructions are defined as follows:
© 2015 Gilbert Ndjatou
162 Syntax:
NEG destination
Operation:
destination = 0 - destination
Flags status: ZF, SF, OF, AF, and PF may be modified. CF is set if destination is not 0. The destination operand is either an 8-bit register or memory location, or a 16-bit register (that is not a segment register) or memory location. An attempt to negate the smallest 8-bit or 16-bit signed integer will produce an overflow condition. Example 6.12 illustrates the execution of these instructions in the Debug environment.
Example 6.12
Executions of INC, DEC, and NEG instructions in the Debug environment
It is assumed that the initial data is moved into the registers or the memory locations before the execution of each instruction. a) INC
BX Registers BX
b) INC BYTE PTR
Before execution:
0009
After execution:
000A
[200h] Memory locations Offset:
c) DEC
0200
Before execution:
05
After execution:
06
BL Registers BL
© 2015 Gilbert Ndjatou
Before execution:
0A
After execution:
09
163 d) DEC WORD PTR [200h] Memory locations Offset:
e) NEG
0200
0201
Before execution:
0B
00
After execution:
0A
00
AX Registers AX
f) NEG BYTE PTR
Before execution:
0001
After execution:
FFFF
[200h] Memory locations Offset:
6.4
0200
Before execution:
FE
After execution:
02
Iteration Instruction
An iteration instruction is an instruction that specifies that the execution of one or more instructions be repeated a certain number of times. The iteration instruction provided by the Intel 8086 processor is the Loop instruction with mnemonic opcode LOOP. For this instruction, the count register CX must contain the number of times the execution must be repeated. It is defined as follows:
Loop Instruction Syntax:
LOOP
ShortOffset
Operation: 1. CX := CX - 1 2. If CX 0
then
IP =
ShortOffset
Otherwise, continue with the next instruction. Flags:
© 2015 Gilbert Ndjatou
none of the flags is affected.
164 In the above definition, ShortOffset is the offset of the first instruction in the sequence of instructions (or body of the loop) whose execution must be repeated. The size of the body of the loop must be less than or equal to 126 bytes. This implies that the relative address of the first instruction in the body of the loop (with respect to the Loop instruction) must be specified as a byte. Note that if count is the initial value in register CX, then the Loop instruction will repeat the execution of each instruction in the body of the loop count times. Example 6.13 illustrates the execution of Loop instructions that are used to change the contents of consecutive memory locations.
Example 6.13
Tracing Programs that use the Loop Instruction to affect the Contents of Consecutive Memory Locations. M emory Locations at Offset:
Inst. #
AL
BX
CX
?
?
?
?
0200
0201
0202
?
?
?
00 03
?
?
?
Offset
Instructions
0100
MOV
CX, 3
1
?
103
MOV
BX, 200
2
?
02 00
00 03
?
?
?
106
MOV
AL, 4E
3
4E
02 00
00 03
?
?
?
108
MOV
[BX], AL
4
4E
02 00
00 03
4E
?
?
10A
SUB
AL, 4
5
4A
02 00
00 03
4E
?
?
10C
INC
BX
6
4A
02 01
00 03
4E
?
?
10D
LOOP
108
7
4A
02 01
00 02
4E
?
?
10F
INT
20
4
4A
02 01
00 02
4E
4A
?
5
46
02 01
00 02
4E
4A
?
6
46
02 02
00 02
4E
4A
?
7
46
02 02
00 01
4E
4A
?
4
46
02 02
00 01
4E
4A
46
5
44
02 02
00 01
4E
4A
46
6
44
02 03
00 01
4E
4A
46
7
44
02 03
00 00
4E
4A
46
© 2015 Gilbert Ndjatou
165 M emory Locations at Offset:
Inst. #
BX
CX
0200
0201
0202
0204
?
?
06
00
0A
00
00 02
06
00
0A
00
Offset
Instructions
0100
MOV
CX, 2
1
0103
MOV
BX, 200
2
02 00
00 02
06
00
0A
00
0106
ADD
W ORD PTR [BX], 5
3
02 00
00 02
0B
00
0A
00
0109
ADD
BX, 2
4
02 02
00 02
0B
00
0A
00
010C
LOOP
106
5
02 02
00 01
0B
00
0A
00
010E
INT
20
3
02 02
00 01
0B
00
0F
00
4
02 04
00 01
0B
00
0F
00
5
02 04
00 00
0B
00
0F
00
?
Sample Program We discuss here a sample program that uses the Loop instruction.
Problem Statement Given the fullword binary integers e and n, write a Debug program to compute the eth power of n, ne. Assume that e > 0 and that e and n are such that the result will be a word. e is stored in the data segment at offset 0120 and n is stored at offset 0130. The result will be stored at offset 0140.
Program Logic This program requires you to copy 1 into register AX, and then multiply the contents of register AX by n e times. After the first iteration of the loop, register AX will contain n1, and after the second iteration, it will contain n2, . . . , and after the eth iteration, it will contain ne. In order to use the LOOP instruction to accomplish this, you must first load e into register CX. The desired algorithm is described in pseudocode as follows:
© 2015 Gilbert Ndjatou
166 CX ² e AX ² 1 REPEAT e times (DX AX) ² AX * n END REPEAT save the result: store AX
The instructions of this program are provided in Figure 6.5. Note that every time the Loop instruction is executed, 1 is subtracted from the value in register CX and the new value is compared to 0. If it is greater than 0, then the instruction at offset 0107 is executed again, followed by the other instructions in the sequence until the Loop instruction; if it is 0, then the iteration stops and the instruction that follows the Loop instruction at offset 010D is executed.
Figure 6.5
Given the fullword binary integers e stored at offset 0120 and n stored at offset 0130, compute ne and store the result at offset 0140. e > 0 and e and n are such that the result is a word. offset
Instructions
Remarks
0100
MOV CX , [DS:120]
; repeat e times
0104
MOV AX , 1
0107
IMUL WORD PTR [DS:130]
010B
LOOP 107
010D
MOV [DS:140] , AX
0110
INT
20
0120
DW
4
; exponent
0130
DW
0C
; number
0140
DW
0
; reserved for the result
; (DX, AX) = AX * n
; if CX > 0 jump to 0107; otherwise continue ; store the result
; ; data
© 2015 Gilbert Ndjatou
167
6.5
Processing One-Dimensional Arrays
In High-level languages, a one-dimensional array is a structure that contains values of the same data type, and is ordered in such a way that individual values may be accessed either by their relative position in the structure or by using a pointer variable. In the first case, the relative position is written in parentheses or in brackets and is called a subscript. In the second case, a pointer variable is first initialized to the offset of the first element of the array, and then, is incremented to moved to the next one. For example, in C/C++ programming language, an array of ten integers called list is defined by providing the data type, int of its elements, and the number of elements in the array as follows: int list[10]; The elements of this array occupy consecutive memory locations and could be defined in assembly language by using the define directive introduced in chapter 4 as follows: DW
10 DUP (?)
This definition includes the size of the elements of the array (which in this case is two) and the number of elements in the array, ten. In some high-level languages, it is possible to specify the initial values for the elements of an array when that array is defined. For example, the following C/C++ definition creates an array of five signed integers and initializes its elements with the integer constants provided in braces: int list[]
= {3, -5, 31, 16, -17};
The elements of this array could be defined in assembly language by using the define directive as follows: DW
3, -5, 31, 16, -17
The elements of an array of ten bytes could also be defined as follows: DB
10 DUP (?)
Note that in these definitions we do not specify the data type of the elements of the array. For example, the elements of an array of five bytes could be defined and initialized with 8-bit signed integer values as follows:
© 2015 Gilbert Ndjatou
168 DB
12, -5, -21, 10, 23
It could also be initialized with five character values as follows: DB
‘KABIL’
Using Register Indirect Addressing with Arrays In some high-level languages, individual elements on an array can be accessed by using a pointer variable that is incremented to point to the next element. For example, in the C/C++ programming language, a pointer variable can be used to access the elements of the above array list in order to compute their sum as follows:
int sum = 0; int * pt; for (pt = list; pt < list + 5; pt ++) sum = *pt + sum;
This method of accessing the element of an array is implemented in assembly language by using the register indirect addressing discussed in chapter 4. In the program in Figure 6.6, we use register BX to hold the offset of the array elements. Note that register SI or DI could also be used.
Sample Program 1 Problem Statement An array of five fullword signed integers is stored in memory starting at offset 0120. Write a Debug program to compute the average of the elements of this array. The remainder of the division is ignored and the result (quotient) is stored at offset 0130.
© 2015 Gilbert Ndjatou
169 Program Logic This problem requires you to copy 0 into a register (register AX), and then add each of the five elements of the array to register AX: after the first iteration of the loop, the first element will be in register AX; after the second iteration, the sum of the first two elements will be in register AX; . . . ; and after the fifth iteration, the sum of all the five elements will be in register AX. The sum of the five elements is then divided by five to get the average. In order to use the LOOP instruction to add all the elements of this array to register AX, you must first load 5 into register CX. You must also load into register BX the offset of the first element of the array. Register BX is then incremented by 2 in the body of the loop in order to point to the next element of the array. The desired algorithm is described in pseudocode as follows:
CX ² 5 AX ² 0 BX ² 120 REPEAT 5 times AX ² AX + (BX ÷element) BX ² BX + 2 END REPEAT (DX , AX) = (DX , AX) ÷ 5 save the result: store AX
The instructions of this program are provided in Figure 6.6.
Figure 6.6 Debug program to compute the average of the elements of an array of five fullword signed integers using register indirect addressing. The elements of the array are stored in memory starting at offset 0120. The remainder of the division is ignored, and the result (quotient) is stored in memory at offset 0130. © 2015 Gilbert Ndjatou
170 offset
Instructions
Remarks
0100
MOV CX, 5
; repeat 5 times
0103
MOV AX, 0
0106
MOV BX, 120
; BX points to the first element
0109
ADD
AX, [BX]
; AX ² AX + (BX ÷ element)
010B
ADD
BX, 2
; BX points to next element
010E
LOOP 109
; if CX > 0 jump to 0109; otherwise, continue
0110
CWD
; (DX, AX) = sum of the elements
0111
MOV BX, 5
; reuse BX to hold the number of elements
0114
IDIV
; AX = average
0116
MOV [DS:130], AX ; store the result
011A
INT
BX 20
; ; data 0120
DW
23, FFF4, 5, FFFD, 16 ; array
0130
DW
0
; reserved for the average
Using Indexed Addressing or Base Relative Addressing with Arrays In High-level languages, individual elements of an array can also be accessed by using their relative position in the array. The relative position of an element is written in parentheses or in brackets as in the following C/C++ code segment:
int i, sum = 0; for ( i = 0; i < 10; i ++) sum = list[i] + sum; This method of accessing the elements of an array can be implemented in assembly language by using the indexed addressing mode or the base relative addressing mode introduced in chapter 4. In the following sample programs, we will use the indexed addressing mode. But, it is understood that the base relative addressing could also be used by replacing register SI or DI with register BX, or with register BP if the array is in the stack. © 2015 Gilbert Ndjatou
171 Sample Program 2 Problem Statement the problem statement is the same as in Sample Program 1.
Program Logic This problem requires you to copy 0 into a register (register AX), and then add each of the five elements of the array to register AX: after the first iteration of the loop, the first element will be in register AX; after the second iteration, the sum of the first two elements will be in register AX; . . . ; and after the fifth iteration, the sum of all the five elements will be in register AX. The sum of the five elements is then divided by five to get the average. In order to use the LOOP instruction to add all the elements of this array to register AX, you must first load 5 into register CX. You must also load into register DI, 0: the relative position of the first element of the array is 0. Register DI is then incremented by 2 in the body of the loop in order to hold the relative position of the next element of the array. The desired algorithm is described in pseudocode as follows:
CX ² 5 AX ² 0 DI ² 0 REPEAT 5 times AX ² AX + 120[DI] DI ² DI + 2 END REPEAT (DX , AX) = (DX , AX) ÷ 5 save the result: store AX
The instructions of this program are provided in Figure 6.7.
© 2015 Gilbert Ndjatou
172
Figure 6.7 Debug program to compute the average of the elements of an array of five fullword signed integers using the direct indexed addressing. The elements of the array are stored in memory starting at offset 0120. The remainder of the division is ignored and the result (quotient) is stored in memory at offset 0130. offset
Instructions
Remarks
0100
MOV CX, 5
0103
MOV AX, 0
0106
MOV DI, 0
0109
ADD
AX, [DI + 120] ; AX ² AX + 120[DI]
010C
ADD
DI, 2
010F
LOOP 109
; if CX > 0 jump to 0109; otherwise, continue
0111
CWD
; (DX, AX) = sum of the elements
0112
MOV BX, 5
; BX holds the number of elements
0115
IDIV
; AX = average
0117
MOV [DS:130], AX ; store the result
011B
INT
BX
; repeat 5 times ; DI holds the relative position of the first element ; DI holds relative position of next element
20
; ; data 0120
DW
23, FFF4, 5, FFFD, 16 ; array
0130
DW
0
; reserved for the average
Sample Program 3 Problem Statement Write a Debug program to add 25 to each element of an array A of 5 word signed integers, and to construct another array B such that: B[i] = 25 + A[i]. Assume that the elements of Array A are stored in memory starting at offset 0120, and that the elements of array B will be stored in memory starting at offset 0130.
© 2015 Gilbert Ndjatou
173 Program Logic The elements of array A are accessed by using an operand in direct indexed addressing mode in which the displacement is the offset of the first element of the array, 0120. Similarly, the elements of array B are accessed by using an operand in direct indexed addressing mode in which the displacement is the offset of the first element of the array, 0130. Since both arrays are processed in parallel, the index register SI is used as the index in both arrays. It is first initialized to 0, and then incremented by 2 after the processing of each pair of array elements (one in array A and the other in array B). In order to use the LOOP instruction to process all the elements of both arrays, you must first load 5 into register CX. The desired algorithm is described in pseudocode as follows:
CX ² 5 SI ² 0 REPEAT 5 times 130[SI] ² 120[SI] + 5 SI ² SI + 2 END REPEAT
The corresponding program is provided in Figure 6.8.
Figure 6.8 Debug Program to compute B[i] = A[i] + 25. The elements of array A and array B are stored in memory starting at offset 0120, and offset 0130 respectively.
© 2015 Gilbert Ndjatou
offset
Instructions
0100
MOV CX, 5
; loop 5 times
0103
MOV SI, 0
; initialize index to 0
174 0106
MOV AX, [SI + 120]
; AX := A[SI]
010A
ADD AX, 19
; AX := A[SI] + 25
010D
MOV [SI + 130], AX
; B[SI] := A[SI] + 25
0111
ADD SI, 2
; SI := SI + 2
0113
LOOP 106
; if CX 0 branch back
0115
INT
20
; 0120
DW
4, FFFB, 0A, FFF1, 14
0130
DW
0, 0, 0, 0, 0
Exercise 6.5
Note: In order to write the fallowing programs, assume that the first instruction in the body -of-theloop is at offset 0000; then as you assemble the program in the Debug environment, fill in its offset in the LOOP instruction.
1. Write a Debug program to compute the sum of the first 10 positive integer values and to store the result in the data segment at offset 0130. 2. Write a Debug program to compute the product of the first 10 positive integer values and to store the result in the data segment at offset 0130. 3. Write a Debug program to compute the sum of the first 10 positive multiples of 5 and to store the result in the data segment at offset 0130. 4. An integer value is stored in the data segment at offset 0120. Write a debug program to compute the 5th power of this integer value and to store the result in the data segment at offset 0130. Assume that the result is a word. 5. An array A of ten word two’s complement binary integers is stored in the data segment starting at offset 0120. Write a Debug program to add 5 to each element of this array. That means A[i] = A[i] + 5. 6. An array A of ten word two’s complement binary integers is stored in the data segment starting at offset 0120. Write a Debug program to subtract 15 to each element of this array and to store the result into the corresponding element of an array B that will be stored into the data segment starting at offset 0130 . That means B[i] = A[i] - 15.
© 2015 Gilbert Ndjatou
175 7. Two arrays A and B of ten word two’s complement binary integers are stored in the data segment starting at offset 0120 and 0130 respectively. Write a Debug program to subtract from each element of array A the corresponding element of array B, and to store the result into the corresponding element of another array C that will be stored into the data segment starting at offset 0140 . That means C[i] = A[i] - B[i].
6.6
Executing a Debug Program
This section provides the step-by-step procedures to assemble and execute Debug programs: the first procedure which is described in Figure 6.9 is used for programs without any reference to memory locations whereas the second which is described in Figure 6.10 is used for programs with references to memory locations. The program defined in Figure 6.1 is used to illustrate the first procedure and the program defined in Figure 6.8 is used to illustrate the second one.
Figure 6.9
Step 1:
Step-by-Step Procedure to assemble and execute a Debug program without any reference to memory locations.
At the MS-DOS prompt, execute Debug C:\W INDOW S>DEBUG -
Step 2:
At the Debug prompt, assemble the instructions of your program starting at offset 0100.
-A 100 0D87:0100 M OV AX, 6
; AX = 6
0D87:0103 SUB AX, 0A
; AX = 6 - 10
0D87:0106 ADD AX, -0F
; AX = 6 - 10 + (-15)
0D87:0109 ADD AX, 14
; AX = 6 - 10 + (-15) + 20
0D87:010C SUB AX, -7
; AX = 6 - 10 + (-15) + 20 - (-7)
0D87:010F M OV DX, AX
; DX = AX
0D87:0111 INT 20 0D87:0113
© 2015 Gilbert Ndjatou
176 Step 3:
After you have entered the last instruction of the program, press the ENTER key to return to the Debug prompt. -
Step 4:
disassemble the instructions of your program (from the memory locations where you have entered them in Step 2). -U 100 112 0D87:0100 B80600
MOV
AX,0006
0D87:0103 2D0A00
SUB
AX,000A
0D87:0106 05F1FF
ADD
AX,FFF1
0D87:0109 051400
ADD
AX,0014
0D87:010C 2DF9FF
SUB
AX,FFF9
0D87:010F 89C2
MOV
DX,AX
0D87:0111 CD20
INT
20
Step 5:
Display the contents of the registers: -R AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0100 NV UP EI PL NZ NA PO NC 0D87:0100 B80600
MOV
AX,0006
Step 6:
Trace the execution of the program starting at offset 0100: -T=100 AX=0006 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0103 NV UP EI PL NZ NA PO NC 0D87:0103 2D0A00
SUB
AX,000A
-T AX=FFFC BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0106 NV UP EI NG NZ AC PE CY 0D87:0106 05F1FF
ADD
AX,FFF1
-T AX=FFED BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0109 NV UP EI NG NZ NA PE CY 0D87:0109 051400
ADD
AX,0014
-T AX=0001 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=010C NV UP EI PL NZ AC PO CY 0D87:010C 2DF9FF
SUB
AX,FFF9
-T AX=0008 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=010F NV UP EI PL NZ AC PO CY 0D87:010F 89C2
© 2015 Gilbert Ndjatou
MOV
DX,AX
177 -T AX=0008 BX=0000 CX=0000 DX=0008 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0111 NV UP EI PL NZ AC PO CY 0D87:0111 CD20
INT
20
-G Program terminated normally Step 7:
Identify the result(s) of the program (in registers or in memory). -R AX=0008 BX=0000 CX=0000 DX=0008 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0111 NV UP EI PL NZ AC PO CY 0D87:0111 CD20
INT
20
-
Figure 6.10
Step 1:
Step-by-Step Procedure to assemble and execute a Debug program with references to memory locations. At the MS-DOS prompt, execute Debug C:\W INDOW S>DEBUG -
Step 2:
At the Debug prompt, assemble the instructions of your program starting at offset 0100. -A 100 0D87:0100 M OV CX, 5
;LOOP 5 TIM ES
0D87:0103 M OV SI, 0
; INITIALIZE INDEX TO 0
0D87:0106 M OV AX, 120[SI]
; AX = A[SI]
0D87:010A ADD AX, 19
; AX = A[SI] + 25
0D87:010D M OV 130[SI], AX
; B[SI] = A[SI] + 25
0D87:0111 ADD SI, 2
; SI = SI + 2
0D87:0114 LOOP 106
; IF CX 0 BRANCH BACK
0D87:0116 INT 20 0D87:0118
Step 3:
After you have entered the last instruction of the program, press the ENTER key to return to the Debug prompt. -
© 2015 Gilbert Ndjatou
178 Step 4:
disassemble the instructions of your program (from the memory locations where you have entered them in Step 4). -U 100 117
Step 5:
0D87:0100 B90500
MOV
CX,0005
0D87:0103 BE0000
MOV
SI,0000
0D87:0106 8B842001
MOV
AX,[SI+0120]
0D87:010A 051900
ADD
AX,0019
0D87:010D 89843001
MOV
[SI+0130],AX
0D87:0111 83C602
ADD
SI,+02
0D87:0114 E2F0
LOOP
0106
0D87:0116 CD20
INT
20
Define the memory locations that correspond to the operands: Define the first array then press the Enter key to return to Debug prompt -A 120 0D87:0120 DW 4, FFFB, 0A, FFF1, 14 0D87:012A Define the second array then press the Enter key to return to Debug prompt -A 130 0D87:0130 DW 0, 0, 0, 0, 0 0D87:013A -
Step 6:
Display the memory locations that contain the data and identify the different data elements -D 120 13F
Array A
0D87:0120 04 00 FB FF 0A 00 F1 FF-14 00 BF DB E1 F3 A4 AA ................
Array B
0D87:0130 00 00 00 00 00 00 00 00-00 00 D7 E0 C7 06 CD DF ................
Step 7:
Display the contents of the registers: -R AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0100 NV UP EI PL NZ NA PO NC 0D87:0100 B90500
Step 8:
MOV
CX,0005
-
Trace the execution of the program starting at offset 0100: -T =100 AX=0000 BX=0000 CX=0005 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0103 NV UP EI PL NZ NA PO NC 0D87:0103 BE0000
MOV
SI,0000
-T AX=0000 BX=0000 CX=0005 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0106 NV UP EI PL NZ NA PO NC 0D87:0106 8B842001
© 2015 Gilbert Ndjatou
MOV
AX,[SI+0120]
DS:0120=0004
179 -T AX=0004 BX=0000 CX=0005 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=010A NV UP EI PL NZ NA PO NC 0D87:010A 051900
ADD
AX,0019
-T AX=001D BX=0000 CX=0005 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=010D NV UP EI PL NZ NA PE NC 0D87:010D 89843001
MOV
[SI+0130],AX
DS:0130=0000
-T AX=001D BX=0000 CX=0005 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0111 NV UP EI PL NZ NA PE NC 0D87:0111 83C602
ADD
SI,+02
-T AX=001D BX=0000 CX=0005 DX=0000 SP=FFEE BP=0000 SI=0002 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0114 NV UP EI PL NZ NA PO NC 0D87:0114 E2F0
LOOP
0106
-T AX=001D BX=0000 CX=0004 DX=0000 SP=FFEE BP=0000 SI=0002 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0106 NV UP EI PL NZ NA PO NC 0D87:0106 8B842001
MOV
AX,[SI+0120]
DS:0122=FFFB
• • • -T AX=000A BX=0000 CX=0002 DX=0000 SP=FFEE BP=0000 SI=0008 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0114 NV UP EI PL NZ NA PO NC 0D87:0114 E2F0
LOOP
0106
-T AX=000A BX=0000 CX=0001 DX=0000 SP=FFEE BP=0000 SI=0008 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0106 NV UP EI PL NZ NA PO NC 0D87:0106 8B842001
MOV
AX,[SI+0120]
DS:0128=0014
-T AX=0014 BX=0000 CX=0001 DX=0000 SP=FFEE BP=0000 SI=0008 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=010A NV UP EI PL NZ NA PO NC 0D87:010A 051900
ADD
AX,0019
-T AX=002D BX=0000 CX=0001 DX=0000 SP=FFEE BP=0000 SI=0008 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=010D NV UP EI PL NZ NA PE NC 0D87:010D 89843001
© 2015 Gilbert Ndjatou
MOV
[SI+0130],AX
DS:0138=0000
180 -T AX=002D BX=0000 CX=0001 DX=0000 SP=FFEE BP=0000 SI=0008 DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0111 NV UP EI PL NZ NA PE NC 0D87:0111 83C602
ADD
SI,+02
-T AX=002D BX=0000 CX=0001 DX=0000 SP=FFEE BP=0000 SI=000A DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0114 NV UP EI PL NZ NA PE NC 0D87:0114 E2F0
LOOP
0106
-T AX=002D BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=000A DI=0000 DS=0D87 ES=0D87 SS=0D87 CS=0D87 IP=0116 NV UP EI PL NZ NA PE NC 0D87:0116 CD20
INT
20
-G Program terminated normally Step 9:
Dump the memory locations that contain the data and Identify the result(s) of the program (in registers or in memory). -D 120 13F
Array A
0D87:0120 04 00 FB FF 0A 00 F1 FF-14 00 BF DB E1 F3 A4 AA ................
Array B
0D87:0130 1D 00 14 00 23 00 0A 00-2D 00 D7 E0 C7 06 CD DF ....#...-....... -
In the debugging sessions provided in Figure 6.9 and Figure 6.10, the descriptions of the steps are in italic and the commands or the entries typed by the user are in bold. Notice that after you disassemble the instructions of a program, you must check to make sure that the unassembled instructions correspond to the instructions that you assembled in step 2. Also, after you dump the contents of memory locations containing the data elements of your program, you must check to make sure that the displayed data elements correspond to those that were entered in memory. You may notice in Figure 6.10 that in a debugging session, the contents of a memory location operand are displayed to the right of the instruction in which it is referenced. After the execution of an instruction, you may also check the contents of memory locations before you continue the execution with the next instruction.
© 2015 Gilbert Ndjatou
181 The programs are executed in Figure 6.9 and Figure 6.10 by stepping through them one instruction at a time. This approach allows you to observe how individual instructions of a program are executed and to have control over the execution of your program: partial results can be checked and verified, and mistakes are detected exactly where they have occurred. You could also use the T (Trace) command to trace more than one instruction at a time, or the G (Go) or the P (Proceed) command to execute more than one instruction at a time. For example, in the debugging sessions in Figure 6.9 and Figure 6.10, the G (Go) command is used to execute the interrupt handler for interrupt 20h. The T (Trace) command would have stepped through the interrupt handler one instruction at a time.
Printing a Debugging Session One way to print a debugging session is to use the Mark and the Copy Enter operations provided in a DOS window. The Mark operation is used to mark a section of a DOS window, and the Copy Enter operation is used to copy the marked section of a DOS window to the clipboard. These two operations can be used during a debugging session to copy parts of the debugging session to the clipboard, and then paste them in a Notepad or a wordprocessor file for printing at the end of the debugging session. In order to do this, you must first open a Notepad or a wordprocessor file and then minimize its window before you run Debug. Sections of a debugging session are copied to the clipboard and then pasted to the output file as they appear in the DOS window: after a section of the DOS window is copied to the clipboard, you will switch to your output file to paste it into the file, and then switch back to the DOS window to continue the debugging session. At the end of the debugging session, the output file is printed using the usual printing procedure of Notepad or the wordprocessor used to create the file.
© 2015 Gilbert Ndjatou
182 Using the Mark and the Copy Enter Commands in a DOS Window To select a section of a DOS window, do the following: S
click the MS-DOS prompt icon on the title bar to access a drop down menus
S
select Edit, then Mark from the drop down menus.
S
Now use the mouse to highlight the section of the window that you want to select: double click at one end of the window section that you want to select, and then drag the mouse diagonally to the other end.
To copy the selected section of the window to the clipboard, press the ENTER key or do the following: S
click the MS-DOS prompt icon on the title bar to access the drop down menus.
S
select Edit, then Copy Enter from the drop down menus.
© 2015 Gilbert Ndjatou