Академический Документы
Профессиональный Документы
Культура Документы
1
I
Structure
i
b
3.1
INTRODUCTION
After discussing about few essential directives, program developmental tools and simple programs, let us discuss more about assembly language programs. In this unit, we will start our discussions with simple assembly programs which fullils simple task such as data transfer, arithmetic operations, shift operations. A kcy example here will be about finding larger of two numbers. T b r e a f ~ e rwe will , discuss about more complex programs showing how loops and various comparisons are used to implement tasks like code conversion, coding characters, finding largcs~ in array etc. Finally, we will discuss about more complex arithmetic and string operations. You must refer to further reading for more discussions on these programming concepts.
3.1
OBJECTIVES
At the end of this unit, you should be able to: write assembly programs with simple arithmetic logical and shift operations implement loops use comparisons for implementing various comparison function write simple assembly program for code conversion a write simple assembly program for implementing arrays
3.2
As part of this unit, we will discuss to write assembly language programs. We shall start with very simple programs, and later graduate to more complex ones.
DATA SEGMENT VALUEl DB VALUE2 DB DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA MOV AX, DATA MOV DS, AX MOV AL,VALUEl XCHG VALUE2,AL MOV VALUE1,AL MOV AX,4COOh
; Load Value1 into AL
OAh 14h
;Initialize Variables
INT 21h
CODE ENDS END MOV instruction has already been described in detail in the Unit 1. We shall only revise some of the limitations on types of operands for this type of data transfer instructions:
- If the source is immediate data, it must not exceed 255 (FFh) for an &bit
XCHG
AL,VALUE2
MOV
Other statements in the above program have already been discussed in the preceeding units.
; ABSTRACT
; REGISTERS
;PORTS DATA
ENDS S EG M ENT
ASSUME C:S:CODE, DS:DATA START: MOV AX, DATA MOV DS, AX MOV AL, HI-TEMP ADD AL, LO-TEMP MOV AH, ()Oh ADC: AH, ()oh hlOV BL, O3h I>IV [ { I .
; Initialize d a t ; ~ scgrncnt
; rcgi"er
all of AH rcgistcr
ENDS START
I n the above program, the ADD AL,LO-TEMP i~islruction adds the specified byte from memory to the contents of thc AL register. I t is not possible to directly add the contents of two memory locations, thercforc,HI-TEMP was first moved into a register.
Thc ADC AH,OOh instruction adds the immediate number OClh plus the contents of the carry flag to the contents of the AH register. The result will be left in the AH rcgistcr. Since we had cleared AH to all zeros, before the add, what we are really adding is O h + O h + CF. The result of all this is that the carry flag bit is put in O O the AH register.
The next major action of our program i~ to divide the $um of two temperature, h> 2 You would remember, in our first unit, we had mentioned two divide instructlon4 DIV and IDIV, for unsigned and signed arithmetic respcctivcly. In our examplc, u.c. have assumed the temperatures to be only positive, and have, therefore, ured unsigned division instruction. In a more general case, we could have assumed the temperature to be both positive and negative, and used IDIV instruction. Before performing the divide operation, thc dividend is put in the AX register and thc divisor in any &bit register. We have used BL register in our case. After the division, the 8-bit quotient will be left in the AL register, which can then be copied into the third memory location.
;Program produces a packed BCD byte from 2 ASCII; encoded digits. The number is 59.
;The first ASCII digit (5) is loaded in BL.
; The second ASCII digit (9) is loaded in AL.
;PORTS CODE
START:
MOV
BL,
'5'
'9
OFh
OFh
04h
ROIC)R
BI..
tZ I..
C 1.
RL.
; Rotate
BL 4 bit positions
; Combine
CODE
ENDS
END
START
You would find in the aho\.c csamplc. that we are using ROL and OR instructions.
8086 docs not ha\v any instruction to swap two nibbles in a byte, it can however exchange two hytcs or words using XCHG instruction. Out of the two rotate
i
b
instructions, ROL ancl RCYL. we ha\x chosen ROL, for the following rcason. ROL rotates Icft the byte Icft by one or more positions, bringing the MSB into LSB position and also mo\.ing it into thc carry bit. RCL on thc other hand, moves thc MSB into the carry l1;1gand brings the original carry flag inln the LSB position. Lvhich is not whirl we want. By using ROL four times we can mo\:c thc upper nibblc into thc Iowcr nil>hlc position, and the lower nithle into the upper one. Lct us now look at irn csiini~lc using RCL instruction. This will makc the differcncc hct\vccn the instrurtion~ clcirr. The folio\\-ing program adds a hytc numhcr from one mcmory location to a byte I'roni thc ncst memory location. puts the sum in the third mcmory location. and ~ i v the %talcof the carry flag in ~ h least significant bit of the fourth mcmory c c location. The upper 7 141sof the memory location where the carry is storcd arc n~;r\L;ccl. :ABSTRACT
: -This program adds 2 8-hit words in the memory locations
: wa\
3 carry
; ALCiORITHM:
,
r
,
position carry in LSB of byte mask off upper seven bits store the result in the carry location.
; PORTS
: None used
; PROCEDURES
; REGISTERS
: None used
: Uses CS, DS, AX
; DATA
NUMl NUM2
SEGMENT
ASSUME CS:CODE, DS:DATA START:MOV AX, DATA MOV DS, AX MOV AL, NUMl ADD AL, NUM2 MOV RESULT, AL RCL AL, 01 AND AL, O O O OB OOOl MOV CARRY, AL CODE END ENDS START
; Initialize data segment
;register
;Get the first number
RCL instruction brings the carry into the least significant bit position of the AL register, and the AND instruction masks all the higher bits. (Please compare it with how carry was brought in AH register in the example in section 3.2.2) In a similar manner we can also write applications using other shift instructions.
Result of comparison
Destination < source Destination = source Destination > source
Flag(s) affected
Carry flag = 1 Zero flag
=
Carry = 0, Zero = 0
Let's look at three examples that show how the flags are set when the numbers are compared. In example 1AL is less than 10, so the carry flag is set. In example 2, the, zero flag is set because both the operands are equal. In example 3, the destination (SI) is greater than the source, so both the zero and the carry flags are clcar.
Example 1. MOV AL, 05 CMP AL, 10 Example 2. MOV AX, 1000 MOV CX, 1000 CMP AX,CX Example 3. MOV SI, 105 CMP SI, 0
; Zero and Carry flags = 0 ;Zero flag = 1
; Carry flag = 1
We shall do a more complete example in the following sections whcrc wc shall scc how to make actual use of these instructions.
I[
False
1-1
3.
In the example given in section 3.2.2 we can change instruction DIV BL with a shift. True ~alse
4.
A single instruction can not swap two nibbles of a byte register. True False
5.
An unpacked BCD number require 8 bits for storage, however, two unpacked BCD numbers can be packed in a single byle register. True False
6.
If AL = 05 andBL = 06 then CMP AL, BL instruclion will clear the zero and carry flags. True
False
33
let us now discuss few examples which are slightly more advanced than what wc have been doing till now. This section deals with more practical examples using loops, comparison and shift instructions.
In the above example the control of the program will be directly transferred to the label THERE only if AX register is equal to the register BX. The same example can be rewritten in the following manner, using different jumps. Example: CMP JNE JMP FIX: ADD AX,BX FIX THERE AX, 02 CL, 07
;compare to set flags ;if not equal do correction
THERE: MOV
Obviously the above piece of code is inefficient as compared to thc rirst example. .r> there is an additional jump which has occurred due to J N E . Hence care must he taken while picking up the instructions. Example: The following example, adds an inflation factor to a serics of price4 In memory. It copies the new price over the old price. The algorithm for the above can be w r i ~ ~ e nfollows: as Repeat Get a price from the array Add inflation factor ~ d j u iresult to correct BCD t Put result back in array Until all prices are inflated
ARRAYS
SEGMENT COST DB 20h, 28h, 15h, 26h, 19h, 27h, 16h, 29h 36h, 554 27h, 42h, 38h, 41h, 29h, 39h
ASSUME CS:CODE, DS:ARRAYS START: MOV MOV LEA MOV DO-NEXT: MOV ADD DAA MOV INC DEC JNZ CODE ENDS END START [BX], AL BX CX DO-NEXT AX, ARRAYS DS, AX BX, PRICES CX, 0008h AL, [BX] AL,03h
;Initialize data segment
; register ; Initialize pointer ; Initialize counter
LEA BX,PRICES will load the BX register with the offset of the array PRICES in the data segment. [BX] contains the value stored at thdt element of the array PRICES. BX can be directly incremented to point to the next element of the array. Every time the register BX is incremented, CX register is decremented by one to keep a check of the bounds of the array. Once the CX register becomes /cro, Zero llag is set to 1. Therefore, before going to fetch the next byte from the array PRICES, CX is decremented, and JNZ instruction is used to jump to the start of the loop. The same program can be written using the LOOP instruction, in which case, DEC CX and JNZ DO-NEXT instructions are replaced by LOOP DO-NEXT instruction. LOOP decrements the value of CX and jumps to the given label, only if CX is not equal to zero.
. Language Programming
/
Mkroproccssor and h m b b
(FFFFW) to be the larger number. JGE on the other hand, would treat the numbers as signed and consider 0 to be greater than -1.
The smallest and the largest variables are first initialized to the first number in the array. They are then compared with the other array values one by one. If the value happens to be smaller than the assumed smallest number or larger than the assumed largest value, the smallest and the largest variables are changed with the new values respectively. DI points to the current array value and LOOP instruction is used to scan the array elements.
CODE
SEGMENT MOV MOV MOV MOV MOV MOV MOV AX,DATA DS,AX DI, OFFSET ARRAY AX, [DI] LARGEST, AX SMALLEST, AX CX,6 AX, [DI] AX, SMALLEST A2 SMALLEST, AX A3
;initialize DS
; DI points to the array ;AX contains the first element
; initialize largest
; initialize smallest
Al:
;yes :skip
; no : move [DI] to smallest ;as it is smallest, thus no need ;to compare it with the largest
.
i
I
A2:
; [DI] = largest
A3:
CODE DATA
ENDS SEGMENT ARRAY LARGEST SMALLEST DW DW DW -1, 2000, -4000, 32767, 500, 0
?
DATA
ENDS
2 is added to DI to poinl to ncxl elcment of the array, as the array consists of words, whose length is equal to 2 bytes. This program can be made faster if smallest and largest are stored temporarily in registers for comparisons. ,
1256 4658
As each digit is input, we would store its ASCII code in a memory byte. After the first number was input the number would be stored as follows:
33 34
3 4
30
0
32
2
In order to calculate the sum, we have two alternatives, either to convert the ASCII digit string to a 16-bit binary value, which in turn could be used in arithmetic calculations; or we can add the ASCII digits themselves. For the second option there are instructions like AAS (ASCII adjust after subtraction), AAD (ASCII adjust alter division), AAA and AAM available. These can be used dirtctly without much difficulty. Refer unit 1 of this block for details on these instructions:We shall demonstrate the first option in the next section. Another type of coded data available is packed decimal numbers (packed BCD). It contains two decimal digits per byte. You have already been doing a lot of examples of this in the previous units. Packed BCD format has at least three strengths:
* The numbers may have almost any number of significant digits. This makes
possible calculations with a great deal of accuracy.
;
;
;ALGORITHM:
;
I F number < 30h THEN error ELSE IF number < 3Ah THEN Subtract 30h (its a number 0-9) ELSE (number is > 39h) I F number < 41h THEN error (number in range 3Ah -40h) ELSE IF number < 47h THEN Subtract 37h for letter A-F 41-46 ELSE error
;
9
,
J
;PORTS
: None used
ASSUME CS:CODE, DS:DATA START: MOV MOV MOV AX,DATA DS,AX AL. ASCII
; Initialize data segment
; register
;start the conversion CMP JB CMP JB CMP AL, 30h ERROR AL,3Ah NUMBER AL, 41h ERROR
; If greater then possibly a lettc~
; Is it a letter? ; Between 3A and 40 is error
; Nor
JB
AL, 46h ERROR AL, 37h CONVERTED AL, 30h CONVERTED AL,OFFh
;It's a number so convert
In the above program, we have demonstrated it for a single binary digit represented by and ASCII character. The program can be extended to take more ASCII digirs .tnd convert them into a 16 t i t hinarv numhcr. Thi5 can hc done in rhc follouing m'rnncr: Example: Assume CX contains the hexadecimal number obtained afrer conversion. BX contains 10, AX contains the number obtained till now. To start with A X was equal to 0. Now assume that AX has become 0020h and CL = 02. AND MUL ADD CX, OOOFh BX AX,CX
; convert digit to binary
; DX :AX = AX
* 10
Follow the above steps with the AX and CL values given above. AL is multiplied by BL, so AX = 0140h. CL is added to AX, yielding 142h. You can improve your program by checking for overflow conditions also.
...................................................................
2.
3.
An assembly program is to be written for inputting two 4 digits decimal numbers from console, adding them up and putting back the results. Will you prefer packed BCD addi~ion such numbers? Why? for
................................................................... ...................................................................
How can we implement nested loops, for example, for (i = 1to 10, step 1)
....................................................................
3.4
In this section we go a step forward, to look at more advanced features of assembly language programming. These are some of the features that give it an edge over the high level language programming. One of the very important set of instructions is for string processing. If you write the same code in high level language, the object code generated after compiling is much longer than for the same program written in assembly language. In the next section we shall demonstrate this.
+ 1;
The intermediate code in assembly language generated by the compiler for the above piece would look something like this: MOV IND,00 IND, 08 L1 AX,STRl BX,IND CX,STR2
;ind : = 0 ; ind < 9
;not so; skip
L3: CMP
JG
LEA MOV LEA
DL, BYTE PTR CX[BX] DL, BYTE PTR AX[BX] L1 IND,BX IND,01 L3
;strl[ind] = str2[ind] ;no, skip
;loop back
You see, there is lot of redundant code, which could have been avoided, if we had written the same program directly in assembly language. The code is further improved if we write it using the string instructions as follows. Example: ;REGISTERS :Uses CS, DS, ES, AX, DX, CX, SI, DI DATA SEGMENT PASSWORD DESTSTR MESSAGE DATA CODE ENDS SEGMENT DB DB DB 'FAILSAFE' 'FEELSAFE'
;source string ;destination string
ASSUME CS:CODE, DS:DATA, ES:DATA MOV MOV MOV AX,DATA DS,AX ES,AX
;Initialize data segment register
; Initialize extra segment register
I'! I
REPE
;Load source pointer ;Load destination pointer ;Load counter with string length ;Clear direction flag
I I I
AX, 4C00h
21h
In the above program, you would notice, a new instruction CMPSB, compares the two strings, pointed by SI and DI registers, and present in the data and the extra segments respectively. It compares the strings byte by byte and subsequently increments the string pointers by one. The same instruction, but with a 'W' suffur instead of 'B' can be used to compare the strings word by word. The REPE prefix in front of the instruction, tells the 8086 to decrement the CX register by one, and continue to execute the following instruction, until the counter in CX becomes zero. Thus, you should now be able to appreciate, the advantage of using the string instructions in assembly. These considerably reduce the code. We have also introduced a new interrupt function, used for displaying the string message. The string is assumed to be present in the data segment, and the DS register is assumed to contain the offset of the data segment. The function number for displaying the string is stored in the AH register, DX register contains the offsc~ of the string to be displayed. A similar type of the program, as above, can be written to move one string to another, MOVS, and scan a string for a character, SCAS.
The first problem, which is a very useful application of assembly, is to produce delay loops. Delay loops are used in places, where you are required to wait for some time before executing the next instruction. To do this, let us first discuss about the calculation of the time for the delay. The rate at which the instructions are executed is determined by the clock frequency. Each instruction takes a certain number of clock cycles to execute. This multiplied by the clock frequency of the microprocessor, gives the time in actual, that the instruction takes to execute. For example, MOV instruction takes four clock cycles. When it is executed on a microprocessor of clock frequency 5 Mhz, takes 415 or 0.8 microseconds to complete its execution. The same instruction when run on a microprocessor with 4Mhz clock frequency takes, 414, i.e. 1microseconds. NOP is used to produce the delay, without effecting the actual running of the program. Consider the following examples, in which you are trying a produce a time delay of 1ms, over a microprocessor, with a clock frequency of 5 MHz. Time taken for each clock cycle is 1/(5 MHz), which is equal to 0.2 micro seconds. To get a delay of 1 ms, we need to execute 100010.2 or 5000 processor clock cycles. The following program can be used to produce the delay, with the counter value correctly initialized. clock MOV cycles CX,N
;4 ;
DELAY:
;3 ;3
; 17 or 5
LOOP instruction takes 17 clock cycles when the condition is true and 5 clock cycles otherwise. The condition will be true, 'N' number of times and false only once, when the control comes out of the loop.
+ N(2*NOP clock-
cycles
+ 17) - 12 (when CX = 0)
LEN
Clear the carry flag Load address of NUMl REPEAT Put byte from N U M l in accumulator Add byte rrom NUM2 to accumula~or+ carry
Rotate carry into LSB of accumulator Mask all but LSB of accumulator Store carry result, address pointer in correct position. ;PORTS
: None uscd : None used : Uses CS, DS, AX, CX, BX, DX
;PROCEDURES ;REGISTERS
DATA
, Olh
30h,
, l l h , 20h
40h
, OFFh
6DUP(O)
DATA
ENDS
LEN CODE
EUU
05h
; constant
START:
; 1nitiali;rcdata segment
AGAIN:
AL, NUMl[BX] ; Get a byte from NUMl AL, NUM2[BX) ; Add to byte from NUM2 SUM[BX], AL ; Store in SUM array BX AGAIN AL, Olh AL, Olh
; Continue until no more bytes ; Move carry into bit 0 of AL
FINISH:
NOP NOP
CODE
Example 3 Code Conversion Consider the following program which converts a +digit BCD numbcr into its binary equivalent, The BCD number is srored as a word in memory location cal BCD. The result is stored in location HEX. ALGORITHM:
I
Use the example 4596 as the BCD number Put the BCD numbcr into 3 extended registers Take the first digit (4) Mask out the other three digits (4000) Multiply by 3EXh (1000) to gct 4000 Take the second digit (5) Mask out thc other three digits (0500)
=
OFAOh
Multiply by 64h (100) Add to first digit and get 4500 Take the third digit (9) Mask out the other three digits (0090) Multiply by 0Ah (10) Add to first and second digit to get 4590 Take the last digit (6) Mask out the other three digits (0006) Add to first, second, and third digit to get 4596 ;PORTS
: None used
=
1194h
llEEh
11F4h
;REGISTERS: Uses CS, DS, AX, CX, BX, DX THOU DATA EQU 3ESh
; 1000
=
3E8h
DATA CODE
ENDS SEGMENT
ASSUME CS:CODE, DS:DATA START: MOV MOV MOV MOV MOV MOV AX,DATA DS,AX AX,BCD BX,AX AL,AH BH,BL
; Initialize data segment
; Place for upper 2 digits ; Place for lower 2 digits ; split up numbers so that we have one ;digit in each register
; Nibble count for rotate ; Digit 1 (MSB) in low nibble of AH ; Digit 3 in low nibble of BH
; Digit 2 in low nibble of AL ; Digit 4 in low nibble of BL ; copy AX into CX so that can use AX for ; multiplication
Language Programming
MOV
A?(.Cw~fk!il
AL,CH D1,THOU DI
;digit 1* 1000
; Result in DX and AX. Because BCD digit ;will not be greater than 9999, the result ; will be in AX only. Zero DH and add BL ;because that digit needs no multiplication ; for place value. Then add the result in ;AX for digit 4
MOV MOV ADD MOV MUL ADD MOV MUL ADD MOV MOV
INT 21h
DH,OOH DL,BL DX,AX AX, 0064h CL DX,AX AX,OOOAh BH DX,AX HEX,DX AX,4C00h
: 5tcn.c digit 4 to DL
; Add
CODE
ENDS END
START
Why should we perform string processing in assembly language in 8086 and not in high level language?
...................................................................
2.
What is the function of direction flag in the second example given in 3.4.1?
...................................................................
3.
3.5
SUMMARY
In this unit, we have covered some basic aspects of assembly language programming. We started with some elementary arithmetic problems, code conversion problems, various types of loops and graduated on to do string processing and slightly complex arithmetic. As part of good programming practice, we also noted some points that should be kept in mind while coding. Some of them are:
Your program should always be preceded by an algorithm. It is a good programming practice. This not only increases the readability of the program,' but also makes your program less prone to logical errors.
- Use comments liberally. You will appreciated them later. - Study the instructions, assembler directives and addressing modes carefully, before starting to code your program. You can even use a debugger to get a clear understanding of the instructions and addressing modes. - Some instructions are very specific to the type of operand they are being used with, example signed numbers and unsigned numbers, byte operands and word operands, so be careful !!
Certain instructions expect some registers to be initialized by some values before being executed, example, LOOP expects the counter value to be contained in CX register, string instructions expect DS:SI to be initialized by the segment and the offset of the string instructions, and ES:DI to be with the destination strings, INT 21h expects AH register to contain the function number of the operation to be carried out, and depending on them some of the additional registers also to be initialized. So study them carefully and do the needful. In case you miss out on something, in most of the cases, you will not get an error message, instead the 8086 will proceed to execute the instruction, with whatever junk is lying in those registers.
Inspite of all these complications, assembly language is still an indispensable part of the programming, as it gives you an access to the most of the hardware features of the machine, which might not be possible with high level language. Secondly, as we have also seen some kind of applications can be written and efficiently executed in assembly language. In the preceeding text, we justified this with string processing instructions, you will appreciate it more, when you actually start the assembly language programming. You can now perform some simple exercises from the further readings. In the next block, we take up more advanced assembly language programming, which also includes accessing some hardware features of the machine.
Mkmpmeeswr and k m b l y
~.nlp.poy.=mlnp ~
36 .
MODEL ANSWERS
AX,A AX, B
;BringAinAX
;Subtract B
IMUL AX
2.
Assuming that each array element is a word variable. MOV MOV MOV CX, COUNT AX,OOOOh SI, AX
;Put the number of elements of the array in ;CX register
;Zero SI and AX
AGAIN: ADD AX, ARRAY [SI] ;Another way of handling array ADD SI, 2
;Select the next element of the array
;Add all the elements of the array. It will
;terminate when CX becomes zero.
LOOP AGAIN
MOV
3.
4.
TOTAL, AX
Yes, because the conversion efforts are small. We may use two nested loop instructionsin assembly also. However, as both the loop instructions use CX, therefore, every time before we are entering inner loop we must push CX of outer loop in the stack and reinitialise CX to the inner loop requirements.
The object code generated on compiling high level languages for string processing commands is, in general, found to be long and contains several redundant instructions. However, we can perform string processing very efficiently in 8086 assembly language. Direction flag if clear will cause REPE statement to perform in forward direction. That is, in the given example the strings will be compared from first element to last. It produces a delay of a desired clock time in the execution. This instruction is useful while development of program. A collection of these instructions can be used to fill up some space in the code segment which can be changed with new code lines without disturbing position of existing code. This is particularly used when a label is specified.
2.
3.