You are on page 1of 18

INTRODUCTION TO PROGRAMMING THE 8086

SAMPLE HELLO WORLD PROGRAM


The following example shows a program that displays the traditional Hello, world! message on the
screen. It contains the essential ingredients of an assembly language application.
TITLE Program Hello World by Andrew H. Andersen, Jr.
PAGE 60,132
;
;
;
;

Written Andrew H. Andersen, Jr.


Brookdale Community College
ELEC 242
Assignment x
.MODEL SMALL

Setup a Stack
.STACK 2000H

;Define values for predefined data


.DATA
prnt equ
9
done equ
4c00h
msg db
Hello world
db
0Dh,0Ah,0Ah,$
;
We could also reserve storage for use
;
under program control
;
;

This is where we state what we want done


We begin with a Main Procedure declaration
.CODE
.startup

Now we should load the Data Segment register


mov ax,@data
mov ds,ax

;
;

This program uses an MS/DOS BIOS function


to send a message to the screen
mov
lea
int
;
;

ah,prnt
dx,msg
21h

;or mov

dx,offset msg

The following 2 statements return control


back to DOS since we are finished

fini: mov ax,done


int 21h
.exit
end

Page 1

INTRODUCTION TO PROGRAMMING THE 8086


Here is a brief description of the important lines in the program:
Line 1 contains the Title directive; all remaining characters on the line are treated as comments
as are all characters on line 4. The source code for this program was written in assembly
language and must be assembled into machine language before it can run. This program is
compatible with both the Microsoft and Borland assemblers.
Segments are the building blocks of programs: The code segment is where program instructions
are stored; the data segment contains all variables, and the stack segment contains the programs
runtime stack. The stack is a special area of memory that the program uses when calling and
returning from subroutines.
The .model small directive indicates that the program uses a maximum of 64K of memory for
code, and 64K of memory for data.
The .stack directive sets aside 2000h (8192) bytes of stack space for the program.
The .data directive indicates the beginning of the data segment where variables are stored. In the
declaration of message, the assembler allocates a block of memory to hold the string containing
Hello, world!, along with two bytes containing a ASCII sequence in MS/DOS for the newline
character sequence (0Dh for Carriage Return and 0Ah for LineFeed).
The $ is a required string terminator character for the MS/DOS Function 9 console output routine
being used.
The .code directive indicates the beginning of the code segment. This is where the executable
instructions are located.
.startup is an MASM directive that identifies the starting point of the program.
The first two statements in the code segment are used to initialize the address of the data segment
into the DS register.
The next two statements in the code segment initialize two register for the MS/DOS Print
Function. The entry requirements are
We must load the address of a string into the DX register. DX is used as an address pointer
and required by the routine.
The MS/DOS BIOS function number is placed in the AH register.
INT 21H causes DOS to execute the function
The last two executable statements (beginning with the label fini) is the normal MS/DOS process
end statement. This causes the program to halt and return control to the operating system.
.exit is the MASM directive, which is usually near the end directive.
The last line of the program contains the end directive. This is the last line of the program to be
assembled. Anything placed in an asm file after the end directive will be ignored by the
assembler.
After creating the Hello World source code program with a text editor, we would save it with the name
HELLO.ASM. We would then invoke the assembler with the command:
ml /Fl hello.asm
The assembler would create an HELLO.OBJ, HELLO.LST, and HELLO.EXE. Entering the command
HELLO at the MS/DOS prompt would cause the program to execute and display the message on the
CRT. Here are the contents of HELLO.LST

Page 2

INTRODUCTION TO PROGRAMMING THE 8086


Microsoft (R) Macro Assembler Version 6.14.8444
Program Hello World by Andrew H. Andersen, Jr.

05/29/00 08:36:36
Page 1 - 1

TITLE Program Hello World by Andrew H. Andersen, Jr.


PAGE 60,132
;
;
;
;

Written Andrew H. Andersen, Jr.


Brookdale Community College
COMP 126 01
Assignment x
.MODEL SMALL

;Define values for predefined data


.DATA

0000
= 0009
= 4C00
0000 48 65 6C 6C 6F 20
77 6F 72 6C 64
000B 0D 0A 0A 24

prnt equ
done equ
msg db
db

001C
001E
0022

0Dh,0Ah,0Ah,$

We could also reserve storage for use


under program control

;
;

This is where we state what we want done


We begin with a Main Procedure declaration
.CODE
.startup

Now we should load the Data Segment register


mov ax,@data
mov ds,ax

;
;

This program uses an MS/DOS BIOS function


to send a message to the screen

B8 ---- R
8E D8

B4 09
8D 16 0000 R
CD 21

mov
lea
int
;
;

0024
0027

9
4c00h
Hello world

;
;

0000

0017
001A

Setup a Stack
.STACK 2000H

B8 4C00
CD 21

ah,prnt
dx,msg
21h

;or mov

dx,offset msg

The following 2 statements return control


back to DOS since we are finished
fini: mov ax,done
int 21h
.exit
end

Page 3

INTRODUCTION TO PROGRAMMING THE 8086


Microsoft (R) Macro Assembler Version 6.14.8444
Program Hello World by Andrew H. Andersen, Jr.

09/16/00 11:49:32
Symbols 2 - 1

Segments and Groups:


N a m e

Size

Length

DGROUP . . . . . . . . . . . . .
GROUP
_DATA . . . . . . . . . . . . .
16 Bit
STACK . . . . . . . . . . . . .
16 Bit
_TEXT . . . . . . . . . . . . .
16 Bit
Microsoft (R) Macro Assembler Version 6.14.8444
Program Hello World by Andrew H. Andersen, Jr.

000F
2000
002D

Align

Combine Class

Word Public DATA


Para Stack STACK
Word Public CODE
09/16/00 11:49:32
Symbols 3 - 1

Symbols:
N a m e
@CodeSize
@DataSize
@Interface
@Model . .
@Startup .
@code . .
@data . .
@fardata?
@fardata .
@stack . .
done . . .
fini . . .
msg . . .
prnt . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

Type
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

Number
Number
Number
Number
L Near
Text
Text
Text
Text
Text
Number
L Near
Byte
0000
Number

Value

Attr

0000h
0000h
0000h
0002h
0000
_TEXT
_TEXT
DGROUP
FAR_BSS
FAR_DATA
DGROUP
4C00h
0024
_TEXT
_DATA
0009h

0 Warnings
0 Errors

In C, the Hello World program source code is much smaller, and might be like the following:
/*

Hello World Program


Written by Andrew H. Andersen, Jr.

#include
#include
char

*/

<stdio.h>
<string.h>

msg[] = Hello world;

main()
{
printf(%s\n\n,msg);
return 0
}

This program would be called HELLO.C After compiling we will have an object file.
Although the source program length is shorter in C, the executable program created by a C compiler
may be over 12 times larger than the assembler version (over 8000 bytes vs. less than 600 bytes)

Page 4

INTRODUCTION TO PROGRAMMING THE 8086


WRITING ASSEMBLY LANGUAGE PROGRAMS
We are all aware that the English Language has specific rules that must be observed. Assembly
language statements also have rules, which must be observed if we wish to have our program
assembled. The source line in an assembly language statement is analogous to a sentence.
The assembler recognizes three types of source lines: instructions, directives, and control. The
assembly language instruction and assembler directives may consist of up to four fields as follows:
NAME: OPCODE OPERAND
;COMMENT
Any number of blanks may separate the fields, but they must be separated by at least one delimiter.
Each statement must appear on a single line, and is terminated with a .
The maximum length of an assembly language statement is 128 characters. The characters that may be
used in assembly language source statements are the letters of the alphabet, and the digits 0 through 9.
Most of the other printable characters may be used, although some of these characters are reserved. In
addition, any ASCII character may appear in a data string enclosed in a single quote. Both upper and
lower case alphabetical characters may be used, and most assemblers treat uppercase and lowercase
characters as the same.
For instance Val and val are treated as the same label or name.
When a program displays data strings enclosed in single quotes, they are printed exactly as they
appear.
Certain characters have special meaning to the assembler, and these characters are called Delimiters.
The delimiter defines the end of a source code statement, a field, or a component of a field. There are
some delimiters that are reserved for use with Macros.
DELIMITERS
CHARACTER
blank

( )

HT
;
:

MEANING
1 or more blanks
single quotes
parentheses
RETURN
TAB
semicolon
colon

USE
field separator or terminator field
enclose a data string
delimit an expression
statement terminator
field separator or symbol terminator
indicate start of a comment
delimiter for labels

NAME FIELD
The name is optional, and for some assemblers a colon must follow the label in the Code segment. A
label is a symbolic name used to refer to a memory address or value. The label may use any
alphanumeric character, and the first character of a label should be alphabetical. The student should use
labels of six characters or less excluding the colon. This is primarily to do with spacing of lines and
characters when printing the lst file. There are restrictions for label names. A label should not be the
same as a mnemonic. We may not use the label SUB for a subroutine label since SUB is the assembly
language mnemonic for subtract, but we could use the label SUB1. If we use a mnemonic or a single
character that is the same as a register, or any reserved characters, the Assembler will flag the
statement, and print a error message. If the assembler encounters a semicolon in the beginning of the
label field, it treats the entire line as a comment.
Page 5

INTRODUCTION TO PROGRAMMING THE 8086


OPCODE FIELD
The opcode field must always contain a valid mnemonic or assembler directive. If it does not, the
assembler will flag the statement and print an error message. All operands and assembler directives
should begin at least one tab space from the left margin.
OPERAND FIELD
The operand field may contain a register name, data, or a label. If there is more than one operand
required by the mnemonic, it must be separated by a comma. If the operand is data, it may be in binary,
octal, decimal, hex, or ASCII. The numeric data type may be upper case or lower case.
Binary data must be entered with no spaces, has a maximum of 8, 16, or 32 bits depending on
the opcode, and a B as the last character, such as 011001B.
Octal data must be entered as a valid octal number up to 377Q for 8bit data or 177777Q for
16bit data with no spaces depending on the opcode, and a Q as the character, such as 175Q.
Decimal data is entered as a number up to 255 for 8bit, 65,535 for 16bit, or 4,294,967,296
for 32-bit unsigned data depending on the opcode. It may have no base designation or a D as
the last digit of the number such a 37 or 37D.
Hexadecimal data is entered as any valid hex number up to 0FFH for 8bit, 0 FFFFH for
16bit, or 0 FFFF FFFFH for 32-bit data depending on the opcode. It must have a number for
the first digit and an H as the last digit of the number.
When ASCII data is used in an operand, it must be enclosed in quotes.
Whenever the $ is present in the operand field, it means the current address.
In addition to specifying the number base in use, a valid operand could be a label with arithmetic or
logical functions as part of the operand.
OPERAND ARITHMETIC OPERATIONS
OPERATION
+

*
/
NOT
AND
OR
XOR

EXAMPLE
LABEL+2
LABEL1
TOP*3
SIX/2
NOT TRUE
WQ AND SE
WQ OR SE
WQ XOR SE

EXPLANATION
Address of LABEL + 2 bytes
Address 1 byte before LABEL
Equates to the value TOP times 3
Equates to the value six divided by 2 or 3
the 1s complement of TRUE
returns the value of label WQ AND SE
returns the value of label WQ OR SE
returns the value of label WQ XOR SE

COMMENT FIELD
The comment field must begin with a semicolon and may continue only until the end of the line. If it
must continue on the next line, that line must begin with a semicolon. In the comments field the
programmer should explain what events are taking place with that instruction or group of instructions.
On line documentation is essential to enable the programmer or another individuals to determine what
is happening. No programs will be accepted without proper documentation.

Page 6

INTRODUCTION TO PROGRAMMING THE 8086


ASSEMBLER PSEUDO OPERATIONS
A pseudo op is an assembler directive, and is located in the opcode field. Pseudo ops give instructions
to the Assembler, and it may or may not generate machine code. Labels may be used to identify pseudo
ops and most require operands.
DATA ALLOCATION DIRECTIVES
A variable is a symbolic name for a location in memory where some data are stored. A variables
offset is the distance from the beginning of the segment to the variable. A variables name is
automatically associated with its offset. An array is a group of sequential memory locations used for
storage and whose address is represented by a symbolic name. The first element of the array is at the
base address. Other elements of the array are accessed by adding an offset (the number of memory
locations) to the base address. For example, if we declare an array containing four characters, the name
aList identifies only the offset of the first character (A):
.data
mystring db This is a string
mystring is a label or name. The purpose of the label is to associate a memory location in the data
segment with user assigned name. This makes it easy for the programmer to access the data stored
here.
The DB directive instructs the assembler to reserve storage for data on a byte boundary.
T is the first letter of the string, and is placed in the base address of mystring.
The h is offset +1 or one byte after the T (the address of this memory location is mystring +1 byte).
The character i is located at mystring+2 (the address of mystring plus two bytes), and so on for all
characters in the string.
The address of mystring is based on its location in the program.
Address
Contents
mystring
54h
mystring+1
68h
mystring+2
69h
mystring+3
73h
mystring+4
20h
And so on. In the table above, the numeric data is the hex value for the ASCII character. 20h is the
ASCII character for a space.
We use the following MASM data allocation directives to reserve storage on multiple byte boundaries.
Different assemblers may us slightly different assembler directives. You should check the
documentation for the proper declaration syntax. For MASM:
Assember Directive
Description
Size
Define byte
1 byte
DB
Define word
2 bytes
DW
Define doubleword
4 bytes
DD
Define
quadword
8 bytes
DQ
Define tenbytes
10 bytes
DT

Page 7

INTRODUCTION TO PROGRAMMING THE 8086

DB

The Define Byte directive is used to define memory storage of data on an 8bit
boundary. Labels are optional, but an operand is required. Multiple operand values
may be entered in any acceptable format (numeric can be in binary, octal, decimal,
or hex) and is separated by commas. Strings are enclosed in quotes.
Unsigned integer values are in the range of 0 to 255
The following are examples of the DB directive:

VALUE
VAL2
BINUM
MSG

DB
DB
DB
DB

100
10H
01100111B
HELLO

;DEFINE VALUE AS 100.


;DEFINE VAL2 AS 10 IN HEX.
;DEFINE BINUM AS BINARY VALUE.
;FIVE BYTE ASCII MESSAGE.

NUM

DB

1,2,3,4

INIT

DB

;DEFINE NUM AS THE FOUR BYTES


;1, 2, 3, AND 4 IN DECIMAL.
;INITIAL VALUE UNASSIGNED

DUP

The DUP operator, which is placed in the operand field, allows you to initialize
storage to one or more multiple values. The DUP operator used with the DB
directive is:

NUM1

DB 80 DUP (20h)

;INITIALIZES 80 BYTES OF STORAGE TO


;20H, the ASCII value for a space
DB 5 DUP (No) ;DEFINE VAL2 AS NoNoNoNoNo

VAL2
DW

The Define Word directive is similar to the Define Byte, except that it is used to
define 16bit data (A word) instead of 8bit data. The syntax of the DW directive
is similar to DB except that it stores the defined data on a word boundary.
It is used to represent unsigned Integer values (0 to 65 535)
The DW format is:

NUM1
NUM2
CAL1
BLANK
BLANK

DW
DW
DW
DW
DW

13H
;DEFINE NUM1 AS THE VALUE 0013H
1000
;DEFINE NUM2 AS THE VALUE 1000
256 * 2
;ASSIGN THE VALUE 512 TO CAL1
80 DUP (?) ;RESERVE 80 WORDS UNINITIALIZED
80 DUP (20H) ;RESERVE 80 WORDS OF SPACES (0020H)

The Define DoubleWord directive is similar to DB and DW, except that it is used
to define 32bit data (A double word). The syntax of the DD directive is similar
to DB except that it stores the defined data on a double word boundary.
It is used to represent unsigned Integer values (0 to 4 294 967 295)
The DW format is:
NUM1
DD
13H
;DEFINE NUM1 AS THE VALUE 0000 0013H

DD

The Define QuadWord directive is similar to DB, except that it is used to define
64bit data.
Unsigned integer values range from 0 to 264 1 (~1.8e19)
The DW format is:
NUM1
DQ 13H
;DEFINE NUM1 AS 0000 0000 0000 0013H
DQ

Page 8

INTRODUCTION TO PROGRAMMING THE 8086


Equates Directive
EQU The EQU directive is used to equate a symbolic name (or label) to another label
or a value. You should make liberal use of labels and equate statements since
they make the program easier to understand. Although the EQU statement may
appear anywhere in a program, it is a good technique to place all the equate
statements together in the DATA area. An example of the equate statement is:
SIX
COUNT
NUM
VAL2
VAL8

EQU
EQU
EQU
EQU
EQU

6
25
100H
SIX
SIX+2

Equal-Sign Directive
This is similar to the EQU, but is used as a redefinable equates. The value
=
associated with the = may be reassigned during assembly. Like the EQU
directive, it cannot change during program execution/
Examples are:
count = 25
.386
maxLongInt = 7FFF FFFFh (+2 147 486 647)
minLongInt = 8000 0000h (-2 147 486 648)
maxUnsignLongInt = 0 FFFF FFFFh (4 294 967 295)
The ORG directive is used to change the current address of a program to another
address. It should be used in the beginning of the program, and is usually the last
statement in the Equates Area. The addresses below 03FFH (4 groups of 256) are
used to store the RESET and RESTART (vectored interrupt) and user defined
vectored interrupt addresses. The programmer or operating system will usually
load these addresses but they are not used to store source code. The ORG
statement may be used at any point in the program, and may be used more than
once.
It could be used to define a hex lookup table for printing the ASCII value of
single hex digits that begins at a specific address.
.DATA
ORG 1000H
HEXTBL
DB
01234
DB
56789
DB
ABCDE
DB
F
ORG

END

The END assembler directive identifies the last line of the source code
program. Only one END statement may appear in a source code program as any
statements after the end statement are ignored by the assembler. The END
statement should be located in the OPCODE field, and labels and operands are
optional when using simplified segment directives.

Page 9

INTRODUCTION TO PROGRAMMING THE 8086


OFFSET Operator
The OFFSET operator returns the offset of a memory location from the beginning of its segment. The
destination operand must be a l6-bit register, as in the following example:
mov si,offset addr ; SI points to addr
SI points to addr because it contains its offset address. When the register contains an address that we
wish to access,, we call it a pointer. This is a technique we will use later when we see how to access
the contents of an array. In the following example, assume that byteSize is the first storage location in
the data segment.
.data
byteSize
db
10h,25h,3h,4Fh
wordSize
dw
1000h,2000h,3000h
.code
mov di, offset byteSize
;DI points to address 0000 with respect to the
;base address of the data segment or DS:0000
mov bx, offset byteSize+1 ;BX points to the memory location byteSize+1 (0001)
;or DS:0001
mov si offset wordSize+2 ;SI points to the memory location DS:0006
PTR Operator
The PTR operator forces an operand to a desired boundary. For instructions where the boundary of an
operand might be ambiguous, the PTR operator can be used to define the operands proper size in
combination with the declared data size. For example, we might see:
mov al,byte ptr Num1
mov si,word ptr Num2
mov eax,dword ptr listPointer
When the size of an operand is not clear from the context of an instruction, you must make sure to use
the PTR directive. Consider the following instruction, which would generate an operand must have
size error message by the assembler:
inc [si]
In the previous instruction, the assembler cannot determine what size data SI is pointing to. By using
the PTR operator, the assembler knows the data size.
inc word ptr [si]
The .MODEL is used to define the type of program being created. It automatically sets the default
attribute for all procedures to either near or far.
No. of Segments
OS
.model
Data
Code
DOS
Features
tiny
1
1
Used for COM only, Data and Code combined
small
1
1
Smallest EXE file
medium
1
Multiple
DOS/
compact Multiple
1
large
Multiple Multiple Windows
huge
Multiple Multiple
Uses normalized addressing
flat
1
1
Windows Uses 32-bit addressing, Data and Code
NT
combined

Page 10

INTRODUCTION TO PROGRAMMING THE 8086


There are two methods to do this with MASM. The Standard Segment Directives, which works with
both older and newer versions of assemblers, and the Simplified Segment Directives, which only
works with MASM 5 and higher.
SEGMENT
ENDS

The 80x86 has different segments for the Stack, Data, and Code. Each of
these three storage areas should be identified.
Defines the end of the Segment. This must occur before the END
directive

STANDARD DIRECTIVE METHOD


ML assembles and links in one command. If you install MASM on your home computer and you wish
to edit and assemble files from your Floppy Disk, open AUTOEXEC.BAT with EDIT in C:\ and add
the following to your PATH statement:
C:\MASM611\BIN
With MASM 6.11 and higher, the ML command assemble and links a .ASM file
ml hello.asm
It produces a .OBJ file and a .EXE file
Option /Fl produces a source listing with an lst extension
Option /Fm produces a map file with a map extension
To produce both of these, type (with spaces) ml /Fl /Fm hello.asm
PROCESSORS
MASM supports a set of directives for selecting processors and coprocessors. Once you select a
processor, you must use only the instruction set for that processor. The default is the 8086 processor.
To enable a different processor modes and the additional instructions available on that processor, use
the directives .186, .286, .386, and .486.
The .286P, .386P, and .486P directives enable the instructions available only at higher privilege levels
in addition to the normal instruction set for the given processor. Generally, you dont need privileged
instructions unless you are writing operating-systems code or device drivers.
STACK Segment
The stack is the section of memory used for pushing or popping registers and storing the return address
when a subroutine is called. The stack often holds temporary and local variables.
If your main module is written in a high-level language, that language handles the details of creating a
stack. Use the .STACK directive only when you write a main module in assembly language.
The .STACK directive creates a stack segment. By default, the assembler allocates 1K of memory for
the stack. This size is sufficient for most small programs.
To create a stack of a size other than the default size, give .STACK a single numeric argument
indicating stack size in bytes:
.STACK 2048
; Setup 2K stack
.STACK 2000h
; Setup 2K stack exactly same as previous

Page 11

INTRODUCTION TO PROGRAMMING THE 8086


DATA Segment
Programs can contain both near and far data. In general, you should place important and frequently
used data in the near data area, where data access is faster. This area can get crowded, however,
because in 16-bit operating systems the total amount of all near data in all modules cannot exceed 64K.
Therefore, you may want to place infrequently used or particularly large data items in a far data
segment.
The .DATA, .DATA?, .CONST, .FARDATA, and .FARDATA? directives create data segments.
You can access the various segments within DGROUP without reloading segment registers (see
Defining Segment Groups, later in this chapter). These five directives also prevent instructions from
appearing in data segments by assuming CS to ERROR.
Near Data Segments
The .DATA directive creates a near data segment. This segment contains the frequently used data for
your program. It can occupy up to 64K in MS-DOS or 512 megabytes under flat model in Windows
NT. It is placed in a special group identified as DGROUP, which is also limited to 64K.
When you use .MODEL, the assembler automatically defines DGROUP for your near data segment.
The segments in DGROUP form near data, which can normally be accessed directly through DS or SS.
Far Data Segments
The compact, large, and huge memory models use far data addresses by default. With these memory
models, however, you can still construct data segments using .DATA, .DATA?, and .CONST. The
effect of these directives does not change from one memory model to the next. They always contribute
segments to the default data area, DGROUP, which has a total limit of 64K.
When you use .FARDATA or .FARDATA? in the small and medium memory models, the assembler
creates far data segments FAR_DATA and FAR_BSS, respectively. You can access variables with:
mov ax, SEG farvar2
mov ds, ax
Code Segment
Whether you are writing a main module or a module to be called from another module, you can have
both near and far code segments. This section explains how to use near and far code segments and how
to use the directives and predefined equates that relate to code segments.
Near Code Segments
The small memory model is often the best choice for assembly programs that are not linked to modules
in other languages, especially if you do not need more than 64K of code. This memory model defaults
to near (two-byte) addresses for code and data, which makes the program run faster and use less
memory.
When you use .MODEL and simplified segment directives, the .CODE directive in your program
instructs the assembler to start a code segment. The next segment directive closes the previous
segment; the END directive at the end of your program closes remaining segments.
You can use the predefined symbol @CodeSize to determine whether code pointers default to

Page 12

INTRODUCTION TO PROGRAMMING THE 8086


Far Code Segments
When you need more than 64K of code, use the medium, large, or huge memory model to create far
segments.
The medium, large, and huge memory models use far code addresses by default. In the larger memory
models, the assembler creates a different code segment for each module. If you use multiple code
segments in the small, compact, or tiny model, the linker combines the .CODE segments for all
modules into one segment.
For far code segments, the assembler names each code segment MODNAME_TEXT, in which
MODNAME is the name of the module. With near code, the assembler names every code segment
_TEXT, causing the linker to concatenate these segments into one. You can override the default name
by providing an argument after .CODE. (For a complete list of segment names generated by MASM,
see Appendix E, Default Segment Names.)
With far code, a single module can contain multiple code segments. The .CODE directive takes an
optional text argument that names the segment. For instance, the following example creates two
distinct code segments, FIRST_TEXT and
SECOND_TEXT.
.CODE FIRST
.
.
; First set of instructions here
.
.CODE SECOND
.
.
; Second set of instructions here
The easiest way to begin and end an MS-DOS program is to use the .STARTUP and .EXIT directives
in the main module. The main module contains the starting point and usually the termination point.
You do not need these directives in a module called by another module.
These directives make MS-DOS programs easy to maintain. They automatically generate code
appropriate to the stack distance specified with .MODEL. However, they do not apply to flat-model
programs written for 32-bit operating systems. Thus, you should not use .STARTUP or .EXIT in
programs written for Windows NT.
To start a program, place the .STARTUP directive where you want execution to begin. Usually, this
location immediately follows the .CODE directive:
.CODE
.STARTUP
.
.
; Place executable code here
.
.EXIT
END
Note that .EXIT generates executable code, while END does not. The END directive informs the
assembler that it has reached the end of the module. All modules must end with the END directive
whether you use simplified or full segments.

Page 13

INTRODUCTION TO PROGRAMMING THE 8086


If you do not use .STARTUP, you must give the starting address as an argument to the END directive.
For example, the following fragment shows how to identify a programs starting instruction with the
label start:
.CODE
start:
.
.
; Place executable code here
.
END start
Only the END directive for the module with the starting instruction should have an argument. When
.STARTUP is present, the assembler ignores any argument to END. Sometimes MASM generates a
warning stating the address of end was ignored. Do not worry about this warning as it is generated
because the .exit and end directives are adjacent.
For the default NEARSTACK attribute, .STARTUP points DS to DGROUP and sets SS:SP relative
to DGROUP, generating the following code:

Page 14

INTRODUCTION TO PROGRAMMING THE 8086


SIMPLIFIED SEGMENT DIRECTIVE METHOD
Title Segment Example TOTAL.ASM by Andrew H. Andersen, Jr.
Page 60,132
;

POINTS
SUM

TOTAL:

ADDUP:

.MODEL SMALL
.DATA
ORG
7000H
DB
16 DUP(?)
DB
?
.CODE
.STARTUP
MOV
AX,7000H
MOV
DS,AX
MOV
AL,0
MOV
BL,16
LEA
SI,POINTS
ADD
AL,[SI]
INC
SI
DEC
BL
JNZ
ADDUP
MOV
SUM,AL
MOV
AH,04CH
INT
21H
.EXIT
END
TOTAL

;save room for 16 data bytes


;save room for result (1 byte)

;load address of data area


;init data segment register
;clear result
;init loop counter
;init data pointer
;add data value to result
;increment data pointer
;decrement loop counter
;jump if counter not zero
;save sum
;Normal MS-DOS progam end
;Using MS-DOS

Microsoft (R) Macro Assembler Version 6.13.7299


05/20/00 08:37:41
Segment Example TOTAL.ASM by Andrew H. Andersen, Jr.
Page 1 - 1
Title Segment Example TOTAL.ASM by Andrew H. Andersen, Jr.
Page 60,132
;
.MODEL SMALL
0000
.DATA
ORG
7000H
7000 0010 [
POINTS DB
16 DUP(?) ;save room for 16 data bytes
00
]
7010 00
SUM
DB
?
;save room for result (1 byte)
0000
.CODE
.STARTUP
0017 B8 7000
TOTAL: MOV
AX,7000H ;load address of data area
001A 8E D8
MOV
DS,AX
;init data segment register
001C B0 00
MOV
AL,0
;clear result
001E B3 10
MOV
BL,16
;init loop counter
0020 8D 36 7000 R
LEA
SI,POINTS ;init data pointer
0024 02 04
ADDUP: ADD
AL,[SI]
;add data value to result
0026 46
INC
SI
;increment data pointer
0027 FE CB
DEC
BL
;decrement loop counter
0029 75 F9
JNZ
ADDUP
;jump if counter not zero
002B A2 7010 R
MOV
SUM,AL
;save sum
002E B4 4C
MOV
AH,04CH
;Normal MS-DOS progam end
0030 CD 21
INT
21H
;Using MS-DOS
.EXIT
END
TOTAL

Page 15

INTRODUCTION TO PROGRAMMING THE 8086


Microsoft (R) Macro Assembler Version 6.13.7299
Segment Example TOTAL.ASM by Andrew H. Andersen, Jr.

05/20/00 08:37:41
Symbols 2 - 1

Segments and Groups:


N a m e
DGROUP . . . . . . . . . . . . .
_DATA . . . . . . . . . . . . .
_TEXT . . . . . . . . . . . . .

Size

Length

Align

Combine Class

GROUP
16 Bit
16 Bit

7011
0036

Word
Word

Public
Public

Microsoft (R) Macro Assembler Version 6.13.7299


Segment Example TOTAL.ASM by Andrew H. Andersen, Jr.

DATA
CODE

05/20/00 08:37:41
Symbols 3 - 1

Symbols:
N a m e
@CodeSize
@DataSize
@Interface
@Model . .
@Startup .
@code . .
@data . .
@fardata?
@fardata .
@stack . .
ADDUP . .
POINTS . .
SUM . . .
TOTAL . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

Type
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

Number
Number
Number
Number
L Near
Text
Text
Text
Text
Text
L Near
Byte
Byte
L Near

Value
0000h
0000h
0000h
0002h
0000
_TEXT
DGROUP
FAR_BSS
FAR_DATA
DGROUP
0024
7000
7010
0017

Attr

_TEXT

_TEXT
_DATA
_DATA
_TEXT

1 Warnings
0 Errors

Both versions of the program accomplish the same task. The second version allows the Assembler to
perform some housekeeping chores for us.
Let us briefly look at a sample line of output in the total.lst file contents and what it represents:
8000

B8 7000

TOTAL:

MOV

AX,7000H

;load address of data area

8000 is the Hex address in memory for this instruction


B8 is the Intel HEX code for MOV AX
7000H is the hex value of the data
TOTAL is the Label field
MOV is the Opcode
AX,7000H is the operand
;load is the comment.
The assembler generated the first three, and the programmer typed the last 4 in the source code file.

Page 16

INTRODUCTION TO PROGRAMMING THE 8086


TITLE Program STANDARD.ASM written by Andrew H. Andersen, Jr.
Page 60,132
;***************************************************
;
;
Program number
;
Program STANDARD.ASM
;
Written by Andrew H. Andersen, Jr.
;
Course - Section
;
;
This program ,
;
;
We use the procedures Clrscr, Gotoxy, Writestring
;
Readint, and Writeint from LIBRARY.LIB
;
;***************************************************
.model small
.stack 1000h
.data
row1
row2
row3
row4
row5

equ
equ
equ
equ
equ

prompt1
prompt2
get1st
get2nd
showans

0516h
0616h
0916h
0a16h
0b20h

db
db
db
db
db

This program adds two decimal numbers,0


that you enter from the keyboard.,0
Enter the 1st number --> ,0
Enter the 2nd number --> ,0
The sum is --> ,0

.code
;
;

Define proc used from library.lib


the \ is continue form previous line
extern Writeint:proc, Writestring:proc, \
Readint:proc, Gotoxy:proc,
.startup

main:

mov
mov

ax,@data
ds,ax

Page 17

INTRODUCTION TO PROGRAMMING THE 8086


;************
;
;
Define what happens here
;
;************
init:

call
call

Clr
SetCur

the rest of main is placed here

fini:

mov
int

ah,04ch ;standard MS/DOS Process End


21h

ALL PROCEDURES ARE HERE

Clear the screen using MS/DOS Video BIOS

Clr
;
;

proc
Clear Screen with 25 line scroll.
The screen is blue and the text is yellow

Clr

mov
mov
mov
mov
mov
int
endp

ah,
al,
cx,
dx,
bh,
10h

6
0
0
1950h
1eh

;The Video BIOS function


;Scroll # of lines 0 = all
;row/col at top
;row/col at bottom 24 & 79
;foreground/background colors

SetCur
proc
;
Now set Cursor to row 5 column 30 on page 0
mov ah, 2
;The BIOS function
mov dx, 051eh ;row/column position
mov bh, 0
;video page no. 0
int 10h
;using Video BIOS
ret
SetCur
endp
.exit
end

Page 18

You might also like