Assambly ch03
Assambly ch03
ISBN 0-13-660390-4
From this point on, we will use the Microsoft Assembler (called MASM) and Turbo
Assembler (called TASM). Although many examples in this chapter could be assembled
and tested using Debug, it has many limitations. For example, Debug does not let you
create symbolic names, or insert and delete individual source code lines. If you need to
review the commands for assembling, linking, and debugging programs, refer to Section
3.3 for the specific commands applying to various assemblers.
Integer constants can end with a radix symbol that identifies the numeric base. The bases
are: h = hexadecimal, q (or o) = octal, d = decimal, b = binary. If no radix is specified,
decimal is the default. Uppercase/lowercase differences are ignored. Here are examples:
26 decimal
1Ah hexadecimal
1101b binary
36q octal
2BH hexadecimal
42Q octal
36D decimal
47d decimal
0F6h hexadecimal
When a hexadecimal constant begins with a letter, it must contain a leading zero.
Although the radix can be uppercase, we recommend that lowercase be used consistently for a
more uniform appearance.
A constant expression consists of combinations of numeric literals, operators, and
defined symbolic constants. The expression value must be able to be determined at assembly
time, and its value cannot change at runtime. Here are some examples of expressions
involving only numeric literals:
3.1 BASIC ELEMENTS OF ASSEMBLY LANGUAGE 55
5
26.5
4 * 20
3 * 4 / 6
2.301E+04
Although these declarations look like runtime statements written in a high-level language, it is
important to realize that they can only be evaluated at assembly time.
Character or String Constant. A constant may also represent a string of characters enclosed
in either single or double quotation marks. Embedded quotes are permitted, as the following
examples show:
ABC
X
This is a test
4096
This isnt a test
Say hello to Bill.
Notice that the string constant containing 4096 is four bytes long, each containing the
ASCII code for a single character.
3.1.2 Statements
An assembly language statement consists of a name, an instruction mnemonic, operands, and
a comment. Statements generally fall into two classes, instructions and directives. Instruc-
tions are executable statements, and directives are statements that provide information to tell
the assembler how to generate executable code. The general format of a statement is:
[name] [mnemonic] [operands] [;comment]
Statements are free-form, meaning that they can be written in any column with any
number of spaces between each operand. Blank lines are permitted between statements. A
statement must be written on a single line and cannot pass column 128. You can continue a
line onto the next line, if the last character in the first line is \ (backslash):
longArrayDefinition dw 1000h, 1020h, 1030h \
1040h, 1050h, 1060h, 1070h, 1080h
56 CHAPTER 3: ASSEMBLY LANGUAGE FUNDAMENTALS
A directive is a statement that affects either the program listing or the way machine code
is generated. For example, the db directive tells the assembler to create storage for a byte
variable named count and initialize it to 50:
count db 50
The following .stack directive tells the assembler to reserve 4096 bytes of stack space:
.stack 4096
3.1.3 Names
A name identifies a label, variable, symbol, or keyword. It may contain any of the following
characters:
Character Description
A . . . Z, a . . . z Letters
0...9 Digits
? Question mark
_ Underscore
@ @ Sign
$ Dollar sign
. Period
Label. If a name appears in the code area of a program, it is called a label. Labels serve as
place markers when a program needs to jump or loop from one location to another. A label
can be on a blank line by itself, or it can share a line with an instruction. In the following
example, Label1 and Label2 are labels identifying locations in a program:
Label1: mov ax,0
mov bx,0
.
.
Label2:
jmp Label1 ; jump to Label1
Keyword. A keyword always has some predefined meaning to the assembler. It can be an
instruction, or it can be an assembler directive. Examples are MOV, PROC, TITLE, ADD, AX,
and END. Keywords cannot be used out of context or as identifiers. In the following, the use
of add as a label is a syntax error:
add: mov ax,10
.code
main proc
mov ax,@data
mov ds,ax
mov ah,9
mov dx,offset message
int 21h
mov ax,4C00h
int 21h
main endp
end main
Next in the main procedure, we write a character string on the screen. This is done
by calling an MS-DOS function that displays a string whose address is in the DX
register. The function number is placed in the AH register.
The last two statements in the main procedure (mov ax,4C00h / int 21h) halt the
program and return control to the operating system.
The statement main endp uses the ENDP directive. ENDP marks the end of the
current procedure. Procedures, by the way, are not allowed to overlap.
The end of the program contains the end directive, which is the last line to be
assembled. The label main next to it identifies the location of the program entry
point, that is, the point at which the CPU starts to execute the programs instructions.
At this point you may be fondly remembering the first Hello, world program you
wrote in C, C++, Java, or Pascal. How can the assembly language version be so complicated?
Actually, if you looked at the machine code generated by a high-level language compiler, you
would see a lot of extra code that was automatically added to the program. In contrast, an
assembler only inserts machine code for instructions that you have written. It is interesting to
compare the executable size of the same program written and compiled in C++ (8772 bytes)
to that of the program in Example 1 (562 bytes). Now whos doing more work?
Table 1 contains a list of the most commonly used assembler directives.
Directive Description
Link
Library
(DOS
(assembler) (linker) loader)
Source Object Executable
Output
File File Program
Listing Map
(text editor) File File
The assembler produces an optional listing file, which is a copy of the programs
source file (suitable for printing) with line numbers and translated machine code. The
linker produces an optional map file, which contains information about the programs
code, data, and stack segments.
A link library is a file containing subroutines that are already compiled into
machine language. Any procedures called by your program are copied into the execut-
able program during the link step. (If youve ever programmed in Pascal or C, you have
made extensive use of link libraries, perhaps without realizing it). Table 2 displays a list
of filenames that would be created if we assembled and linked the Hello World program.
3.3 ASSEMBLING, LINKING, AND DEBUGGING 61
We have shown the MS-DOS command prompt here as C:\> for illustrative purposes, but
your command prompt may be different. This command can be typed at the command-line
prompt in MS-DOS, or in an MS-DOS shell running under Windows. The /l/n options tell the
assembler to produce a listing file, with no symbol table, and /z indicates that source lines
with errors are to be displayed. The following is the screen output produced by assembling
the program with the Borland assembler:
Turbo Assembler Version 4.1
Copyright (c) 1988, 1996 Borland International
The primary file produced by the assembly step is hello.obj. The assembler distin-
guishes between error messages and warning messages. A program with warning messages
will still assemble, but the object file may have errors. In general, it is best to fix such errors
before linking the program.
Syntax Errors. We were fortunate to have not made any mistakes when writing this program.
But if we had, the assembler would have displayed the line with the mistake, along with an
explanation. For example, value1 was incorrectly spelled as vlue1:
62 CHAPTER 3: ASSEMBLY LANGUAGE FUNDAMENTALS
Linking the Program. In the LINK step, the linker reads the object file, called hello.obj, as
input and creates the executable file, called hello.exe. Here is the command:
C:\> tlink/3/m/v hello
The /3 option allows the use of 32-bit registers, the /m option tells the linker to create a map
file, and the /v option includes debugging information in the executable program. Be sure to
use these options when assembling and linking programs shown in this book.
Running the Program. You can run an assembly language program from the MS-DOS
command prompt by just typing its name:
C:\> hello
You will probably want use a debugger to test a newly written program. For example, we can
run the sample.exe program in Borlands Turbo Debugger with the following command:
C:\> td hello
For example, the following command assembles and links hello.asm (with CodeView
debugging information), producing hello.obj and hello.exe:
ml/Zi hello.asm
The following assembles and links hello.asm, producing a listing file called hello.lst, as
well as hello.obj and hello.exe:
ml/Fl hello.asm
The following assembles, links, and produces a map file called hello.map during the link
step. It still produces hello.obj and hello.exe:
ml/Fm hello.asm
3.4 DATA ALLOCATION DIRECTIVES 63
The following produces an object file, listing file, map file, executable file, and
includes debugging information. The line following it runs the CodeView debugger:
ml/Zi/Fm/Fl hello.asm
cv hello
Microsoft also supplies the masm.exe program to remain compatible with programs
written under older versions of the assembler. The MASM commands to assemble and link a
program called sample are the following:
masm/l/n/z sample;
link/m/co sample;
If the first letter is at offset 0, the next one is at offset 1, the next at 0001 B
2, and so on. The offset of aList is equal to 0, the offset of the first 0002 C
letter. 0003 D
We use data allocation directives to allocate storage, based
on several following predefined types. (In this chapter we will discuss the DB, DW, and
DD directives and leave the others for later chapters):
A variables initial contents may be left undefined by using a question mark for the initializer:
myval db ?
Multiple Initializers. Sometimes the name of a variable identifies the beginning of a sequence
of bytes. In that case, multiple initializers can be used in the same declaration. In the follow-
ing example, assume that list is stored at offset 0000. This means that 10 is stored at offset
0000, 20 at offset 0001, 30 at offset 0002, and 40 at offset 0003:
list db 10,20,30,40
Characters and integers are one and the same as far as the assembler is concerned. The
following variables contain exactly the same value and can be processed the same way:
char db A ; a character (ASCII 41h)
hex db 41h ; hexadecimal
dec db 65 ; decimal
bin db 01000001b ; binary
oct db 101q ; octal
Each initializer can use a different radix when a list of items is defined, and numeric,
character, and string constants can be freely mixed. When a hexadecimal number begins with
a letter (A-F), a leading zero is added to prevent the assembler from interpreting it as a label.
In this example, list1 and list2 have the same contents:
list1 db 10, 32, 41h, 00100010b
list2 db 0Ah, 20h, A, 22h
3.4 DATA ALLOCATION DIRECTIVES 65
Representing Strings. A string can be identified by a variable, which marks the offset of
the beginning of the string. There is no universal storage format for strings, although
null-terminated strings used by the C language are used when calling Microsoft Win-
dows functions. The following shows a null-terminated string called CString, and
another called PString that has its length encoded in the first byte:
Cstring db Good afternoon,0
Pstring db 14, Good afternoon
The DB directive is ideal for allocating strings of any length. The string can continue on
multiple lines without the necessity of supplying a label for each line. The following is a null-
terminated string:
LongString db This is a long string, that
db clearly is going to take
db several lines to store,0
The assembler can automatically calculate the storage used by any variable by subtract-
ing its starting offset from the next offset following the variable. The $ operator returns the
current location counter, so we can use it an expression such as the following:
(offset)
0000 mystring db This is a string
0010 mystring_len = ($ mystring)
The DUP operator can also be nested. The first example that follows creates storage
containing 000XX000XX000XX000XX. The second example creates a two-dimensional
word table of 3 rows and 4 columns:
aTable db 4 dup( 3 dup(0), 2 dup(X) )
aMatrix dw 3 dup( 4 dup(0) )
66 CHAPTER 3: ASSEMBLY LANGUAGE FUNDAMENTALS
Each initializer is equivalent to an unsigned integer between 0 and 65,535 (FFFFh). If initval
is signed, the acceptable range is 32,768 (8000h) to +32,767 (7FFFh). A character constant
can be stored in the lower half of a word. One can also leave the variable uninitialized by
using the ? operator. Here are some examples:
dw 0,65535 ; smallest/largest unsigned values
dw -32768,+32767 ; smallest/largest signed values
dw 256 * 2 ; calculated expression (512)
dw 1000h,4096,AB,0 ; mutiple initializers
dw ? ; uninitialized
dw 5 dup(1000h) ; 5 words, each equal to 1000h
dw 5 dup(?) ; 5 words, uninitialized
Pointer. The offset of a variable or subroutine can be stored in another variable, called a
pointer. In the next example, the assembler initializes P to the offset of list:
list dw 256,257,258,259 ; define 4 words
P dw list ; P points to list
Reversed Storage Format. The assembler reverses the bytes in a word value when storing it in
memory; the lowest byte occurs at the lowest address. When the variable is moved to a 16-bit
register, the CPU re-reverses the bytes. For example, the value 1234h would be stored in
memory as follows:
Offset: 00 01
Value: 34 12
The bytes in a doubleword are stored in reverse order, so the least significant digits are
stored at the lowest offset. For instance, the value 12345678h would be stored as:
3.5 SYMBOLIC CONSTANTS 67
Offset: 00 01 02 03
Value: 78 56 34 12
.386
maxLong = 7FFFFFFFh ; Maximum 32-bit signed value
minLong = 80000000h ; Minimum 32-bit signed value
maxULong = 0FFFFFFFFh ; Maximum 32-bit unsigned value
A symbol defined with the equal-sign directive can be redefined any number of
times. In Example 2, count changes value several times. On the right side of the example,
we see how the assembler evaluates the constant:
68 CHAPTER 3: ASSEMBLY LANGUAGE FUNDAMENTALS
S tatem en t A s s e m b le d A s
count = 5
count = 10
count = 2000
E x am ple Ty pe o f Value
In this syntax, text is any sequence of characters enclosed in angle brackets <...>,
textmacro is a previously defined text macro, and constExpr is an expression that evaluates to
text. Text macros can appear anywhere in a programs source code. A symbol defined with
TEXTEQU can be redefined later in the program.
A symbolic name can be assigned to a string, allowing the name to be replaced by the
string wherever it is found. For example, the prompt1 variable references the continueMsg
text macro:
continueMsg textequ <Do you wish to continue (Y/N)?>
.data
prompt1 db continueMsg
An alias, which is a name representing another predefined symbol, can be created. For
example:
;Symbol declarations:
move textequ <mov>
address textequ <offset>
;Original code:
move bx,address value1
move al,20
;Assembled as:
mov bx,offset value1
mov al,20
In the following example, TEXTEQU is used to define a pointer (p1) to a string. Later,
p1 is assigned a literal containing 0:
.data
myString db A string,0
.code
p1 textequ <offset myString>
mov bx,p1 ; bx = offset myString
p1 textequ <0>
mov si,p1 ; si = 0
70 CHAPTER 3: ASSEMBLY LANGUAGE FUNDAMENTALS
In these formats, reg can be any non-segment register, except that IP cannot be a target
operand. The sizes of both operands must be the same. A 16-bit register must be moved to a
16-bit memory location, for example.
Where segment registers are concerned, the following types of moves are possible, with
the exception that CS cannot be a target operand:
mov segreg,reg16
mov segreg,mem16
mov reg16,segreg
mov mem16,segreg
Notably missing from the MOV instruction is the ability to use two memory operands1.
Instead, you must use a register when copying a byte, word, or doubleword from one memory
location to another. The following instructions, for example, copy a word from var1 to var2:
mov ax,var1
mov var2,ax
Examples of MOV with all three types of operands are shown here:
.data
count db 10
total dw 4126h
bigVal dd 12345678h
.code
mov al,bl ; 8bit register to register
mov bl,count ; 8bit memory to register
mov count,26 ; 8bit immediate to memory
mov bl,1 ; 8bit immediate to register
3.6 DATA TRANSFER INSTRUCTIONS 71
Type Checking. When a variable is created using DB, DW, DD, or any of the other data
definition directives, the assembler gives it a default attribute (byte, word, doubleword) based
on its size. This type is checked when you refer to the variable, and an error results if the
types do not match. For example, the following MOV instruction is invalid because count has
a word attribute and AL is a byte:
.data
count dw 20h
.code
mov al,count ; error: operand sizes must match
Type checking, while sometimes inconvenient, helps you avoid logic errors. Even when
a smaller value fits into a larger one, a type mismatch error is flagged by the assembler:
.data
byteval db 1
.code
mov ax,byteval ; errror
If necessary, you can use the LABEL directive to create a new name with a different
attribute at the same offset. The same data can now be accessed using either name:
.data
countB label byte ; byte attribute
countW dw 20h ; word attribute
.code
mov al,countB ; retrieve low byte of count
mov cx,countW ; retrieve all of count
arrayB db 10h,20h
arrayW dw 100h,200h
arrayD dd 10000h,20000h
The notation arrayB+1 refers to the location one byte beyond the beginning of arrayB,
and arrayW+2 refers to the location two bytes from the beginning of arrayW. You can code
operands in MOV instructions that use this notation to move data to and from memory. In the
following example, we show the value of AL after each move has taken place:
mov al,arrayB ; AL = 10h
mov al,arrayB+1 ; AL = 20h
When dealing with an array of 16-bit values, the offset of each array member is two
bytes beyond the previous one:
mov ax,arrayW ; AX = 100h
mov ax,arrayW+2 ; AX = 200h
XCHG is the most efficient way to exchange two operands, because you dont need a
third register or variable to hold a temporary value. Particularly in sorting applications, this
instruction provides a speed advantage. One or both operands can be registers, or a register
can be combined with a memory operand, but two memory operands cannot be used togther.
For example:
xchg ax,bx ; exchange two 16-bit registers
xchg ah,al ; exchange two 8-bit registers
xchg var1,bx ; exchange 16-bit memory operand with BX
xchg eax,ebx ; exchange two 32-bit registers
.model small
.stack 100h
.data
value1 db 0Ah
value2 db 14h
.code
main proc
mov ax,@data ; initialize DS register
mov ds,ax
Destination can be a register or memory operand. All status flags are affected except the
Carry flag. Examples are shown here.
inc al ; increment 8-bit register
dec bx ; decrement 16-bit register
inc eax ; increment 32-bit register
inc membyte ; increment memory operand
dec byte ptr membyte ; increment 8-bit memory operand
dec memword ; decrement memory operand
inc word ptr memword ; increment 16-bit memory operand
In these examples, the BYTE PTR operator identifies an 8-bit operand, and WORD PTR
identifies a 16-bit operand.
Source is unchanged by the operation, and destination is assigned the sum. The sizes of
the operands must match, and no more than one operand can be a memory operand. A
segment register cannot be the destination. All status flags are affected. Examples are as
follows:
add cl,al ; add 8-bit register to register
add eax,edx ; add 32-bit registers
add bx,1000h ; add immediate value to 16-bit register
add var1,ax ; add 16-bit register to memory
add dx,var1 ; add 16-bit memory to register
add var1,10 ; add immediate value to memory
add dword ptr memVal, ecx
The sizes of the two operands must match, and only one can be a memory operand.
Inside the CPU, the source operand is first negated and then added to the destination. For
3.7 ARITHMETIC INSTRUCTIONS 75
example, 4 1 is really 4 + (1). Recall that twos complement notation is used for
negative numbers, so 1 is stored as 11111111:
0 0 0 0 0 1 0 0 ( 4 )
+ 1 1 1 1 1 1 1 1 (1 )
0 0 0 0 0 0 1 1 ( 3 )
Examples of SUB used with various types of operands are shown here:
sub eax,12345h ; subtract 32bit immediate from register
sub cl,al ; subtract 8bit register from register
sub edx,eax ; subtract 32bit register from register
sub bx,1000h ; subtract immediate value from 16bit register
sub var1,ax ; subtract 16bit register from memory
sub dx,var1 ; subtract 16bit memory from register
sub var1,10 ; subtract immediate value from memory
The Zero flag is set when the result of an arithmetic operation equals 0. Note that INC
and DEC affect the Zero flag, but not the Carry flag:
mov bl,4Fh
add bl,0B1h ; BL = 00, ZF = 1, CF = 1
mov ax,0FFFFh
inc ax ; ZF = 1 (CF not affected)
mov ax,0FFh
add al,1 ; AL = 00, CF = 1
This is an 8-bit operation because AL is used. If we want to get the right answer, we must add
1 to AX, making it a 16-bit operation:
mov ax,0FFh
add ax,1 ; AX = 0100, CF = 0
A similar situation occurs when subtracting a larger operand from a smaller one. In the
next example, the Carry flag tells us the result in AL is invalid:
mov al,1
sub al,2 ; AL = FF, CF = 1
Signed Operations. The Overflow flag is set when an addition or subtraction operation
generates a out-of-range signed value. You may recall that signed 8-bit numbers can range
from 128 to +127, and 16-bit numbers can range from 32,768 to +32,767. If we exceed
these ranges (as in the following examples), the Overflow flag is set and the signed results are
invalid:
Example 1:
mov al,+126 01111110
add al,2 + 00000010
10000000 AL = 80h, OF = 1
Example 2:
mov al,128 10000000
sub al,2 00000010
01111110 AL = 7Eh, OF = 1
Some terms used in the table must be explained: A displacement is either a number
or the offset of a variable. The effective address of an operand refers to the offset
(distance) of the data from the beginning of its segment. Each operand type in Table 3
refers to the contents of memory at an effective address. The addressing mode used by
an instruction refers to the type of memory operand in use. For example, the following
instruction uses the register indirect addressing mode:
mov ax,[si]
list[bx]
[list + bx] EA is the sum of a base or index
indexed
list[di] register and a displacement.
[si+2]
[bx+di]
EA is the sum of a base register and
base-indexed [bx][di]
[bp-di]
an index register.
[bx+si+2]
base-indexed with EA is the sum of a base register, an
list[bx+si]
displacement list[bx][si]
index register, and a displacement.
78 CHAPTER 3: ASSEMBLY LANGUAGE FUNDAMENTALS
OFFSET Operator. The OFFSET operator returns the 16-bit offset of a variable. The assem-
bler automatically calculates every variables offset as a program is being assembled. In the
following example, if the variable aWord is located at offset 0000, the MOV statement moves
0 to BX:
.data
aWord dw 1234h
.code
mov bx,offset aWord ; BX = 0000
.data
array db 0Ah,0Bh,0Ch,0Dh
.code
mov al,array ; AL = 0Ah
mov bl,array+1 ; BL = 0Bh
mov cl,array+2 ; CL = 0Ch
mov dl,array+3 ; DL = 0Dh
You can also subtract from a labels offset. In the following example, the label endlist is
one byte beyond the last byte in list. To move the last byte in list to AL, we write:
.data
list db 1,2,3,4,5
endlist label byte
.code
mov al,endlist-1 ; move 5 to AL
In a list of 16-bit numbers, add 2 to a numbers offset to get the offset of the next
element. This is done in the following example:
.data
wvals dw 1000h,2000h,3000h,4000h
.code
mov ax,wvals ; AX = 1000h
mov bx,wvals+2 ; BX = 2000h
mov cx,wvals+4 ; CX = 3000h
mov dx,wvals+6 ; DX = 4000h
1. Show three examples of assembly language instructions: one with no operands, one with
a single operand, and one with two operands.
2. Write an example of an assembly language mnemonic.
3. Explain what a disassembler utility does.
4. Can a comment be placed on the same line as an instruction? (y/n)
5. Name three types of objects that can be represented by operands.
6. Name at least two popular debuggers used with assemblers sold today.
7. Write a series of instructions that move the values 1, 2 and 3 to the AX, BX, and CX
registers.
8. Write an instruction that adds the number in the BX register to the CX register.
80 CHAPTER 3: ASSEMBLY LANGUAGE FUNDAMENTALS
10. Addresses are shown in Debug as a combination of two numbers, called the segment and the
_________.
11. Show the storage of memory bytes for the 16-bit value 0A6Bh.
12. Show several examples of integer constants.
13. Can a symbolic constant contain an arithmetic expression? (y/n)
14. Show an example of assigning a numeric constant to a symbol, using the = operator.
15. Which radix character is used for hexadecimal constants?
16. Create several examples of string constants, including one that contains embedded
quotes.
17. Name the four basic parts of assembly language statements.
18. Show how a source program statement can be divided between two lines.
19. Can multiple statements appear on the same line? (y/n)
20. In assembly language, how is a directive different from an instruction?
21. Name the six general types of memory operands.
22. Which special characters can appear in identifier names?
23. Would the following be a valid identifier name? first$try
24. Show several examples of labels.
25. How are labels used in programs?
26. What are segments in an assembly language program?
27. What is the diffference between the .stack and .code directives?
28. Write a statement that copies the location of the data segment into the DS register.
29. If any of the following MOV statements are illegal, explain why:
a. mov ax,bx
b. mov var2,al
c. mov ax,bl
d. mov bh,4A6Fh
e. mov dx,3
3.9 REVIEW QUESTIONS 81
f. mov var1,bx
g. mov al,var3
h. mov cs,0
i. mov ip,ax
j. mov var1,var2
k. mov ds,1000h
l. mov ds,es
.data
var1 dw 0
var2 dw 6
var3 db 5
30. The three basic types of operands are register, memory, and ______________.
31. Is the address of each operand relative to the start of the program calculated at assembly time
or at link time?
32. Which directive marks the end of a procedure?
33. What is the significance of the label used with the END directive?
34. Identify the types of operands (register, immediate, direct, or indirect) used in each of the
following instructions:
a. mov al,20
b. add cx,wordval
c. mov bx,offset count
d. add dl,[bx]
35. Mark and correct any syntax errors in the following listing:
.data
blist db 1,2,3,4,5
wlist dw 6,7,8,9,0Ah
.code
mov al,blist
add al,wlist+1
mov bx,offset blist
mov cx,wlist
mov dx,cx
inc word ptr dx
dec ax
82 CHAPTER 3: ASSEMBLY LANGUAGE FUNDAMENTALS
37. Write a data definition statement for a list of 8-bit memory operands containing the following
values:
3, 15h, 0F6h, 11010000b
38. Write a data declaration directive for a sequence of 500 16-bit words, each containing the
value 1000h.
39. An operand in an instruction can be a memory variable, a register, or
____________________ .
40. Which of the following registers cannot be used as destination operands?
AX, CL, IP, DX, CS, BH, SS, SP, BP
41. What will be the hexadecimal value of the destination operand after each of the statements in
Table 4 has executed? (If any instruction is illegal, write the word ILLEGAL as the answer.)
var1 and var2 are 16-bit operands, and count is 8 bits long. All numbers are in hexadecimal.
42. Write a data definition for the variable arrayptr that contains the offset address of the
variable intarray.
43. What will be the hexadecimal value of the destination operand after each of the state-
ments in Table 5 has executed? You may assume that var1 is a word variable and that
count and var2 are byte variables. If any instruction is illegal, write the word ILLEGAL
as the answer:
44. What will AX equal after the following instructions have executed?
.code
mov ax,array1
inc ax
add ah,1
sub ax,array1
.data
array1 dw 10h,20h
array2 dw 30h,40h
45. As each of the following instructions is executed, fill in the hexadecimal value of the
operand listed on the right side:
.code
mov ax,array1 ; AX =
xchg array2,ax ; AX =
dec ax
d. inc bl BX = FFFF BX =
f. dec cx CX = 0000 CX =
.data
array1 dw 20h,10h
array2 dw 30h,40h
1. Program Trace
Code a program containing the following list of instructions. Where marked, write down
the anticipated values of the Carry, Sign, Zero, and Overflow flags before you actually
run the program:
mov ax,1234h
mov bx,ax
mov cx,ax
add ch,al ; CF = , SF = ,ZF = , OF =
add bl,ah ; CF = , SF = ,ZF = , OF =
add ax,0FFFFh ; CF = , SF = ,ZF = , OF =
dec bx ; CF = , SF = ,ZF = , OF =
inc ax ; CF = , SF = ,ZF = , OF =
Also, before running the program, write down what you think AX, BX, CX, and DX will
contain at the end of the program. Finally, run and trace the program with a debugger. Verify
the register and flag values that you wrote down before running the program.
Write instructions to load each number into DL and display it on the console. (The
following instructions display the byte in DL on the console:)
mov ah,2
int 21h
3.10 PROGRAMMING EXERCISES 85
3. Arithmetic Sums
Write a program that finds the sum of three 8-bit values and places the sum in another
variable. Use the following data definitions. Use direct-offset addressing:
ThreeBytes db 10h, 20h, 30h
TheSum db ?
4. Uppercase Conversion
Write a program that converts a string containing up to 256 lowercase characters to upper-
case. (A lowercase character can be converted to uppercase by subtracting 32 from its ASCII
code.)
7. Fibonacci Numbers
The well-known Fibonacci number series, reputedly discovered by Leonardo of Pisa around
the year 1200, has been valued for centuries for its universal qualities by artists, mathemati-
cians, and composers. Each number in the series after the number 1 is the sum of the two
previous numbers:
1, 1, 2, 3, 5, 8, 13 ,21, 34, 55 . . .
Write a program that generates and displays the first 24 numbers in the Fibonacci series,
beginning with 1 and ending with 46,368.
End Notes:
1
There is a specialized type of memory-to-memory move instruction called MOVS,
which is often used when moving large blocks of data. See Chapter 10 for details.