Your Federal Quarterly Tax Payments are due April 15th Get Help Now >>

Assembly Language Programming A Lab Manual - DOC by xwm19580




       Introduction
       Intel 8086: A brief excursion
       Using DEBUG
       Using the Assembler
       A sample program
       Data Definition
       Interrupts
       Functions
       Macros
       Interfacing


Suggested list of experiments


Note to the T.A / Instructor

Instruction Execution

   Fetch/Decode/Execute cycle is like a program:

      Repeat
        Fetch instruction from primary memory
        Increment Program Counter
        Decode
        Fetch operands from memory (if required)
        Execute instruction
        Write results to memory (if required)
      Until Halt
      How is this "program" written?

       eg. ADD Instruction

           1.   Fetch operand1, store in register X
           2.   Fetch operand2, store in register Y
           3.   Tell ALU to add X and Y
           4.   Put result in ACC

       MICROCODE (see fig. below)

      Lowest level of software
      Flexible: can be updated by designers
      Controls the digital logic of the CPU
      Implements the machine code instructions

   Lowest level of software meets highest level of hardware

   Don't have to use microcode at all .
   Possible for Machine Code instructions to control logic directly (via Control


   Bug fixes are simpler than changing logic
   Complex instructions are best implemented as microcode


   Instruction execution less efficient than "hard-wired" approach


   Each type of CPU has it s own Instruction Set
   The set of instructions that can be decoded and executed
   Each instruction has a number
   Usually written as a "mnemonic"

    8086 instruction set (79 basic instructions)

    AAA          AAD                 AAM              AAS
    ADC          ADD                 AND              CALL
    CBW          CLC                 CLD              CLI
    CMC          CMP                 CMPS             CMPXCHG
    CWD           DAA                DAS              DEC
    DIV          ESC                 HLT              IDIV
    IMUL         IN                  INC              INT
    INTO         IRET/IRETD           Jxx             JCXZ/JECXZ
    JMP          LAHF                LDS              LEA
    LES          LOCK                LODS             LOOP
     MOV         MOVS                LOOPE/LOOPZ      LOOPNZ/LOOPNE
    MUL          NEG                 NOP              NOT
    OR           OUT                 POP              POPF/POPFD
    PUSH         RCL                 RCR              PUSHF/PUSHFD
    REP          REPE/REPZ           RET/RETF          REPNE/REPNZ
    ROL          ROR                  SAHF             SAL/SHL
    SAR          SBB                  SCAS            SHL
    SHR          STC                 STD              STI
    STOS         SUB                 TEST             WAIT/FWAIT
    XCHG         XLAT/XLATB          XOR


   Instructions vary from one CPU to another
   General groupings possible...
   Arithmetic/Logic

    * Add, subtract, AND, OR, shifts
    * Performed by ALU

   Data Movement

    * Load, Store (to/from registers/memory)

   Transfer of Control

    * Jump, Branch, procedure call

   Test/Compare

    * Set condition flags

   Input/Output

    * In, Out

    * Only on some CPU's

   Others

    * Halt, NOP


   Instruction defined by Opcode and Operands
   Decoded by examining bit patterns
   If operands used, must specify addresses

   Zero-address instruction:

   One-address instruction:
                                              Opcode            Address

   Two-address instruction:         Opcode              Address1         Address2

   Instruction Length may be shorter than/ same as / longer than a machine


   Operands may be
       o implicit (eg. stored in accumulator or on stack)
           o    stored in
                     registers
                     primary memory
      Instruction may need to specify addresses of operand(s) and where to put result
      Several ways to interpret address part of instruction (call it addr)


       addr is address field of instruction

      Immediate
       addr is operand
      Register
       addr is number of CPU register
       operand := [ addr ]
      Direct
       addr is address in primary memory
       operand := [ addr ]
      Indirect
       addr is register number (or memory address)
       operand_address := [ addr ]
       operand [ operand_address ]
      Indexed
       addr is base address
       index is a register

       operand := [ addr + [index] ]

Auto-indexing modes allow automatic increment (or decrement) of value in index

       8086 ARCHITECTURE :Hardware Overview

The Registers

In Intel Processors there are several registers, the registers are special memory locations
that are built right into the chip. These registers are used to mess with data in a program.
All registers can and always work with numbers. The range of numbers that can be
loaded into a register is -65535 to +65535, I think, in hex the range is -FFFF to +FFFF
and finally in binary the range is -11111111 to +11111111. In the Intel processor there
are 4 general use registers:

AX - Called the Accumulator, used in math operations.

BX - Called the Base Register?, not used very often.

CX - Called the Count Register, used as a counter in loops.

DX - Called the Data Register, it just holds data.

All these registers can be split into 2 registers that hold a lower range of numbers. The
range for the split registers is: up to 255 decimal, FF in hex, and 1111 binary. Their
names are derived from the register they were split from:

AX: Contains AH and AL.
BX: Contains BH and BL.
CX: Contains CH and CL.
DX: Contains DH and DL.

When a split register is changed, the large register is changed as well. Example below:
Each split register is in fact PART of the original register it came from. So, if AX is
FF56 in hex. Then AL will be FF and AH will be 56. If you change a split register, you
also change that part of the large register.

The Special Registers

There are also 6 other registers in the Intel Processor. These have special uses too.
However, modifying these registers without knowing what you are doing can crash your
program, or your computer. They are called the Segment Registers:

CS - Code Segment, points to the segment of the currently running program code.

ES - Extra Segment, you can use this one!

DS - Data Segment, points to the segment of data to be used with certain operations.

SS - Stack Segment, points to the stack of the running program code.

   For the other two they are NOT Segment Registers and are the most dangerous to mess

BP - Base Pointer, points to the base of the stack.

SP - Stack Pointer, points to the top of the stack.

When a register points to something, that means if read the register will contain the
memory address of what it points to. Also these registers have the same range as the
regular registers, but CANNOT BE SPLIT UP.


The FLAGS are a set of indicators that can have a TRUE (binary 1) or FALSE (binary 0)
value in them. They are modified through the use of set (make 1) and clear (make 0)
operations. They are also modified by any compare operation done. They are used as
error indicators too. They are:

Overflow Flag - Indicates that a number has gone too high to handle.

Carry Flag - Used as an error indicator, or holds the carry from an + or - operation.

Interrupt Flag - Indicates whether or not interrupts are honored or not.
Learn about interrupts later.

Parity Flag - Not used very often, it used to be used to indicate errors but nowadays...

Direction Flag - Used to determine which way text operations work.

Trap Flag - Of no use to us.

Sign Flag - Indicates an above or below after the comarison of numbers.

Zero Flag - Indicates an equal result after a compare operation.

Auxiliary Flag - Of little use to us.
Those are all the flags, as you can see some are leftover from the early days of Intel
Processors and aren't used any more by programmers. These flags are a necessity for a
certain operation I'm not going to tell you about yet. However, flags are very important,
don't ever forget them!

The Stack

The stack is just a bunch of data that gets stacked on top of each other growing downward
in memory. When a register or all of the flags gets pushed onto the stack, the stack grows
down. When a value is popped off the stack the value popped is the last one that got
pushed on. LIFO: Last In First Out, remember that because that is how the stack works.


They Interrupt the CPU. Interrupts are just what the name suggests, they interrupt the
processor (CPU from now on) and make it do something and then return to what it was
doing before the interrupt. There are several kinds of interrupts, they are:

Hardware - Internal CPU interrupts, we can't use these.

Software - One of the most important things to use.

Each interrupt has a unique number, and each interrupt number has many function
numbers that determine the interrupt function to run. Next section we start coding!

Using Interrupts

To use an interrupt function you need a function number in the AH split register. And
then you call the interrupt number that contains the function. Here is an example:

                      mov ah,4ch          ; MOVes 4C in hex to AH.
                      int 21h            ; calles the DOS System interrupt number.

Function 4C of int 21h is the end program function, this function is why programs
crashed if you ran assembled code from previous sections. Some functions require
parameters to be passed to them. Parameters are required to be passed in registers.
Registers used for parameters differ from function to function. Here is an example:

                      mov ah,2            ;MOVes 2 to AH. 2 is the write letter to screen
                      mov dl,'H'       ; DL is where the letter goes. Letters are specified in
                      int 21h         ; 21h is the DOS service interrupt number.
                      mov ah,4ch
                      int 21h             ; These last two line are to make it work if you
assemble it.

Some functions return one or several values in registers, such as one letter input functions
and so on.


         Address bus: 20 bits... 1,048,576 addresses
   But internal registers only 16 bits: can't hold a full address
   Segment Registers define four 64k "windows" on the address space

8086 addresses are specified as xxxx:yyyy

        o    where xxxx is value in segment register
        o    yyyy is offset

Addresses are specified as relative to start of segment

    eg. Instruction Pointer relative to Code Segment

    Address of next instruction (hexadecimal) is:

        CS     xxxx0
        IP      yyyy +
        Addr    aaa aa

aaaaa is "effective address" (20 bits)

Put another way:

    effective address = 16 * [ segment-reg ] + offset

(Referred to as segment/offset addressing)

Most other microprocessors can access all of memory at any time: "flat memory

      Segment/offset addressing
           o addresses are relative to segment registers
           o segments may overlap
      Storage is Little-Endian
      8086 CPU is split into two main parts
           o Execution Unit
                    General Registers
                    ALU
           o Bus Interface Unit
                    Instruction Queue
                    Segment Registers
                    Instruction Pointer
      Status Flags Register

       O = Overflow           Z = Zero
       D = Direction          A = Aux. Carry
       I = Interrupt        P = Parity
       T = Trap             C = Carry
       S = Sign

A Machine Code Program
      addr code
      0000 2B C0
      0002 03 07
      0004 83 C3 02
      0007 3B D3
      0009 79 F7

      2B C0 =0010 1011 1100 0000
      Format of register-to-register instruction:

        opcode = 001010 means "Subtract"
        w = 1 means "word" (16 bits); 0 means "byte"
       dest reg = address of destination register: 000 = AX
        src reg = address of source register: 000 = AX

    Written using mnemonics and comments

    0000 SUB AX,AX          ;Set AX to 0

    0002 ADD AX,[BX]        ;add (word pointed to by BX) to AX

    0004 ADD BX,2         ;Add 2 to BX (points to next word)

    0007 CMP DX,BX          ;Compare DX to BX

    0009 JNS 0002        ;If DX >= BX jump back to 0002

   Adds up contents of memory from [BX] to [DX], result goes in AX


   Subtracts source from destination and updates flags
   does not save result.
   Flags can subsequently be checked for conditions
   CMP DX, BX performs (DX - BX)
   So if BX > DX result will be negative - Sign bit will be set
   Test/Compare instructions set flags
   Flags may affect later instructions (eg. Conditional jumps)


   Jumps to new address if Sign flag = 0

    0009 79 F7 JNS 0002

   79 means "JNS"
   How does "F7" take us back to 0002...?

    F7 = 1111 0111

    2's complement... MSB=1 so NEGATIVE
        Invert: 0000 1000

        Add 1: 0000 1001 = 9 (dec)

       Therefore 1111 0111 (F7) is -9

       After fetching "79 F7" Instruction Pointer = 000B
       Adding -9 to IP gives 0002

Start Coding

First, lets learn how to move data to a register:
To move data to a register you use the mov command. Where the data is to go is the first
item, and the data is the second item. Here is an example that MOVes 45 to AX:
             mov ax,45

 Let's try assembling it: Type mov ax,45 into asm.txt and save it. Drag asm.txt over and drop it to assemble. will run and create 2 new files. The .sym file
is of no use to us and can be deleted. However, the .com file is the program. Don't try
running the .com file, because it WILL crash because we didn't end the program properly.
That is how to assemble a file.

Now, let's move data from one register to another: We still use the mov command , and
time the register to receive the data is first and the register with the data to move is
second, here is an example:
                     mov ax,45h
                     mov bx,ax
The first line moves 45(h after a number means hex) into ax, the second copies the
number in ax (45h) to bx, so bx is now 45h too. To mov data around in the split registers
simply replace the large register with the split version. Like this mov ah,cl or mov
dh,90h , however, do not mix large and split registers like this mov ah,ax or it won't
assemble. Using split registers works for add and sub only.

Math Operations

+,-,*,divide (how do you do divide on a keyboard?)

The basic math operations in assembly are:

add - Adds the first item to the second storing result in first item.

sub - Subracts the second item from the first and stores result in the first item.
mul - Multiplies the given item to AX and stores the result in AX.

div - Divides the given item by AX and stores the result in AX.

The add and subtract operations are simple enough, they do their job like a MOV
command and subtract or add to the receiving end and store the result in the receiving
end. Example:
                  add ax,23      ;adds 23 to ax and stores results in ax.
                  sub ax,45h     ;subtracts 45 in hex from ax and stores in ax.

The mul and div instructions are a bit different though, they both use the AX register as
their "base of operations", They both multiply to or divide by A REGISTER ONLY and
store the result in AX.

                        mov ax,10   ;give a value to multiply by in AX.
                        mov bx,20     ;give a register the data we want to * by
                        mul bx          ;multiply ax & bx, storing the result in
               example: DIVISION:
                        mov ax,10  ;What we want to divide or data by.
                        mov dx,100 ;What we want to be divided by AX.
                        div dx      ;Divide DX by AX, storing result in AX.

And that's how the BASIC Math Operations work. That's right! Basic is italicized
because there are actually two more math operations I have not mentioned yet, and no,
they do not make multiply and divide any easier! Wondering why the explanations of the
example code start with semi-colons? Find out in the next section!

Code Comments

What those semi-colons are for! Those semi-colons are called code comments, they are
useful to document your code so you know what each thing does. The semi-color (;)
stops the assembler from thinking that your comment is assembly code and returning an
error. Comments last until the end of the current line and are considered good
programming practice in large projects. That's all the commenting I have to comment on
comments! :-)

Labels and Unconditional Jumps

The goto statement for you Basic Programmers. In this section we start getting into
program flow control. Labels are just what the name suggests labels, the syntax for a
label is like this:

example:                       label1:

As you can see it is a name and a colon. NO CODE CAN BE ON THE SAME LINE AS
A LABEL! Labels do not actually do anything but sit there and reference a location in a
program. However, they are very useful for Unconditional Jumps, which are used to
JUMP to another location in a program and run the code starting after the label
referenced. Here is an example to best explain Unconditional Jumps:
                         jmp runhere    ;JMP command jumps to the label "runhere" and
run the code after it.
                         mov ax,45      ; This command won't be run because it is JMPed
                         runhere:       ; The label where the JMP jumps to.
                         mov ax,90h      ; This statement will be run after the jump.

Now I hope that you understand labels and their use with Unconditional Jumps.

Conditional Jumps

Conditional Jumps only jump if a certain condition is met, that's why they are called
conditional! The condition they check is based on the FLAGS. See, I told you the flags
would be important! There are several jump commands that check a certain thing to see
if they should jump or not. They are:

JE - Checks for equality.

JNE - Checks for UNequality.

JA - Checks to see if one thing is Above another.

JB - Checks to see if one thing is Below another.

JZ - Same as JE...

Those are the Conditional Jump Commands. Use them well Young Jedi.

Compare Command

The Compare Command (CMP) compares the first item with the second setting and
clearing flags automatically. The most recent compare is what conditional jumps use.
You can compare two registers like this:
                    cmp ax,bx        ;Compares AX to BX

And Register to Data like this:

                         cmp dx,45     ;Compares DX to 45


Also, remember that the first item is compared TO the second. This command is like
telling the computer to create an equation resulting from the comparison such as DX > 45,
which would make the JA (Jump on Above) jump. Remember in all operations that
registers go on the left and data goes on the right. You can also use the split registers
with the cmp command.


1 [Arithmeti c]
Write 8086 Assembly Language programs for the following operations. The
operands and the results are to be stored in specific memory locations.
(a) Add three 16-bit unsigned integers (b)Add three 16-bit signed integers (c)
Multiply two 16-bit unsigned integers (d) Multiply two 16-bit signed integers (e)
Divide a 16-bit unsigned integer by an 8-bit unsigned integer (f)Compute the
X = |((A*B) – (C*D))| /E. Assume 16-bit unsigned integer variables.

2 [Basic Input/Output]
Study the various BIOS interrupts and DOS functi on calls that are useful in
input and output operations. Build programs for multiple character input, multi -
digit input, etc that may be reused in the subsequent programs.

3 [Control Stru ctures ]
Write Assembly Language programs for simulating:
(a) For.. loop (b)While loop (c) Repeat..until loop (d) If ..then..else structure
(e)Switch statement ( of C language). Use appropriate action within the loop such
that the difference among the above control structures is understood.

5 [Subroutines -Use of Sta ck]
(a) Write a subroutine for raising an integer x to an integral power n. Using this
routine, evaluate a polynomial p(x) at x = k. (b)Test whether an input string is a

6 [Search]
(a) Write a program to search for a given number in an array of N n um bers. Do
not assume that the array is sorted. Generate appropriate responses after a
success and failure (b) Create a sample login session for a user. Get a User -id
and Password from the keyboard, without echoing the password. Verify the User -
id, passwor d pair using a stored list, and take appropriate action.

7 [Finding M in and M ax of a set of numbers]
Given a set of N integers, find the minimum value in it. Without using an
additional loop, find the maximum value also. Hence find the range of the set
(i.e. Max-Min).

8 [Display Attributes and Speaker control]
Design a menu-driven program for the following display functions
(a) Clear the screen (b) Display the string given by the user at the center of the
screen in a particular color and make it blink (c) Produce a beep soun d after step
b is completed.

9 [M ACRO definition]

Code a MACRO definition to find the GCD of two integers. It should accept two
dummy parameters A and B and produce GCD (A, B). Use the macro for finding
LCM (A, B) also.

Exp 10 Interfa cing
(a) Interface a Digital-to-Analog Converter (DAC) to the 8086-kit and write a
program to display different waveforms (triangular, square, saw tooth, etc) on a
CRO. (b) Interface a Stepper motor interface card to the 8086 kit, and write a
program to control the rotation of the stepper motor.


                         NOTE TO THE T.A / INSTRUCTOR

       An introductory session to the functional blocks of Intel 8086, its
        instruction set and the use of MASM/TASM/DEBUG is desirable.

       Divide the students into groups of 2-3 people. Assign each group a user-
        id and password on a specific machine, which must be used throughout
        the course.

       After login, go to the directory C:/8086/HELPPC on the C drive. Choose
        MASM or TASM as the case may be. HELPPC contains the basics of 8086
        architecture and its instruction set.

       Enter the programs using a text editor, and assemble using TASM/MASM
        from the DOS command line. Link the .obj files and execute the resulting
        .exe file. Alternately, use the debugger facility to enter, assemble and step
        through the program.

       After completing each experiment, a demo of the same should be
        evaluated. Also insist on regular record submission.


          IBM PC Assembly Language and Programming: Peter Abel

          Using Assembly Language: Wyatte, Sr.

To top