Assembly Lab Manual

20
ASSEMBLY LANGUAGE PROGRAMMING: A LAB MANUAL Contents Introduction Intel 8086: A brief excursion Using DEBUG Using the Assembler A sample program Data Definition Interrupts Functions Macros Interfacing Appendix-I Suggested list of experiments Appendix-II Note to the T.A / Instructor

description

Assembly Lab Manual

Transcript of Assembly Lab Manual

Page 1: Assembly Lab Manual

ASSEMBLY LANGUAGE PROGRAMMING: A LAB MANUAL

Contents

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

Appendix-I

Suggested list of experiments

Appendix-II

Note to the T.A / Instructor

Page 2: Assembly Lab Manual

ASSEMBLY LANGUAGE PROGRAMMING: AN INTRODUCTION

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

IS MICROCODE ESSENTIAL? Don't have to use microcode at all .

Page 3: Assembly Lab Manual

Possible for Machine Code instructions to control logic directly (via Control Unit)

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

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

INSTRUCTIONS 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

TYPES OF INSTRUCTION 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

Page 4: Assembly Lab Manual

* Jump, Branch, procedure call

Test/Compare

* Set condition flags

Input/Output

* In, Out

* Only on some CPU's

Others

* Halt, NOP

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

Zero-address instruction:

One-address instruction:

Two-address instruction:

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

ADDRESSING 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)

ADDRESSING MODES

addr is address field of instruction

Opcode

Opcode Address

Opcode Address1 Address2

Page 5: Assembly Lab Manual

Immediate addr is operand

Register addr is number of CPU register operand := [ addr ]

Direct addr is address in primary memoryoperand := [ addr ]

Indirect addr is register number (or memory address)operand_address := [ addr ]operand [ operand_address ]

Indexed addr is base addressindex is a register

operand := [ addr + [index] ]

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

8086 ARCHITECTURE :Hardware Overview

Page 6: Assembly Lab Manual

PROGRAMMER'S VIEW - REGISTERS

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:

Page 7: Assembly Lab Manual

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 with:

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

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.

Page 8: Assembly Lab Manual

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.

Interrupts

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 function.

mov dl,'H' ; DL is where the letter goes. Letters are specified in quotes.

int 21h ; 21h is the DOS service interrupt number.mov ah,4chint 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.

8086 ADDRESSING

Address bus: 20 bits... 1,048,576 addresses

Page 9: Assembly Lab Manual

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 x x x x 0 IP y y y y + --------- Addr a a a a a

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 model"

8086 FEATURES Segment/offset addressing

Page 10: Assembly Lab Manual

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 code0000 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

Page 11: Assembly Lab Manual

ASSEMBLY LANGUAGE PROGRAM

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

CMP - COMPARE 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)

JNS - JUMP IF NOT SIGNED 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)

Page 12: Assembly Lab Manual

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 A86.com and drop it to assemble. A86.com 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.

Page 13: Assembly Lab Manual

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.

example: MULTIPLICATION:mov ax,10 ;give a value to multiply by in AX.mov bx,20 ;give a register the data we want to * by

AX.mul bx ;multiply ax & bx, storing the result in

AX.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 over!

Page 14: Assembly Lab Manual

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

REMEMBER THAT CMP DOESN'T STORE ANYTHING!

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.

APPENDIX-I

SUGGESTED LIST OF EXPERIMENTS

Page 15: Assembly Lab Manual

1 [Arithmetic]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 function:X = |((A*B) – (C*D))| /E. Assume 16-bit unsigned integer variables.

2 [Basic Input/Output]Study the various BIOS interrupts and DOS function 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 Structures ]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 Stack](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 palindrome.

6 [Search](a) Write a program to search for a given number in an array of N numbers. 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, password pair using a stored list, and take appropriate action.

7 [Finding Min and Max 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 sound after step b is completed.

9 [MACRO 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 Interfacing(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.

APPENDIX-II

Page 16: Assembly Lab Manual

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.

References

IBM PC Assembly Language and Programming: Peter Abel

Using Assembly Language: Wyatte, Sr.