Upload
matthew-smith
View
5
Download
0
Tags:
Embed Size (px)
DESCRIPTION
37
Citation preview
Advanced MicroprocessorsSession – XIX
Interrupts, DOS Services09.11.2005
Dr. K.RajanikanthM.S.Ramaiah Institute of Technology, Bangalore----------------------------------------------------------------
Learning Objectives:
• Understand interrupt system of 8086 and learn to write Interrupt Service Routines
• Learn to use DOS Services
Introduction:
• Normal program flow can be “interrupted” because of a variety of reasons.
• When the interrupt occurs and is recognized, the values of the Flag register, CS
and IP registers are saved on the stack and the control is transferred from the
executing program to an associated “Interrupt Service Routine (ISR)”. After
completing the ISR control returns to the interrupted program.
• Thus, this mechanism is similar to yet different from Far Call. CALL is always an
instruction in the program. The mechanism of calling & returning from ISR is
some what different from normal CALL mechanism.
• The concept of an interrupt vis-à-vis a far call is illustrated in the following
figure:
Interrupts
CALLInterrupt
RETURN Return fromInterrupt
Interrupt ServiceRoutine (ISR)
(ISR; Interrupt Service Procedure; Interrupt Handler All mean the same)
Interrupt can be because of:
An external interrupt signal at the pins NMI or INTR . These are called
Hardware interrupts (studied in a later session).
A Software interrupt instruction.
Internal causes resulting from execution of other instructions etc, like
Interrupt on Divide Error. (sometimes called exceptions)
Whatever be the source of interrupt:
An interrupt instruction has an associated numeric operand called interrupt type code;
a number in the range of 0 to 255 (00H to FFH). (Thus we can have a total of 256 type
codes)
The interrupt type code:
Is provided by external hardware like Interrupt Controller (in the case of
external interrupts).
Is specified as part of instruction in the case of Software Interrupts.
Is implicit in the case exceptions like Divide Error.
Whatever be the source of interrupt & what ever be the type code:
For an ISR, both CS and IP are specified.
To this extent, an ISR is like a far procedure.
CS and IP of an ISR together constitute the Interrupt Vector. Thus an
interrupt vector is 2 + 2 = 4 bytes long.
One interrupt vector is required for each interrupt type code. We have 256
possible interrupt type codes and thus 256 possible interrupt vectors.
Consequently, to specify all these interrupt vectors, we need 256 x 4 =
1024 bytes of memory.
• Interrupt Vector Table: A table of 1024 bytes containing the 256 interrupt
vectors. Address range is 00000H (0:0) to 003FFH (0:03FFH). This is a memory
block of 1KB starting from 00000H
• Interrupt vector corresponding to interrupt type code n starts at location 4 x n.
• Example: Interrupt type code = 20H Corresponding interrupt vector starts at
20H x 4 = 80H. (In locations 80H, 81H, we have IP and in locations 82H, 83H,
we have CS)
• Another Example: Interrupt type code = 00H Corresponding interrupt vector
starts at 00H x 4 = 00H. (00H, 01H: IP ; 02H, 03H: CS)
Interrupt type codes:
• Some have predefined meaning;
• Some are reserved for future use; and
• Remaining interrupt type codes are free for user definitions.
This scheme is shown in the following Interrupt Vector Table:
Interrupt Vector Table
User-Defined80H – 3FFH20H - FFH
Reserved14H – 7FH
Interrupt on Overflow10H – 13H
Breakpoint0CH – 0FH
NMI08H – 0BH
Single Step04H – 07H
Divide Error00H – 03H
Type Codes Address Function
0
12
34
5 – 1F
Interrupt Processing:
When an interrupt is to be processed:
• Flags, CS and IP are pushed on to the stack.
(Note that no automatic pushing of Flags occurs with far Call!)
• T and I flags are cleared (disabling Single Step and External Interrupts)
• Control is transferred to the new CS : IP specified in the Interrupt Vector. (ISR
begins execution.)
Return from ISR:
• To return from the ISR, the interrupt return (IRET) instruction is used.
• Executing IRET pops IP, CS and Flags from the stack.
• In particular, the status of T and I flags is restored.
• Now, control returns to the interrupted program.
I Flag:
• I flag is cleared disabling recognition of external interrupts. To enable them
within the ISR, programmer can enable them using STI (Set Interrupt Flag)
instruction.
• CLI (Clear Interrupt Flag) instruction also clears the I flag disabling recognition
of interrupts from INTR pin.
• The use of these instructions is studied in detail in a later session.
T Flag:
• Setting the T flag enables Single Step. The, after the execution of every
instruction, an interrupt of type 1 is generated. This feature is quite useful for
debugging. (The ISR can display Register values & other useful information.)
• Evidently, within the ISR, Single Step should not be in effect! So T is cleared. On
return from ISR, the value of T is restored.
• This concept is illustrated in the following figure:
T Flag - 1Program to be traced(single-stepped):T flag = 1
ISR for INT 1; Part of DebugMonitor. T flag = 0
Software Interrupt Instructions (INT n):
These instructions appear as regular instructions in the program code.
• INT 3 is 1 –Byte long. (The only special case). Rest of INT n instructions are all
2 – Byte long.
• These instructions are commonly used to access system procedures. Example:
INT 21H to access DOS services.
• A software interrupt instruction is more convenient than far call. It occupies less
memory as it needs only 1 or 2 bytes as against the 5 bytes required for a far Call.
Further, there is no need to remember the CS:IP values. These values are obtained
from the Interrupt Vector Table.
• The software instruction format is as shown below:
INT 3 Instruction:
• Only INT n instruction that is 1 Byte long! Rest are 2 – Byte long.
• This is often used to effect a “breakpoint” in the program. The breakpoint service
routine can provide Register values and other information useful for debugging.
Any INT n can be used for implement a breakpoint. However, as INT 3 is only
1-byte long, it is comparatively easier to insert this instruction into the program.
INTO Instruction:
• This instruction causes an Interrupt on Overflow. Thus if the O flag = 1, an
interrupt is generated as Interrupt Vector 4. And if the O flag = 0 , this instruction
results in no operation.
• This instruction is placed in the program usually after arithmetic instructions that
may lead to overflow condition. (Recall that JO instruction also detects overflow
condition.)
opcode type code
Interrupts in PC:
• Type codes 0 to 4 are used in the standard way.
• Several interrupt type codes are dedicated to interrupts from hardware devices
like key board, mouse etc. Examples: 9 for Keyboard; 17H for Parallel Port.
• Software interrupt instructions commonly used in Assembly Language Programs
are:
– INT 21H : DOS Services
– INT 27H : Terminate and Stay Resident (TSR)
– INT 1AH : Clock Service etc.
DOS Services:
• DOS provides a variety of services like Reading the Keyboard, Writing to
Display, Disk access facilities etc.
• All these services are accessed in common via INT 21H
• Before invoking INT 21H
– We place a Function Code that indicates the service required in the
register AH.
– Other relevant parameters if any are placed in appropriate registers
Examples:
• Write to Standard Output Device
AH 02H; DL ASCII Char to be displayed
• Display a Character String
AH 09H ; DS:DX Address of Char String
The Char String must be terminated with an ASCII “$” (24H).
• Complete list of functions may be found in the Text Book.
• Before invoking a DOS function, user must Save & Restore registers if necessary.
• Lower – Level direct control of various I/O devices is possible via BIOS (Basic
Input Output System) function calls like INT 10H, INT 11H etc. (Not discussed in
this session)
• This session discusses some simple examples of using INT 21H.
Reading Keyboard:
• When a character typed on the key board is read, it may return the standard 7-Bit
ASCII code corresponding to the key typed. Additionally, Extended ASCII codes
are used to represent Function Keys, Key Combinations (Keys in combination
with Shift, Control, Alt keys). The full list of key codes used in a standard PC is
available in the Text Book.
• In this session, we will consider 3 simple ways to read keyboard:
Read key with echo;
Read key without echo;
Read entire line with echo.
Read Key With Echo:
• The code corresponding to the key typed is read. Further, the same character is
displayed on the screen also (echo). This routine responds to CNTL-C (That is,
when CNTL-C is typed, an immediate exit to DOS occurs)
• This service can be realized by invoking INT 21H with AH 01H
On return, AL ASCII code of character typed.
• If AL = 0, Extended ASCII code is indicated. In such a case, INT 21H must be
executed again to get the Extended ASCII code.
• The Read Key Procedure may distinguish these cases suitably (for example, via
Carry flag). In the following routine, CARRY is cleared to indicate standard key
code and it is set to indicate extended key code.
KEY PROC FAR
MOV AH, 01H
INT 21H
OR AL, AL ; Extended key code?
JNZ KEY1 ; No, return with carry = 0
INT 21H ; Extended code, read again
STC ; and return with carry = 1
KEY1: RET
KEY ENDP
Read Key Without Echo:
• The code corresponding to the key typed is read. However, the character is not
displayed on the screen also (no echo). Also, this routine does not respond to
CNTL-C (That is, typing CNTL-C does not cause an exit to DOS)
• Invoke INT 21H with AH 06H & DL = FFH
• On return, Z = 1 indicates that no char was typed.
Else, AL ASCII code of character typed. In this case, if AL = 0, Extended
ASCII code is indicated. Now, INT 21H must be executed again to get the
Extended ASCII code.
• The Read Key Procedure may distinguish these cases suitably (for example, via
Carry flag). In the following routine, Z = 1 indicates that no key was typed. If Z =
0, the key code is returned in AL and the CARRY is cleared to indicate standard
key code and it is set to indicate extended key code.
KEYS PROC FAR
MOV AH, 06H
MOV DL, 0FFH
INT 21H
JE KEYS ; No key was typed.
OR AL, AL ; Extended key code?
JNZ KEYS1 ; No, return with carry = 0
INT 21H ; Extended code, read again
STC ; and return with carry = 1
KEYS1: RET
KEYS ENDP
Read Entire Line With Echo:
• This service is used to read an entire line of characters. The characters read are
maintained in a buffer. Thus, this is Buffered Keyboard Input service.
• Function Code: 0A H
• Input Parameters:
DS:DX = Address of the Buffer
First byte of Buffer = Maximum Number of Characters to be read (up to 255)
• Characters are read (displaying them as they are read) until the specified number
of characters are read OR until the Enter key (code is 0DH) is typed.
Upon return:
• Second Byte of Buffer Actual number of characters read.
• Third Byte of Buffer onwards The actual characters typed.
• Hence, the Buffer Size must be 2 more than the number of characters to be read!
.MODEL SMALL
.DATA
BUF1 DB 102 DUP (?) ; Allow a maximum of 100 characters
.CODE
.STARTUP
MOV BUF1, 100 ; Char count allowed = 100
MOV DX, OFFSET BUF1
MOV AH, 0AH
INT 21H
.EXIT
END
Display One ASCII Character:
• This service allows to display a single character on the screen.
• Function Code: 02H or 06H As both of these are quite similar, we will illustrate
the use of Function Code 6 only.
• DL ASCII Character to be displayed
.MODEL TINY
.CODE
.STARTUP
MOV AH, 06H
MOV DL, 41H ; Display character “A”, ASCII code is 41H
INT 21H
.EXIT
END
Display Character String:
• This service allows the display of a string of ASCII characters.
• Function Code: 09H
• DS:DX Address of the Character String
• The Character String must be terminated with ASCII “$” char (24H)
• The character string could be of any length.
• It could include control characters like Carriage Return (0DH), Line Feed (0AH)
etc. However, the character $ is used as the terminator and thus can not be part of
the string. ($ could be displayed as a single character using Function Code 06H as
explained above.)
MODEL SMALL
.DATA
MSG1 DB 0DH, 0AH, ‘Advanced Microprocessors. $’
.CODE
.STARTUP
MOV AH, 09H
MOV DX, OFFSET MSG1
INT 21H
.EXIT
END
Terminate Program:
• EXIT directive used in all the examples described so far effects program
termination by using Function Code 4CH (Terminate Program)
• This directive inserts the following 2 lines of code:
MOV AH, 4CH
INT 21H
• Instead of .EXIT, the above 2 lines could be directly written by the programmer.
Set Interrupt Vector, Read Interrupt Vector:
• These services allow the user to set / read the interrupt vector corresponding to a
type code. This is preferred to directly manipulating the Interrupt Vector Table.
• AH 25H (Set Interrupt Vector)
AL Interrupt Vector Number
DS:DX Address of Interrupt Procedure
• AH 35H (Read Interrupt Vector)
AL Interrupt Vector Number
On return, ES:BX Address stored at the vector.
Advanced MicroprocessorsSession – XX
Modular Programming11.11.2005
Dr. K.RajanikanthM.S.Ramaiah Institute of Technology, Bangalore----------------------------------------------------------------
Learning Objectives:
• Learn to use Modular Programming Techniques.
• Understand and use Macros.
Modular Programming
Concepts:
• Modular Programming is essential for conquering complexity inherent in the
development of large, industry-strength software systems.
• The basic idea is the classical “Divide & Conquer” approach. Program is
composed from several smaller modules. Modules could be developed by separate
teams concurrently. The modules are only assembled producing .OBJ modules
(Object modules). Each module is produced from a separate Assembly Language
program.
• The .OBJ modules so produced are combined using a LINK program.
• The ML command of MASM typically used for smaller programs actually
consists of the two distinct steps of assembling to produce the object file and then
Linking the object module to produce the .EXE file.
• Here, the two steps are separated.
• This idea is illustrated in the following figure:
Concepts - 2
ASM File #1
ASM File #2
ASM File #n
Assembler
Assembler
Assembler
.OBJ file
.OBJ file
.OBJ file
Linker .EXE
A further concept that is extremely useful is that of a Library of Object Modules.
Frequently used procedures could be assembled in to object modules and these object
modules are placed in a Library file that is linked into the application. Note that only the
required object modules are pulled from the Library to be linked in to the final
application. The concept of a Library is explored in detail later.
This idea is illustrated in the following figure:
Concepts - 3
ASM File
ASM File
Library of Assembled Modules
(.OBJ files)
Assembler
Assembler
.OBJ file
.OBJ file
Linker .EXE
Assembler Features Required to Support Modular Programming:
To appreciate the features required to support Modular Programming, consider the
following development scenario:
• In Module A , we defined
BUF1 DB 10 DUP (?)
• In Module B , we wish to access BUF1, say as in
MOV DX, OFFSET BUF1
• BUF1 is not defined in Module B. Thus, when assembling Module B, we will get
the assembly error of “Undefined Symbol”. Note that the symbol is actually
defined in Module A. But, the two modules are assembled independently!
• Problem: How to make the BUF1, defined in Module A, accessible to Module B?
• Solution:
• Declare BUF1 as public in Module A
(Interpretation: Defined in this module, may be used in other modules.)
• Declare BUF1 as external in Module B
(Interpretation: Used in this module, but defined in some other module.)
BUF1 becomes a global symbol.
Its use is resolved by a Linker program.
What happens if BUF1 is declared as external in one module; but Linker
does not find its definition in any of the modules being linked together?
This will be a Link Error, something like: “Globally Unresolved
Symbol”
• Properly used, Public and External facilities allow modules to communicate with
each other, which is essential for Modular Programming.
PUBLIC and EXTRN Directives:
The following example illustrates the use of Public and External directives to achieve
communication among independently assembled modules.
PROG1.ASM, defines two symbols BUF1 and BUF2 and declares them as PUBLIC.
It also defines a Far Procedure called RDKEY and declares this also as PUBLIC.
Such a declaration allows these symbols to be accessed from other modules. Thus,
BUF1, BUF2 and RDKEY can be accessed from other modules.
File 1: PROG1.ASM
.MODEL SMALL
.DATA
PUBLIC BUF1
PUBLIC BUF2
BUF1 DB 10 DUP (?)
BUF2 DW 10 DUP (?)
.CODE
.STARTUP
PUBLIC RDKEY
RDKEY PROC FAR
MOV AH, 1
INT 21H
RDKEY ENDP
END
In another program PROG2.ASM, we make use of the symbols BUF1, BUF2 and
RDKEY. We declare them as EXTRN. Such a declaration indicates that the
definitions for these symbols are not in this module; how ever this is not to be treated
as an error. These symbols are expected to be defined in other modules which will be
specified during LINK time.
Further, note that the type of the EXTRN data items must be declared for proper
assembly. Similarly, the FAR / NEAR nature of an EXTRN procedure also must be
declared for the Assembler to generate correct code.
File 2: PROG2.ASM
.MODEL SMALL
.DATA
EXTRN BUF1:BYTE
EXTRN BUF2:WORD
.CODE
EXTRN RDKEY:FAR
.STARTUP
MOV DX, OFFSET BUF1
MOV CX, 10
L1: CALL RDKEY
STOSB
LOOP L1
MOV BUF2, AX
.EXIT
END
• We now have 2 Files: PROG1.ASM and PROG2.ASM
• These can be assembled and Linked by the following command
ML PROG1.ASM PROG2.ASM
• Another way that more clearly illustrates the Modular Programming approach is
as follows :
Only assemble (not link) the two programs separately, getting the two
.OBJ files.
Run LINK utility and specify the two .OBJ files as inputs.
Experiment in the Laboratory.
LIBRARIES:
• Frequently used procedures for a given application domain may be placed in a
“Library File” as .OBJ files.
• The Library file can be specified at LINK time.
• Only the required .OBJ files are extracted from the Library File and linked in to
the program.
• Thus, Libraries provide a powerful reuse mechanism.
LIB Command:
The LIB command provides the following facilities:
• Create a new Library file
• Add .OBJ file to a Library file.
• Delete .OBJ file from a Library file.
• Replace an existing .OBJ file in the Library with another .OBJ file with the same
name (equivalent to Delete followed by Add)
• The LIB command is used as follows:
LIB library file name
If the named Library file does not exist, the system prompts whether to create?
Type Y
It prompts for operation (operation could be specified on command line also).
The Operation can be:
+ (add) ; - (remove) ; -+ (replace)
Examples
Create a Library file called MYIO1.LIB and add the module PROG1 to the
library:
>LIB MYIO1.LIB
Copyright messages etc from the utility
Library file does not exist. Create? Y
Operations: +PROG1
List File: MYIO1
To the Library file called MYIO1.LIB add the module PROG2:
> LIB MYIO1.LIB
Copyright messages etc from the utility
Operations: +PROG2
>
To the Library file called MYIO1.LIB add the module PROG3:
>LIB MYIO1.LIB
Copyright messages etc from the utility
Operations: +PROG3
>
Alternatively, the 3 modules could be added to the Library file as shown below:
>LIB MYIO1.LIB
Copyright messages etc from the utility
Library file does not exist. Create? Y
Operations: PROG1 + PROG2 + PROG3
List File: MYIO1
>
From the Library file called MYIO1.LIB, remove the module PROG2:
> LIB MYIO1.LIB
Copyright messages etc from the utility
Operations: -PROG2
>
• List file shows:
Sizes and names of the files in the Library
Public labels available in the Library
• Once we create Library files, we can use them to link the required modules in to
the application program by specifying the Library files to the Linker. With ML or
with LINK, specify the Library files required in response to the prompt
Libraries [.lib]:
• Library files have .lib as the default extension.
Macros
Macros provide several powerful mechanisms useful for the development of
generic programs.
• A Macro is a group of instructions with a name.
• When a macro is invoked, the associated set of instructions is inserted in place in
to the source, replacing the macro name. This “macro expansion” is done by a
Macro Preprocessor and it happens before assembly. Thus the actual Assembler
sees the “expanded” source!
• We could consider the macro as shorthand for a piece of text; somewhat like a
new pseudo-code instruction.
Macros and Procedures:
Macros are similar to procedures in some respects, yet are quite different in many
other respects.
Procedure:
Only one copy exists in memory. Thus memory consumed is less.
“Called” when required;
Execution time overhead is present because of the call and return instructions.
Macro:
When a macro is “invoked”, the corresponding text is “inserted” in to the
source. Thus multiple copies exist in the memory leading to greater space
requirements.
However, there is no execution overhead because there are no additional call
and return instructions. The code is in-place.
These concepts are illustrated in the following figure:
CALL Macro invoked
RETURN
Inserted inplace
MACRO
MACRO Definition:
A macro has a name. The body of the macro is defined between a pair of directives,
MACRO and ENDM. Two macros are defined in the example given below.
Examples of Macro Definitions:
; Definition of a Macro named PA2C
PA2C MACRO
PUSH AX
PUSH BX
PUSH CX
ENDM
; Another Macro named POPA2C is defined here
POPA2C MACRO
POP CX
POP BX
POP AX
ENDM
Examples of Macro usage:
The following examples illustrate the use of macros. We first show the source with
macro invocation and then show how the expanded source looks.
Program with macro invocations:
PA2C
MOV CX, DA1
MOV BX, DA2
ADD AX, BX
ADD AX, CX
MOV DA2, AX
POPA2C
When the Macro Preprocessor expands the macros in the above source, the expanded
source looks as shown below:
PUSH AX
PUSH BX
PUSH CX
MOV CX, DA1
MOV BX, DA2
ADD AX, BX
ADD AX, CX
MOV DA2, AX
POP CX
POP BX
POP AX
Note how the macro name is replaced by the associated set of instructions. Thus,
macro name does not appear in the expanded source code. In other words, the actual
Assembler does not “see” the macros. What gets assembled is the expanded source.
This process is illustrated in the following figure:
MACROS (continued)
.ASM filewith Macros
.ASM file withMacros Expanded
MacroPreprocessor
Assemble &Link
.EXE file
MACROS with Parameters:
Macros have several other interesting and powerful capabilities. One of these is the
definition and use of macros with parameters.
A macro can be defined with parameters. These are dummy parameters. When the
macro is invoked, we provide the actual parameters. During the macro expansion, the
dummy parameters are replaced by the corresponding actual parameters. The
association between the dummy and actual parameters is positional. Thus the first
actual parameter is associated with the first dummy parameter, the second actual
parameter with the second dummy one and so on.
This is illustrated in the following example where a Macro named COPY is defined
with two parameters called A and B.
Example:
COPY MACRO A , B
PUSH AX
MOV AX, B
MOV A, AX
POP AX
ENDM
The macro is invoked in the following code with actual parameters as VAR1 and
VAR2. Thus during the macro expansion, the parameter A is replaced by VAR1 and
the parameter B is replaced by VAR2.
COPY VAR1, VAR2
The expanded code is:
PUSH AX
MOV AX, VAR2
MOV VAR1, AX
POP AX
Local Variables in a Macro:
• Assume that a macro definition includes a label RD1 as in the following example:
READ MACRO A
PUSH DX
RD1: MOV AH, 06
MOV DL, 0FFH
INT 21H
JE RD1 ;; No key, try again
MOV A, AL
POP DX
ENDM
• If READ macro is invoked more than once, as in
READ VAR1
READ VAR2
assembly error results!
• The problem is that the label RD1 appears in the expansion of READ VAR1 as
well as in the expansion of READ VAR2. Hence, the label RD1 appears in both
the expansions. In other words, the Assembler sees the label RD1 at two different
places and this results in the “Multiple Definition” error!
• SOLUTION: Define RD1 as a local variable in the macro.
READ MACRO A
LOCAL RD1
PUSH DX
RD1: MOV AH, 06
MOV DL, 0FFH
INT 21H
JE RD1 ;; No key, try again
MOV A, AL
POP DX
ENDM
• Now, in each invocation of READ, the label RD1 will be replaced,
automatically, with a unique label of the form ??xxxx ; where xxxx is a unique
number generated by Assembler. This eliminates the problem of multiple
definitions in the expanded source.
• With the use of local variable as illustrated above,
READ VAR1
gets expanded as:
PUSH DX
??0000: MOV AH, 06
MOV DL, 0FFH
INT 21H
JE ??0000 ;; No key, try again
MOV VAR1, AL
POP DX
Subsequently, if we write
READ VAR2
it gets expanded as:
PUSH DX
??0001: MOV AH, 06
MOV DL, 0FFH
INT 21H
JE ??0001 ;; No key, try again
MOV VAR2, AL
POP DX
Note how each invocation of the READ macro gets expanded with a new and
unique label, generated automatically by the Assembler, in place of the local variable
RD1. Further, note that LOCAL directive must immediately follow the MACRO
directive. Another feature to note is that Comments in Macros are preceded by ;; (two
semicolons) , and not as usual by ; (a single semicolon).
File of Macros:
• We can place all the required Macros in a file of its own and then include the file
into the source.
• Example: Suppose the Macros are placed in D:\MYAPP\MYMAC.MAC
In the source file, we write
INCLUDE D:\MYAPP\MYMAC.MAC
Advanced Features:
• Conditional Assembly
• REPEAT , WHILE, and FOR statements in MACROS
Conditional Assembly:
• A set of statements enclosed by IF and ENDIF are assembled if the condition
stated with IF is true; otherwise, the statements are not assembled; no code is
generated.
• This is an Assembly time feature; not run-time behavior!
• Allows development of generic programs. From such a generic program, we can
produce specific source programs for specific application contexts.
• Example: Assume that our generic program has the following statements:
IF WIDT
WIDE DB 72
ELSE
WIDE DB 80
ENDIF
Now the assembly language program that is generated depends on the value of
WIDT. Assume the block is preceded by
WIDT EQU 1
Then the assembled code is:
WIDE DB 72
It is important to note that the Assembler sees a source file that has only the above
statement.
Another case:
WIDT EQU 0
IF WIDT
WIDE DB 72
ELSE
WIDE DB 80
ENDIF
What gets assembled is: WIDE DB 80
There are several other directives that can be used for Conditional Assembly as
listed below:
IF If the expression is true
IFB If the argument is blank
IFNB If the argument is not blank
IFDEF If the label has been defined
IFNDEF If the label has not been defined
IFIDN If argument 1 equals argument 2
IFDIF If argument 1 does not equal argument 2
With each of the above constructs, the code that follows gets assembled only if the
stated condition is true.
REPEAT Statement:
This statement allows a block of code to be repeated the specified number of times.
This avoids repetitive typing and is much more elegant than Editor-level Copy-and-
Paste operation.
Example:
REPEAT 3
INT 21H
INC DL
ENDM
The generated code would be 3 repetitions of the block of 2 statements enclosed
within REPEAT and ENDM as shown below:
INT 21H
INC DL
INT 21H
INC DL
INT 21H
INC DL
WHILE Statement:
This statement allows a block of code to be repeated while the condition specified
with the WHILE is true.
Example: Consider the following code
SQ LABEL BYTE
SEED = 1
RES = SEED * SEED
WHILE RES LE 9
DB RES
SEED = SEED + 1
RES = SEED * SEED
ENDM
Note that SEED and the arithmetic statements involving SEED and RES are all
Assembly time actions. Apart from the initial label SQ, the only statement to actually
get repeated is DB RES.
The logic is follows: Initially the label SQ is generated. SEED is initialized to 1 and
RES is computed as 1 * 1 = 1. Now RES LE 9 is true as the value of RES is 1 which
is less than 9. So the code DB 1 is generated. The next statement within the scope of
WHILE, “SEED = SEED + 1” is executed making SEED assume the value of 2. The
next statement within the scope of WHILE is RES = SEED * SEED. This is also
executed and RES assumes the value of 4. This completes one pass of execution of
the WHILE block. So, the condition associated with WHILE is again evaluated. This
is again TRUE as 4 is less than 9. So again DB 9 is generated. Reasoning as before,
we see that DB 9 is also generated. However, in the next pass SEED is 4 and RES is
16. So the condition RES LE 9 evaluates to FALSE and WHILE loop is exited!
Thus the generated code is:
SQ DB 01
DB 04
DB 09
FOR Statement:
This is very similar to the FOR of languages like PERL. With the FOR statement, a
control variable and a list of values are specified. The control variable is successively
assigned values from the specified list and for each such value, the following block of
statements is repeated.
Example:
DISP MACRO CHR:VARARG
MOV AH, 2
FOR ARG, <CHR>
MOV DL, ARG
INT 21H
ENDM
ENDM
The outer Macro has one parameter which is specified as sequence of characters of
variable length. The inner FOR statement has two enclosed statements which will be
repeated for each value in the list <CHR>. Thus in the following illustration, DISP is
invoked with 3 characters as parameters. The two statements within FOR scope are
thus repeated 3 times with ARG successively assuming the 3 characters.
Thus, the statement
DISP ‘V’,’T’,’U’
gets expanded as
MOV AH, 2
MOV DL,’V’
INT 21H
MOV DL, ’T’
INT 21H
MOV DL, ’U’
INT 21H
Summary:
• Modular programming techniques simplify the software development process by
exploiting the classical divide and conquer approach.
• MACROS have very powerful features.
• Used properly, they can reduce effort required to develop large and complex
programs. Further, Macros make it easy to develop Generic Programs which can
be easily adapted for specific applications.
• Expertise with Modular programming techniques and Macros is essential for
developing industry-strength large scale software in Assembly Language.
Advanced MicroprocessorsSession – XXI
Data Conversion Routines15.11.2005
Dr. K.Rajanikanth-----------------------------------------------------
Learning Objectives:
Learn to develop Data Conversion Routines
• Using Algorithmic Techniques and
• Through Look –Up Tables.
Introduction:
• Often Data available in one format needs to be converted in to some other format.
Examples:
ASCII to Binary
Binary to ASCII
BCD to 7-Segment Code … … …
• Data Conversion may be based on
Algorithm
Look –Up Table
Converting from Binary to ASCII:
In many contexts, for example, when displaying a number on the screen, we must
produce a sequence of ASCII characters representing the number to be displayed.
Thus the given number must be converted to a string of equivalent ASCII characters.
• Example: Binary number: 0100 0011 = 43H = 67 D
To display this on the screen, we need to convert this binary number in to Two
ASCII characters, ‘6’ and ‘7’.
ASCII code for character ‘6’ is 36H and
ASCII code for character ‘7’ is 37H.
So, we need to produce 36H and 37H as output given 43H as input.
• Another Example: Binary number: 0000 0010 0100 0011 = 0243H = 579 D
To display this on the screen, we need Three ASCII characters, ‘5’, ‘7’ and ‘9’.
ASCII code for character ‘5’ is 35H,
ASCII code for character ‘7’ is 37H, and
ASCII code for character ‘9’ is 39H
So, we need to produce 35H, 37H and 39H as output given 0243H as input
Binary to ASCII Algorithm:
Example: Binary number: 0000 0010 0100 0011 = 579 D• Divide 579 by 10 ; Quotient = 57 ; Remainder = 9 , Save 9
• Divide 57 by 10; Quotient = 5 ; Remainder = 7 , Save 7
• Divide 5 by 10; Quotient = 0 ; Remainder = 5 , Save 5
• Quotient = 0 Conversion Complete.
• Remainders saved in the order of 9, 7, and 5.
• Retrieve remainders in the order of 5, 7, and 9.
(As the order of retrieval is the reverse of the order of producing these digits, the
most convenient technique is to Save & Retrieve the digits using Stack)
• While retrieving, add 30H to convert the digit to ASCII code and then display it
(or print it, or save it…)
• Thus the algorithm is:
While the number is not equal to 0
Divide the number by 10;
Push the remainder digit on the stack;
Set number <- quotient
While stack not empty
Pop a digit from the stack
Add 30H to covert it to ASCII and display it
Return.
This algorithm is implemented in the following program:
Binary to ASCII Program:; Input : 16-Bit Binary Number in AX
; Output: Equivalent ASCII displayed on screen
.MODEL TINY
.CODE
.STARTUP
MOV AX, 2A5H ; Test value
CALL B2A ; Binary to ASCII and Display
.EXIT
B2A PROC NEAR
PUSH DX
PUSH CX
PUSH BX
MOV CX, 0 ; Count of ASCII digits, Initialized to 0
MOV BX, 10 ; Divisor is 10
B2A1: MOV DX, 0 ; Dividend in DX, AX. So set DX = 0
DIV BX ; Divide by 10
PUSH DX ; Save remainder digit on the stack
INC CX ; Increment digit count
OR AX, AX ; Conversion completed ? (Quotient, i.e AX = 0 ?)
JNZ B2A1 ; No, continue division
; Conversion is complete as quotient in AX = 0
; Count of remainder digits is in CX
B2A2: POP DX ; Retrieve remainder in DL
ADD DL, 30H ; Convert to ASCII
MOV AH, 06H ; Console Display Function
INT 21H ; DOS Service, display digit
LOOP B2A2 ; Repeat for all digits
; Clean up & Return. AX is destroyed
POP BX
POP CX
POP DX
RET
B2A ENDP
END
Notes:
DIV instruction requires the 32-bit dividend in the register pair DX and AX.
The number to be converted (and subsequently, the quotient) is in AX. So, DX
is cleared to 0 to set up the correct dividend.
As the digits are pushed on to the Stack, their count maintained in CX is
incremented. Thus the POPs occur in a loop controlled by CX. In the same
loop, as we POP each digit, 30H is added to produce the output in ASCII.
Another Method for Binary to ASCII Conversion:
• When the input number is less than 100, an alternative, simpler method exists.
• AAM (ASCII Adjust AX After Multiplication) instruction converts value in AX
in to 2-Digit Unpacked BCD and leaves it in AX.
• Example: AX = 0027H (39 Decimal)
Execute AAM ; Now, AX = 0309H ; This is Unpacked BCD.
• Now, add 3030H to AX to get 3339H ; This is Packed ASCII representation.
• Separate the two bytes (unpack) to get the two ASCII characters representing the
given number (33H and 39H).
• Works only when the number is less than 100 as the maximum unpacked BCD
that we can have in the AX register is 0909H only.
• The following program is developed based on this idea.
; Input : Binary Number in AL, Assumed <100
; Output: Equivalent ASCII displayed on screen
.MODEL TINY
.CODE
.STARTUP
MOV AL, 2AH ; Test value
CALL B2A ; Binary to ASCII and Display
.EXIT
B2A PROC NEAR
PUSH DX
MOV AH, 0 ; AX = Number
AAM ; AX = Unpacked BCD
ADD AX, 3030H ; Convert to ASCII
PUSH AX
; Now, unpack and display
MOV DL, AH ; First Digit
MOV AH, 06H ; Display Function
INT 21H ; Display first digit
POP AX ; Retrieve value
MOV DL, AL ; Second Digit
MOV AH, 06H ; Display Function
INT 21H ; Display second digit
; Clean up & Return. AX is destroyed
POP DX
RET
B2A ENDP
END
Refinements:
• Suppose the input is: AL = 7H. What is displayed is 07
• Can we replace leading 0 with a blank so that the display looks better? Thus,
instead of 07, the display should be 7.
• Yes. We need to check if the first digit is 0. If so, display 20H (blank);
else, display the digit.
We need to modify the previous program to incorporate this check for a leading 0.
Old Code for displaying first digit:
MOV DL, AH ; First Digit
MOV AH, 06H ; Display Function
INT 21H ; Display first digit
Revised Code for displaying first digit:
ADD AH, 20H
CMP AH, 20H ; First Digit = 0?
JZ B2A1 ; Display blank (ASCII Code is 20H)
ADD AH, 10H ; Add 10H more to get the correct ASCII Code for the digit
B2A1: MOV DL , AH ; First Digit
MOV AH , 06H ; Display Function
INT 21H ; Display first digit
Incorporating this change, the program will be as shown below:
; Input : Binary Number in AL, Assumed <100
; Output: Equivalent ASCII displayed on screen
.MODEL TINY
.CODE
.STARTUP
MOV AL, 2AH ; Test value
CALL B2A ; Binary to ASCII and Display
.EXIT
B2A PROC NEAR
PUSH DX
MOV AH, 0 ; AX = Number
AAM ; AX = Unpacked BCD
ADD AX, 3030H ; Convert to ASCII
PUSH AX
; Now, unpack and display
ADD AH, 20H
CMP AH, 20H ; First Digit = 0?
JZ B2A1 ; YES. So, display a blank (ASCII Code is 20H)
ADD AH, 10H ; No, we have already added 20H. Add 10H more
; to get the correct ASCII Code for the digit
B2A1: MOV DL, AH ; First Digit itself if not 0 , Or Blank (if 0)
MOV AH, 06H ; Display Function
INT 21H ; Display first digit
POP AX ; Retrieve value
MOV DL, AL ; Second Digit
MOV AH, 06H ; Display Function
INT 21H ; Display second digit
; Clean up & Return. AX is destroyed
POP DX
RET
B2A ENDP
END
ASCII to Binary Algorithm:
In many contexts, for example, when reading a number from the key board, we get a
sequence of ASCII characters representing the number. This string of ASCII
characters must be converted to the equivalent number for further processing.
Example: Assume that ASCII character sequence ‘156’ is the input.
• 3 characters, ‘1’, ‘5’, and ‘6’; with codes as 31H, 35H, and 36H.
• Converted Binary Value must be:
0000 0000 1001 1100 = 009CH = 156 (decimal)
Conversion Procedure:
• Start with (Binary) Result = 0
• First ASCII digit 31H; Subtract 30H to get corresponding BCD digit 01H.
• Result = Result * 10 + Next BCD Digit
Result = 0 * 10 + 01 = 0000 0000 0000 0001
• Next ASCII digit 35H; Subtract 30H to get corresponding BCD digit 05H.
• Result = Result * 10 + Next BCD Digit
Result = 01 * 10 + 05 = 0000 0000 0000 1111
• Next ASCII digit 36H; Subtract 30H to get corresponding BCD digit 06H.
• Result = Result * 10 + Next BCD Digit
Result = 15 * 10 + 06 = 0000 0000 1001 1100
• ASCII digits exhausted. So, conversion is completed.
• Final Result = 0000 0000 1001 1100 = 009CH = 156 (decimal)
• Based on the above ideas, the following program implements the ASCII to Binary
Conversion.
; ASCII to Binary Program
; ASCII characters representing a number are read from key board.
; The first non-digit character (any character other than 0 through 9) typed
; signals the end of the number entry
; Result returned in AX, which is then stored in memory location TEMP.
; Result assumed not to exceed 16 bits!
; Program can be modified to accept larger numbers by implementing
; 32- bit addition.
.MODEL SMALL
.DATA
TEMP DW ?
.CODE
.STARTUP
CALL RDNUM
MOV TEMP, AX
.EXIT
RDNUM PROC NEAR
PUSH BX
PUSH CX
MOV CX, 10 ; Multiplier is 10
MOV BX, 0 ; Result initialized to 0
RDN1: MOV AH, 1 ; Read Key with Echo
INT 21H
; Check the character. If less than ‘0’ or greater than ‘9’ Number entry is over
CMP AL, ’0’
JB RDN2
CMP AL,’9’
JA RDN2
; Is digit. Update Result
SUB AL, 30H ; BCD Digit
PUSH AX
MOV AX, BX
MUL CX
MOV BX, AX ; Result = Result * 10
POP AX
MOV AH, 0 ; AX = Current Digit
ADD BX, AX ; Update Result
JMP RDN1 ; Repeat
; Non- digit. Clean Up and Return
RDN2: MOV AX, BX ; Result in AX
POP CX
POP BX
RET
RDNUM ENDP
END
Notes:
The constant multiplier 10 is held in the register CX.
In the procedure, RDNUM, the result is accumulated in the register BX and at
the end, it is moved in to register AX. The result in AX is moved, in the
calling program, in to the memory location TEMP.
The BCD digit is in AL. AH is cleared to 0 so that the 16-bit value in AX
represents the correct value and thus can be added directly to the accumulating
result in BX. This part of the code must be changed to implement 32-bit
addition if larger results are to be supported.
Using Look – Up Tables for Data Conversion:
• Often, a look-up table simplifies data conversion.
• XLAT can be used if table has up to 256 byte-entries
• Value to be converted is used to index in to the table containing conversion
values.
• As an example, we will demonstrate BCD to 7-Segment code conversion.
BCD to 7-Segment Code Conversion:
In many applications, we need to display BCD values on a 7-Segment display. The 7-
Segment display device, as the name suggests, has 7 segments which can be
independently controlled to be ON or OFF. Further, the device has a decimal point
also that can be switched ON or OFF. The 7 segments and the decimal point are
controlled by 8 bits, with one bit controlling one segment or the decimal point. The
bit value required to switch on a segment depends on whether the device is of a
Common – Anode type or Common – Cathode type. Here, we are assuming a
Common – Anode type. Thus the segment will be ON if the corresponding
controlling bit is 1 and will be off if the bit is 0.
Based on the digit to be displayed, we must determine the segments that must be ON
and the ones that must be OFF. The bits controlling the segments that must be ON are
set to 1 and the bits controlling the segments that must be OFF are cleared to 0. The
resulting bit pattern determines the value of the 7-Segemnt code that must be output.
This display structure is shown in the following figure on the next page:
BCD to 7-Segment Code - 17 –Segment display with active high (Logic 1) inputto light a segment.
a
g
d
b
ce
f
dp
Control Byte:
abcdefgdp
Bit = 1 Segment is on
= 0 Segment is off
As an example of determining the display code corresponding to a given BCD digit,
the following figure shows the display of digit 3 and the determination of the
corresponding 7-Segment code:
BCD to 7-Segment Code - 2Example: Display code for 3; No decimal point
a
g
d
b
ce
f
dp
Control Byte: a = 1; b = 1; c = 1; d = 1;e = 0; f = 0 ; g = 1; dp = 0.
11110010
Display Code for 3 = 4F H
Similarly, for other digits.
Based on the above logic, the following FAR Procedure returns the 7-Segment code
in the AL register, corresponding to the BCD digit provided as input parameter in the
AL register before calling the procedure.
; BCD to 7-Segment Code Program
; Input: AL = BCD Digit
; Output: AL = 7-Segment code.
BT7SEG PROC FAR
PUSH BX
MOV BX, OFFSET TABLE
XLAT CS: TABLE
POP BX
RET
TABLE DB 3FH ; 0
DB 06H ; 1
DB 5BH ; 2
DB 4FH ; 3
DB 66H ; 4
DB 6DH ; 5
DB 7DH ; 6
DB 07H ; 7
DB 7FH ; 8
DB 6FH ; 9
BT7SEG ENDP
Notes:
• XLAT instruction does not normally contain an operand. Here we are using the
operand (TABLE). It is a dummy operand! It is being used here only to specify
segment override. XLAT uses DS by default. Here the table is in CS. So segment
override is being specified.
• More examples are discussed in the Text Book.
Advanced Microprocessors
Session – XIV
Program Control Instructions - 1
21.10.2005
Dr. K.Rajanikanth
M.S.Ramaiah Institute of Technology, Bangalore-------------------------------------------
Learning Objectives:
Learn to use conditional and unconditional jump instructions to control flow of program.
JUMP Group of Instructions
Introduction:
• In almost any meaningful program, we need to alter the sequential flow of
execution.
• Examples:
Instruction at reset CS:IP: At rest, 8086 begins execution at the address
FFFF:0000H (absolute address of FFFF0H). There are only 16 bytes from this
location to the end of the memory space (FFFFH)! It is unlikely that any
meaningful program can be written within this space. Thus the instruction at this
reset location is usually a “long jump” instruction that transfers control to some
suitable lower address based on the available memory.
A Sorting Program: A comparison-based sorting program would need to swap or
not swap two elements based on the outcome of the comparison of the two
elements. This would mean that we need an instruction to “conditionally jump” to
some other location in the program.
Any number of such examples can be given to illustrate the need for instructions
that alter the linear flow of control, either unconditionally or conditionally.
• Unconditional and Conditional Jump Instructions allow such a control over the
execution flow.
Unconditional Jump:
• No testing of any flags is involved in deciding whether a jump is to be executed
or not.
• Control transfer occurs always.
• This is illustrated in the following figure:
Unconditional Jump: ExampleBefore:
CS=FFFF; IP=0000
After:
CS=F000; IP=8000
FFFF0 EA008000F0
F8000
UnconditionallyJump here
B80001
TargetLocation
The instructions used for such unconditional jumps are discussed in detail later.
Conditional Jump:
• Values of one or more flags are used in deciding whether a jump is to be executed
or not.
• Thus, a jump may or may not occur depending on the values of such flag bits
• This idea is illustrated in the following figure:
Conditional JUMP: ExampleCMP AX,BX
JE LAB1
MOV BX,1
… …LAB1: MOV BX,0
… …
Test the Z flag
Control is transferred here onlyif Z = 1. A conditional Jump.
Test fails i.e Z=0 No jump;Execution continues with the nextsequential instruction.
Target location
The instructions used for such conditional jumps are discussed in detail later.
Unconditional Jump Instructions:
• Unconditionally transfer control to an instruction located else where.
• 3 different instructions are available for such unconditional jumps.
• All have similar behavior; but differ in where the target instruction is allowed to
be and consequently, the instruction lengths also differ. And that is the main
advantage.
• The 3 forms are:
Short Jump: Target location must be within -128 to +127 bytes from the
address following the Jump instruction, i.e current IP. In this case, there is no
change in the CS value. Only IP is changed
Near Jump: Target location must be within -32768 to +32767 bytes from the
address following the Jump instruction, i.e current IP. In this case also, there
is no change in the CS value. Only IP is changed
Far Jump: Target location can be any where in the memory space. In this
case, CS as well as IP is changed.
Intra-Segment Jump Instructions:
• Both Short Jump and Near Jump are called intra-segment jumps also because in
both the cases, there is no change in the CS value and only IP is changed. In other
words, the jump is to a location that is within the same code segment.
• For these jumps, the target IP value is not specified as absolute value. Instead,
displacement (relative distance) from the current IP is specified.
• Thus both are relative jumps. (Called Relative Program Memory Addressing in
earlier sessions)
• Jump can be forward (to a higher address) or backwards (to a lower address).
• So, displacement must be a signed number (can be positive or negative).
• Short and Near Jumps differ in the way the displacement is specified.
Short Jump Instruction:
• Specifies one byte displacement. It is sign-extended to 16 bits and added to
current IP to get new IP.
• Displacement can be -128 to +127
• This instruction occupies 2 bytes; the first byte specifies the opcode and the
second byte specifies the relative displacement as a signed 8-bit quantity. The
format is shown below:
A short jump instruction with positive relative displacement is illustrated in the
following figure:
Opcode Displacement
EB 8-Bit Signed Value
Short Jump Instruction
1000010001
EB1A
CS = 1000 H ; IP = 0002 H (Addressfollowing the JMP instruction)Displacement = 1A H = 0001 1010Sign Extend = 001A HNew IP = 0002 + 001A = 001C H
Branch to 1000:001C
(+ve displacement; Forward Jump)10002
1001C Jmp Target
A similar situation but with a negative relative displacement is illustrated in the
following figure:
Short Jump Instruction
1000310004
EBF2
CS = 1000 H ; IP = 0012 H (Addressfollowing the JMP instruction)Displacement = F2 H = 1111 0010Sign Extend = FFF2 HNew IP = 0012 + FFF2 = 0004 H(ignoring the carry out)
Branch to 1000:0004
(-ve displacement; Backward Jump)
10005
1001110012
10010
Jmp Target
• In a typical Assembly Language Program, we use labels for branch targets and
the Assembler will automatically compute the displacement.
• We can force Short Jump to be assembled using the SHORT directive.
• Anyway, most Assemblers choose the short form if possible (that is, if the
displacement is in the range of -128 to +127)
• A program illustrating the Short Jump instruction is shown below:
XOR BX, BX
ST1: MOV AX, 1
ADD AX, BX
JMP SHORT NXT5 ; assume that the forward displacement <= 127
; some instructions
NXT5: MOV BX, AX
JMP ST1 ; assume that the backward displacement <= 128
• Generally labels are used to denote branch targets.
• However, it is also allowed to directly specify the target as $ + displacement
($ stands for current IP)
• Example: JMP $ + 2 jumps over the next 2 memory locations following the JMP
instruction. Thus if the above instruction starts at 1000:0010, the after the jump,
control is transferred to the instruction at 1000: 0014
Near Jump Instruction:
This is quite similar to Short Jump except that the displacement is specified as
16 – Bit signed integer rather than as 8-bit integer.
• Target range is thus -32768 to +32767.
• Target can be any where in the current code segment
• Instruction is 3 – Byte long. The first byte specifies the opcode and the next two
bytes specify the displacement. The format is shown in the following figure:
A near jump instruction with positive relative displacement is illustrated in the
following figure:
Opcode Displacement
E9 Low Byte High Byte
Near Jump Instruction
1000010001
E91A
CS = 1000 H ; IP = 0003 H (Addressfollowing the JMP instruction)Displacement = 201A HNew IP = 0003 + 201A = 201D H
Branch to 1000:201D
(+ve displacement; Forward Jump)10002
1201D Jmp Target
20
10003
A similar situation with a negative displacement is shown in the following figure:
Near Jump Instruction
1000410005
E9F2
CS = 1000 H ; IP = 0013 H (Addressfollowing the JMP instruction)Displacement = FFF2 HNew IP = 0013 + FFF2 = 0005 H(ignoring the carry out)
Branch to 1000:0005
(-ve displacement; Backward Jump)10006
1001110012
10010
Jmp Target
FF
An Assembly Language Program illustrating Near Jump instruction is shown below:
XOR BX, BX
ST1: MOV AX, 1
ADD AX, BX
JMP NXT5
; Some instructions
NXT5: MOV BX, AX
The above program is quite similar to Short Jump Program listed earlier except that the
displacement to NXT5 is assumed to be greater than 127 and hence the instruction JMP
NXT5 is assembled as Near Jump.
Inter-Segment Jump Instruction:
• FAR Jump is the only inter-segment jump instruction. It is called inter-segment
because the target location can be to any other code segment! Thus it is possible
that change occurs in the IP value as well as in the CS value.
• Target is directly specified as new CS:IP.
• Thus far jump can be to any where in the memory.
• This instruction is 5 – Byte long. The first byte specifies the opcode, the next 2
bytes specify the new IP value and the last 2 bytes specify the new CS value. The
format is shown in the following figure:
An example illustrating the far jump is shown in the following figure:
EALowByte
LowByte
LowByte
LowByte
IP CSOpcode
Inter-Segment Jump Instruction
1000310004
0000
Before Far Jump:CS = 2000 H ; IP = 0015 H (Addressfollowing the JMP instruction)
After the Far Jump:New CS:IP = 1000:0004 H
Branch to 10004 H10005
2001320014
20012
Jmp Target
10
EA0420011
20010
• In the ALP, we can use a label with FAR PTR directive.
• Or, we can use a label that is defined as FAR LABEL.
(A label can be FAR only if it is external to the current code segment. So, it is
preceded by EXTRN directive.)
• In such cases, the Linker will fill the CS and IP values at the link time.
• An ALP showing the far jump is shown below:
EXTRN L1:FAR
ST1: MOV AX, 1
… … …
JMP FAR PTR ST1
… … …
… … …
JMP L1
Jump with Register Operands:
• A 16-Bit register may be used as the operand for the jump instruction. (Indirect
Jump)
• Contents of the register are transferred directly into IP (no concept of relative
displacement).
• This option is available for Near Jump only.
• Example: Assume BX = 0080H
After the execution of JMP BX instruction, the control is transferred to the
address 0080H in the current code segment.
Indirect Jump Using Index:
• Uses [] form of addressing to directly access a table of jump addresses.
• FAR PTR directive indicates a far jump ( jump table is assumed to contain
double words giving CS, IP values)
• Otherwise a near jump is indicated. ( jump table is assumed to contain words
giving IP values)
• This form is some times called Double Indirect Jump.
• Example: JMP TABLE [SI]
Fetch the word, using indexed addressing, at the offset of TABLE [SI] from the
current code segment and copy that value into IP. (Near Jump)
• Example: JMP FAR PTR [SI]
Fetch the double word, using indexed addressing, at the offset of [SI] from the
current code segment and copy the values into IP and CS.
Conditional Jump
• Conditional jumps are always short jumps (relative displacement is -128 to +127).
• Based on the values of one or more flags, jump to target address may occur or
execution may continue with the next sequential instruction.
• Usually preceded by instructions like CMP, SUB, TEST, AND etc which affect
the flags.
Example:
CMP AX, BX
JZ LAB1
MOV AX, BX
LAB1:MOV CX, AX
… … …
• In the above program, equality of the operands is tested based on the Z flag.
• Conditional jumps following general relative magnitude comparison are more
complicated. Consider the comparison of FEH with 1AH. Is FEH > 1AH ?
The answer depends on how we interpret the numbers!
• Interpreted as Unsigned integers, 0FE H = 254 in decimal and 1A H = 170 in
decimal. Thus 0FE H > 1A H is true.
• Interpreted as Signed integers using 2’s Complement system, 0FE H = -2 in
Decimal and 1A H = 170 Decimal. Thus 0FE H > 1A H is false!
• Thus, we have one set of conditional jump instructions that are to be used if the
numbers are to be interpreted as Unsigned Integers and another set of
conditional jump instructions that are to be used if the numbers are to be
interpreted as Signed Integers.
• After comparison of Unsigned integers:
Mnemonic Condition Operation
JA Z=0 and C=0 Jump if above
JAE C=0 Jump if above or equal
JB C=1 Jump if below
JBE Z=1 or C=1 Jump if below or equal
• After comparison of Signed integers:
Mnemonic Condition Operation
JG Z=0 and S=O Jump if greater than
JGE S=O Jump if greater or equal
JL S< >O Jump if less than
JLE Z=1 or S< >O Jump if less or equal
(Both S and O Flags are required to test the condition when comparing signed numbers!)
• After comparison of Signed or Unsigned integers:
Mnemonic Condition Operation
JE or JZ Z=1 Jump if equal or Jump if Zero
JNE or JNZ Z=0 Jump if not equal or Jump if not Zero
• Alternative, less often used mnemonics also exist.
JA same as JNBE JG same as JNLE
JAE same as JNB JGE same as JNL
JB same as JNAE JL same as JNGE
JBE same as JNA JLE same as JNG
• Other Conditional Jump Instructions:
Mnemonic Condition Operation
JC C=1 Jump if carry set
JNC C=0 Jump if no carry
JO O=1 Jump if overflow
JNO O=0 Jump if no overflow
JS S=1 Jump if sign is set
JNS S=0 Jump if no sign
• Some more Conditional Jump Instructions:
Mnemonic Condition Operation
JP or JPE P=1 Jump if parity set or Jump if parity is even
JNP or JPO P=0 Jump if no parity or Jump if parity is odd
JCXZ CX = 0 Jump if CX = 0
(Note that the last instruction, JCXZ is some what different from the rest in the sense
that it tests the contents of CX register rather than flags. This instruction, generally
used in loops, is illustrated in later sessions. Programs illustrating other conditional
jump instructions are also discussed in later sessions.)
Advanced MicroprocessorsSession – XV
Program Control Instructions - 225.10.2005
Dr. K.Rajanikanth
M.S.Ramaiah Institute of Technology, Bangalore----------------------------------------------------------------
Learning Objectives:
• Learn to use LOOP instruction.
• Understand machine control instructions (WAIT, ESC, NOP, HLT & LOCK
Prefix)
• Learn to use Procedures
LOOP Instruction:
• Program loops are quite common. Most of the counting loops have a typical
structure that is shown below:
MOV CX, 10H ; Initialize the count that determines the number of
; times the loop is to be executed.
Start1: Instructions constituting the loop body
DEC CX ; Decrement counter
JNZ Start1 ; Repeat if not over
If the pair of instructions that test whether the loop body is to be executed again or
not, that is the instructions, DEC CX and JNZ Start1, could be combined in to
one instruction, we would get more elegant and clearer program.
The LOOP instruction does so combine the above pair of instructions.
Thus the single instruction:
LOOP LAB1
is equivalent in effect to the two instructions:
DEC CX
JNZ LAB1
Conditional LOOP Instructions:
• These instructions are similar to LOOP instruction except that equality (Z flag) is
also tested. This allows a loop to be controlled by a count as well as a comparison
test (like in the case of String instructions).
• There are two such instructions.
• LOOPE (Loop While Equal) or LOOPZ
Exit the loop if the condition is not equal or if CX decrements to 0.
• LOOPNE (Loop While Not Equal) or LOOPNZ
Exit the loop if the condition is equal or if CX decrements to 0.
ESC Instruction
• This instruction is related to 8087 Numeric Data Coprocessor. Details of 8087 are
discussed in later sessions. Briefly, 8087 provides support for floating point
operations and works as a coprocessor to 8086. It
– Shares Pin bus with 8086.
– Implements floating point arithmetic
– and Has its own instruction set
• The program has instructions for 8086 as well as 8087. How does 8087 know the
instruction is for itself? The solution to this problem is the ESC instruction.
• ESC indicates that it is 8087 instruction. Opcode has 11011 as the higher-order 5
bits. Thus ESC is never used by itself.
• Generated by Assembler automatically when 8087 mnemonic is used!
Consequently, ESC is never coded directly by the programmer.
WAIT Instruction
• Monitors the TEST/ pin of 8086.
• At the time of executing this instruction, if
TEST/ pin is LOW , there is no effect; execution simply continues with the next
instruction. However, if
TEST/ is HIGH , then 8086 waits in an “idle” state until TEST/ returns to LOW.
• TEST/ is sampled during leading edge of CLK in each clock cycle during
“waiting”.
• This instruction is generally used in conjunction with 8087.
• 8086 and 8087 can execute in parallel (concurrently)
• WAIT instruction allows synchronization between the concurrently executing
8086 and 8087.
• When 8086 needs the “result” from 8087, it executes the WAIT instruction.
• TEST/ pin of 8086 is connected to the BUSY pin of 8087.
• When 8087 is busy executing its instruction, it sets its BUSY pin = HIGH. Thus
TEST/ of 8086 will also be HIGH. This forces 8086 to “wait” for the completion
of 8087 activity.
• When 8087 is not executing its instruction, its BUSY pin = LOW and thus the
TEST/ of 8086 will also be LOW. This allows 8086 to continue its execution.
• In this manner, synchronization between 8086 and 8087 is achieved.
• More on this topic in the session on 8087.
NOP Instruction
• As the name implies, it is a no operation instruction!
• Takes a short time to execute; otherwise no effect.
• Used in early days to provide for manual code patches. Some NOP instructions
would be written every 100 bytes or so. When code was to be patched, the space
occupied by the NOP instructions was used. However, this is irrelevant in modern
times because the program development usually is based on Assemblers nad
manual coding is no more common.
• Another use for this instruction is that it could be used for producing short time
delays if delay accuracy is not of concern.
HLT Instruction
• As the name implies, it “halts” the program; the processor enters the “HALT”
state.
• An interrupt or a hardware reset will force the 8086 out of the “HALT” state.
• May be used when the program has to wait for an interrupt to occur; but rarely
used so in practice.
• In the early days, this instruction was used in the trainer kits as the last instruction
of a user program. It is no more used in this fashion. In fact, presently it is rarely
used for any other purpose either!
LOCK Prefix
• LOCK can be prefix of an instruction.
• When such an instruction is executed, the LOCK/ pin of 8086 is activated (forced
LOW). Now, another bus master can not gain control of the bus until the end of
the “bus lock”. Thus the Lock prefixed instruction executes as an indivisible
instruction even if it has several memory cycles. (Without the LOCK prefix, the
bus could be taken over by another bus master after a memory cycle, even if the
current instruction is not completed!)
• This feature is useful for implementing indivisible “read – modify-write” kind of
operations that are necessary in multi-processor systems.
• Example: LOCK: XCHG AL, SEM1
The instruction is executed without the possibility of another bus master
intervening.
Instruction shown above can be used in implementing semaphores in a multi-
processor system.
Procedures
• Procedure or a subroutine or a function is a key concept for modular
programming, the essential way to conquer complexity. It is an application of the
general divide-and-conquer strategy. This idea is used in high-level language
programs as well as in assembly language programs.
• A procedure is a reusable set of instructions that has a name.
• Only one copy of the procedure is stored in the memory; and it can be “called” as
many times as needed.
• As only one copy is stored, it saves memory; but has execution time overhead for
the “call” and “return” operations.
• Macros to be studied later are faster but consume more space.
• “CALL” transfers control to the procedure like with a jump; but unlike a jump,
procedure has a “RETURN” instruction which returns control to the instruction
following the CALL instruction! In order to implement such a return, the
necessary information is stored on a stack, before transferring control to the
procedure.
• Further, nested procedures calls are possible. In other words, Procedure A can call
Procedure B which in turn calls Procedure C. After completing Procedure C,
control returns to Procedure B and after completing Procedure B, control returns
to Procedure A. Logically, such a nesting of calls can be to any level, though in
practice Assemblers impose implementation-dependent limits on the nesting
depth.
• It is also possible for a Procedure to call itself (a recursive procedure). Of course,
to avoid infinite regress, the procedure would have an alternative that would not
involve recursion. Examples of recursive procedures are described in later
sessions.
• These ideas are illustrated in the following figures:
• From the above figure we see that return addresses are known in one order and
are used for implementing “return” in exactly the reverse order. Thus a Stack
would be the most convenient data structure for storing return addresses
Coding Procedure and Procedure - Related Instructions:
• Call can be to a procedure in the same code segment. In such a case, we specify
only IP as relative distance or indirectly as actual value. This is known as NEAR
CALL.
• Call can be to a procedure in a different code segment. I such a case, we need to
specify both IP and CS (directly or indirectly). This is known as a FAR CALL
• In ALP, procedure starts with PROC directive and ends with ENDP directive.
• Each directive appears with the name of the procedure.
• PROC directive is followed by the type of procedure: NEAR or FAR.
• NEAR or FAR can be followed by USES statement.
• USES statement allows specification of registers which are automatically pushed
on to the stack and popped from the stack within the procedure.
Near CALL Instruction:
• Similar to Near Jump except that current IP is saved on the stack before
transferring control to the new IP with CS remaining the same.
• Displacement is specified as 16 – Bit signed integer. Target range is thus -32768
to +32767 and consequently, target can be any where in the current code segment
• This Instruction is 3 – Byte long and the format is as shown below:
E8 Low Byte High Byte
Displacementopcode
The operation of this instruction is illustrated in the following figure:
Near CALL Instruction
1000010001
E91A
CS = 1000 H ; IP = 0003 H (Addressfollowing the CALL instruction)Displacement = 201A HNew IP = 0003 + 201A = 201D H
Push current IP (0003) on to stack &Branch to 1000:201D
10002
1201D Near Procedure
20
10003
The saving of the return address is illustrated in the following figure:
Near CALL Instruction: Saving Return Address
1000410005
0300
Saving IP:Before CALL:SS = A000 H ; SP = A000 HIP = 0003
10006
AFFFEAFFFF
AFFFD
In ALP, NEAR indicates near procedure. The following program fragment illustrates the
coding and using of a near procedure:
ST1 PROC NEAR USES BX
MOV AX, 1
ADD AX, BX
RET
ST1 ENDP
… … …
CALL ST1
FAR CALL Instruction:
• FAR CALL is like FAR JMP in the sense that it can call a procedure available
any where in the code space.
• In this case, the target address is directly specified as new CS:IP.
• Both current IP and CS are saved on the stack and then control is transferred to
the new CS:IP
• The instruction is 5 – Byte long. The first byte specifies the opcode, the next two
bytes specify the new IP value and the next two bytes specify the new CS value.
The format is shown below:
E8 LowByte
HighByte
IPopcode
LowByte
HighByte
CS
The operation of the Far Call instruction is illustrated in the following figure:
FAR CALL Instruction
1000310004
0000
Before Far CALL:CS = 2000 H ; IP = 0015 H (Addressfollowing the CALL instruction)
After the Far CALL:New CS:IP = 1000:0004 H
Save IP & CS on stack and
Branch to 10004 H10005
2001320014
20012
Far Procedure
10
9A0420011
20010
• Example:
SUM1 PROC FAR
… … … … … …
SUM1 ENDP
Now, a CALL to SUM1 is assembled as FAR CALL.
CALL with Register Operands:
• As with JMP, 16-Bit register may be used as the operand for the CALL
instruction. (Indirect CALL)
• Again, as with JMP, contents of the register are transferred directly into IP (no
concept of relative displacement).
• This is always a Near CALL.
• Example: Assume BX = 0080H. Now the execution of the instruction:
CALL BX
calls the procedure at 0080H in the current code segment (Near Call).
Indirect CALL Using Index:
• Like the corresponding JMP instruction, this instruction uses [] form of
addressing to directly access a table of CALL addresses.
• FAR PTR directive indicates a far CALL ( the table is assumed to contain double
words giving CS, IP values)
• Otherwise a near CALL is indicated. ( the table is assumed to contain words
giving IP values)
• This form is called Indirect Memory CALL also.
• Example: CALL TABLE[SI]
Fetch the word, using indexed addressing, at the offset of TABLE[SI] from the
current code segment and CALL the near procedure at that address.
• Example: CALL FAR PTR [SI]
Fetch the double word, using indexed addressing, at the offset of [SI] from the
current code segment and CALL the far procedure at that address.
Return from Procedure:
• We use a RET instruction to “return” from the called procedure.
• The control returns to the instruction following the CALL instruction in the
calling program. Corresponding to the two varieties of CALL instructions (near &
far), two forms of RET instructions (near & far) exist.
• Near RET instruction pops a 16-Bit word from the stack and places it in the IP.
• Far RET instruction pops two 16-Bit words from the stack and places them in IP
& CS.
• In ALP, RET is written within the procedure, before the ENDP directive and the
Assembler will automatically select the proper RET instruction!
• Another form: RET immediate value
Example: RET 6
In this case, after popping return address from the stack, the specified number (in
this case, 6) is added to SP, effectively removing some (in this case 3) words from
the stack! These words could have been pushed on to stack before calling. This is
the scheme followed by compilers. Examples are discussed in later sessions.