This level is between the microarchitecture level and the operating system level (level 2). This was the first developed level. This level forms the interface between the hardware and the software. This makes it possible to execute programs written in different higher level languages. The programs are translated to ISA level and the hardware can then execute them. The ISA level defines the interface between the compilers and the hardware. It is a language that both of them have to understand. The higher level programs are compiled to an ISA program. This ISA program is then executed by microprogram or hardware. So a computer architect while designing a machine must consult with both compiler writers and hardware engineers to incorporate the features both of them require at the ISA level. They must also make it compatible so that can run old existing programs.
Thus a good ISA should define a set of instructions that can be implemented efficiently in current and future technologies, resulting in cost-effective designs over several generations. They should also provide a clean target for compiled code.
ISA-level code is what a compiler outputs. The compiler writer must know what the memory model is, what registers there are, and what data types and instructions are available. At the ISA level, most machines operate on two modes: Kernel mode runs the operating system allowing all instructions to be executed, while the user mode runs application mode and does not permit execution of certain sensitive instructions (those that directly manipulate the cache).
Memory models
All computers divide memory into cells that have consecutive addresses. The most common cell size at present is 8 bits (called a byte), although sizes from 1 to 60 bits are in use. An ASCII (American Standard Code for Information Interchange) character is 7 bits, which with a parity bit would be a byte. Bytes are grouped into 4-byte (32-bit) or 8-byte (64-bit) words. Words are usually aligned with their natural boundaries. That is a 4-byte word must begin at 0, 4, 8, etc. and not at 1, 2, 3, 5, 6, 7, etc. A 8-byte word begins at 0, 8, 16, etc.
Most machines have a single linear address space at the ISA level, extending from 0 to a maximum of 232 bytes or 264 bytes. Some machines have separate address spaces for instructions and data, so that an instruction fetch at address 8 goes to a different address space than a data fetch at address 8. The advantage here is that it is possible to have 232 bytes of program and an additional 232 bytes of data while using only 32-bit addresses.. In addition, all writes automatically go to data space, so it is impossible to accidentally overwrite the program. This is not the same as a split level 1 cache, which only has one address space, with different caches storing different parts.
The purpose of registers is to control execution of the program, hold temporary results, etc. Some registers such as TOS and MAR are visible only at the microarchitecture level while others are also visible at the ISA level. ISA level registers are divided into two categories: Special purpose registers include the program counter (PC), stack pointer (SP) and registers with specific functions, while general purpose registers hold key local variables and intermediate calculation results. Their main function is to provide access to heavily used data, avoiding memory access. RISC (Reduced Instruction Set Computers) have fast CPU's (Central Processing Units) and relatively slow memories have at least 32 general purpose registers.
In addition to the ISA level registers visible to user programs, there are a substantial number of special purpose registers available only in kernel mode. They control caches, memory, I/O (Input/Output) devices, and other hardware features. Since they are used only by the operating system, the compilers and users need no knowledge of them.
One control register used by both kernel and user is a flags register or PSW (Program Status Word). This register holds the various miscellaneous bits needed by the CPU. The most important bits are the condition codes. These bits are on every ALU cycle and reflect the status of the result of the most recent operation. Typical condition bits include
N - Set when the result was Negative
Z - Set when the result was Zero
V - Set when the result caused an oVerflow
C - Set when the result caused a Carry out of the
left most bit
A - Set when there was a carry out of bit 3 (Auxiliary
carry)
P - Set when the result had even Parity
The importance of the condition lie in the fact that comparison and conditional branch instructions (i.e., conditional jump instructions) use them. For example the CMP instruction subtracts two operands and sets the condition codes based on the difference. If the operands are equal, the difference will be zero and the Z condition code bit in the PSW will be set. A subsequent BEQ (Branch Equal) instruction tests the Z bit and branches if it is set. Other PSW fields include machine mode (user or kernel), trace bit (used for debugging), CPU priority level, and interrupt enable status. Often the PSW is readable in user mode, but some of the fields can be written only in the kernel mode.
The main feature of the ISA level is its set of machine instructions, which control what it can do. LOAD and STORE move data between memory and registers. Arithmetic instructions for calculations, Boolean instructions and instructions for comparing data items and branching on the results.
Pentium II ISA Level
Introduced by Intel the Pentium II processor has evolved over many generations. 4004 was the first chip. This was followed by the 8-bit chip 8008 which led to the 8080. They were followed by the 8086 and the 8088 processors, 16-bit machines with 8-bit data bus. Their successor was another 16-bit machine, the 80286 with larger address space consisting of 16,684 64K segments rather than a linear 224 -byte memory. The 80386 was the first 32-bit machine in the Intel family called the IA-32. In real mode all features added since 8088 are turned off. So if a program does something wrong, the whole machine just crashes. The virtual 8086 mode makes it possible to run old 8088 programs in a protected mode. The operating system creates a special isolated environment that acts like an 8088, except that if its program crashes, the operating system is notified instead of the machine crashing. Four privilege levels are available and controlled by bits in the PSW. Level 0 corresponds to the kernel mode on other computers and has full access to the machine and is used by the operating system. Level 3 is for user programs. It blocks access to certain critical instructions and control registers to prevent a rogue user program from bringing down the entire machine. Levels 1 and 2 are rarely used.
The Pentium II has a huge address space, with memory divided into 16,384 segments, each going from address 0 to 232-1. However, most operating systems (including UNIX and all versions of Windows) support only one segment, so most linear programs effectively see a linear address space of 232 bytes, part of being occupied by the operating system. Every byte in the address space has its own address, with words being 32 bits long. Words are stored in the little endian format (the low order byte has the lowest address).
Sixteen of the Pentium II registers are described. The first four EAX, EBX, ECX, and EDX are 32 bit general purpose registers. EAX is the main arithmetic register; EBX holds pointers (memory addresses); ECX used in looping; EDX for multiplication and division, where with EAX it holds 64 bit products and dividends. Their 32 bits are divided into upper and lower order 16 bits (AX, BX, CX, and DX). These lower order 16 bits are further divided into 8 bit upper (AH, BH, CH, and DH) and 8 bit lower (AL, BL, CL, and DL), making it easier to manipulate 16 and 8 bit quantities.
The next registers are ESI and EDI which hold pointers into memory, ESI to the source and EDI to the destination. EBP is also a pointer register pointing to the base of the current stack frame, when it is called a frame pointer. The ESP is a stack pointer.
CS, SS, DS, ES, FS, and GS are 16 bit segment registers. EIP (Extended Instruction Pointer) is the program counter, and the last register EFLAGS is the PSW. For more information on the Pentium II click below
The SPARC Architecture was first introduced in 1987 by Sun Microsystems. The architecture was labeled RISC. The original SPARC was a 32-bit but the UltraSPARC is a 64-bit machine. Addressable memory is a linear array of 264 (18,446,744,073,709,551,616) bytes, so large that no current machine can implement it. The byte order is big endian (the higher order byte has the lowest address), but can be turned into little endian by setting a bit in the PSW.
It has two groups of registers: 32 64-bit general purpose (R0 through
R31) explained in the table below and 32 floating point registers.
|
|
|
|
| R0 | G0 | Hardwired to 0. Stores into it are just ignored |
| R1 - R7 | G1 - G7 | Holds global variables |
| R8 - R13 | O0 - O5 | Holds parameters to the procedure being called |
| R14 | SP | Stack Pointer |
| R15 | O7 | Scratch register |
| R16 - R23 | L0 - L7 | Holds local variables for the current procedure |
| R24 - R29 | I0 - I5 | Holds incoming parameters |
| R30 | FP | Pointer to the base of the current stack frame |
| R31 | I7 | Holds return address for the current procedure |
All the general registers are 64 bits wide, and except for R0, can be read and written by a variety of load and store instructions. If floating point numbers are loaded into general registers, an operation will produce utter nonsense.
The global variables store constants, variables, and pointers that are required for procedures. here are 32 general purpose registers. The register CWP (Current Window Pointer) keeps track of which register set is currently in use.
The UltraSPARC II is a load/store architecture. The only operations that access memory directly are LOADs and STOREs, instructions to move data between the registers and memory.
All computers need data, which can be financial, commercial, scientific, engineering, etc. Hardware support means that one or more instructions expect data in a particular format, and the user is not free to pick a different format. For instance, the negative sign is the leftmost bit, whereas in accounting, the negative sign is placed on the right. For large numbers double precision, that is two 32-bit registers are required to store data since one can only store 232 = 4,294,967,296 or about 4 billion unsigned. Data can be numeric or nonnumeric.
Numeric Data Types
Numeric types are integers (to count or to identify) and non integers. Both can be signed or unsigned. Lengths of integers are 8, 16, 32, or 64 bits. They are stored in two's complement binary notation. For more details click: binary Unsigned numbers have no sign bit. All bits are used. So a 32-bit word can hold an unsigned integer in the range 0 to 232 - 1, inclusive. However, a two's complement signed 32-bit word can only handle numbers from -231 to 231 - 1.
Floating point numbers are used in case of non integers. If the numbers are very large or very small, then the scientific notation of the form n = f x 10e is used Here f is the fraction, or mantissa, and e is a positive or negative exponent.
For more details: Floating Point Numbers
They have lengths of 32, 64, or even 128 bits. Most computers have instructions for doing floating-point arithmetic. Many computers have separate registers for holding integer operands and for holding floating-point operands.
Some programming languages, notably COBOL, allow decimal numbers as a data type. These machines support decimal numbers in hardware by encoding a decimal digit in 4 bits and then packing two decimal digits per byte (binary coded decimal format). But arithmetic does not work correctly on packed decimal numbers, so special decimal-arithmetic-correction instructions are needed, which must know the carry out of bit 3. The Y2K (Year 2000) problem was caused by COBOL programmers who decided that it would be cheaper to represent the year as two decimal digits rather than as a 16-bit binary number.
Nonnumeric Data Types
Consecutive runs of character strings are delimited by a special character at the end. Boolean values can be either true or false. A single bit can be used 0 if false and 1 if true. But bytes or words are used as bits do not have their own addresses and so are difficult to access. An exception is a bit map when there is an entire array, so a 32-bit word can hold 32 Boolean values.
An instruction consists of an opcode only, or an opcode followed by one, two, or three addresses which specify details of the operand. On some machines, all instructions have the same length, which is simpler and makes decoding easier, but is wasteful, as all instructions have to be as long as the longest one. Other machines have instructions of different lengths, shorter than, same length as, or longer than word length.
Expanding Opcodes
Consider an (n + k) bit instruction with k-bit opcode and a single n-bit address. This instruction allows 2k different operations and 2n addressable memory cells. Alternately, the same n + k bits could be broken up into a (k - 1) bit opcode, and an (n + 1) bit address, that is only half as many instructions (2k -1) but either twice as much memory addressable, (2n + 1) or the same amount of memory but with twice the resolution. A (k + 1) bit opcode and an (n - 1) bit address gives more operations, but less addresses or poorer resolution. These schemes are called expanding opcodes.
As an example, consider a machine with 16 registers in which instructions are 16 bits long, and addresses are 4 bits long. One design would be a 4-bit opcode and three addresses in each instruction, giving 16 three-address instructions. But if the designers need 15 three-address instructions, 14 two-address instructions, 31 one-addres instructions, and 16 instructions with no address at all, they can use opcodes 0 to 14 as three-address instructions but interpret opcode 15 differently.
A large portion of the bits in a program are used to specify where operands come from, in addition to which operations are performed on them. An ADD instruction requires the specification of three operands: two sources and a destination. So ADD must know where to find the operands and the location of the result. If memory is stored in 32 bits, this requires three 32-bit addresses in addition to the opcode. The addresses take up far more bits than the opcode.
If the same operand is to be used several times, it can be moved into a register. Access time is faster and it takes fewer bits to specify the operand. Only 5 (25 = 32) are needed per address, so 15 bits for all three instead of 96 bits. But it must first be loaded into a register. That requires more specification bits than simply specifying the memory location. A LOAD instruction to move the operand into the register, needing an opcode, full memory address and the specification of the target register.
Or one or more operands can be specified implicitly by using a single specification for a source operand and for a destination. For example using a two-address instruction in an ADD instruction:
DESTINATION = SOURCE1 + SOURCE2 would be
REGISTER2 = REGISTER2 + SOURCE1
The original contents of REGISTER2 will be destroyed. If the original value is required later, it must be first copied into another register.
By using a stack, we do not need any addresses. The IJVM IADD instruction has no address. Both sources and the destination are implicit.
Immediate Addressing
The simplest way is for the address part of the instruction to contain the operand itself rather than an address or other information describing where the operand is. Such an operand is called an immediate operand as it is automatically fetched from memory at the same time the instruction itself is fetched. Table below shows an immediate instruction for loading 4 into register 1.
|
|
|
|
It does not require extra memory reference to fetch the operand, but only a constant (4 in this case) in be supplied. Also the number of values is limited by the size of the field.
Direct Addressing
Here the full address s given. The instruction will always access exactly the same memory location. So while the value can change, the location cannot. It can only be used to access global variables whose address is known at compile time.
Register Addressing
Similar to direct addressing but specifies a register (fast access and short addresses) instead of a memory location. many compilers determine which variables will be accessed most often (example loop index) and these are placed in registers.
Register Indirect Addressing
The operand being specified comes from or goes to memory, but its address is not hardwired into the instruction, as in direct addressing. When used in this fashion, the address is called a pointer It can reference memory without a full memory address in the instruction. It can also use different memory words on different executions of the instruction.
Imagine a loop that steps through the elements of a 1024-element one-dimensional integer array to compute the sum of the elements in register R1. Outside the loop, some other register, R2, can be set to point to the first element of the array, and another register, R3, can be set to point to the first address beyond the array. With 1024 integers of 4 bytes each, if the array begins at A, the first address beyond the array will be A + 4096. A generic assembly program for computing the sum of the elements of an array is shown below:
MOV R1,#0
; accumulate the sum in R1, initially 0
MOV R2,#A
; R2 = address of the array A
MOV R3,#A+4096
; R3 = address of the first word beyond A
LOOP:
ADD R1,(R2)
; register indirect through R2 to get operand
ADD R2#4
; increment R2 by one word (4 bytes)
CMP R2,R3
; are we done yet?
BLT LOOP
; if R2 < R3, we are not done, so continue
The first three instructions use register mode for the first operand (the destination), and immediate mode for the second operand ( a constant indicated by the # sign). The second instruction puts the address of A in R2, not the contents. This is what the # sign tells the assembler. The third instruction puts the address of the first word beyond the array in R3. The body of the loop does not contain any memory address, using register and register indirect mode in the fourth instruction. It uses register and immediate mode in the fifth instruction, and register mode twice in the sixth instruction. A short fast loop results avoiding memory addresses completely.
Indexed Addressing
This references memory words at a known offset from the register. (Example IJVM where local variables are referenced by giving their offset from LV) Addressing memory by giving a register (explicit or implicit) plus a constant offset is called indexed addressing. A generic assembly program for computing the OR of Ai AND Bi for two 1024-element arrays is shown below:
MOV R1,#0
; accumulate the OR in R1, initially 0
MOV R2,#0
; R2 = index, i, of current product: A[i] AND B[i]
MOV R3,#4096
; R3 = first index value not to use
LOOP:
MOV R4,A(R2)
; R4 = A[i]
AND R4,B(R2)
; R4 = A[i] AND B[i]
OR R1,R4
; OR all the Boolean products into R1
ADD R2, #4
; i = i + 4 (step in units of 1 word = 4 bytes)
CMP R2,R3
; are we done yet?
BLT LOOP
; if R2 < R3, we are not done, so continue
There are four registers:
1. R1- holds the accumulated
OR of the Boolean product terms
2. R2 - The index, i, that is
used to step through the arrays
3. R3 - The constant 4096, which
is the lowest value of i not to use
4. R4 - A scratch register for
holding each product as it is formed
After initializing the registers, the six-instruction loop is entered. The instruction at LOOP fetches Ai into R4. The calculation of the source uses indexed mode. A register, R2, and a constant, the address of A, are added together and used to reference memory. The sum of these two quantities goes to memory, but is not stored in any user-visible register. The notation
MOV R4,A(R2)
means that the destination uses a register mode with R4 as the register
and the source uses the indexed mode, with A as the offset and R2 as the
register. If A has the value, say 124300, the actual machine instruction
would be:
|
|
|
|
|
The first time through the loop, R2 is 0 (initialized) so the memory word addressed is A0, at address 124300. This word is loaded into R4. The next time through the loop, R2 is 4, so the memory word addressed is A1, at 123404, and so on
Based-Indexed Addressing
Some machines have an addressing mode in which the memory address is computed by adding up two registers plus an (optional) offset. One of the registers is the base and the other is the index. Using this method, outside the loop we could have put the address of A in R5 and the address of B in R6. Then the instruction at LOOP and its successor can be replaced with:
LOOP:
MOVE R4,(R2+R5)
AND R4,(R2+R6)
Reverse Polish Notation
In mathematics, the operators (+, -, *, /, ^ ) are placed between the
variables or constants, example x + y. This is known as infix
notation.
Prefix
is when the operators are placed before, example + x y. In computers
we use stacks to do the computations. In this case, the operators
are placed after the variables or constants, example x y +. This
is called postfix or reverse Polish notation, after the Polish
logician J.
Lukasiewicz
who studied the properties of this notation. The advantages are:
1. Any formula can be expressed without parentheses.
2. It is convenient for evaluating formulas on computers
with stacks.
3. Reverse Polish eliminates the nuisance of operator
precedence.
Evaluation of Reverse Polish notation Formulas
(8 + 2 x 5) / (1 + 3 x 2 - 4) in IJVM corresponds to 8 2 5 x + 1 3 2
x + 4 - in Reverse Polish.
|
|
|
|
|
|
|
8 2 5 x + 1 3 2 x + 4 - / | BIPUSH 8 | 8 |
|
|
2 5 x + 1 3 2 x + 4 - / | BIPUSH 2 | 8, 2 |
|
|
5 x + 1 3 2 x + 4 - / | BIPUSH 5 | 8, 2, 5 |
|
|
x + 1 3 2 x + 4 - / | IMUL | 8, 10 |
|
|
+ 1 3 2 x + 4 - / | IADD | 18 |
|
|
1 3 2 x + 4 - / | BIPUSH 1 | 18, 1 |
|
|
3 2 x + 4 - / | BIPUSH 3 | 18, 1, 3 |
|
|
2 x + 4 - / | BIPUSH 2 | 18, 1, 3, 2 |
|
|
x + 4 - / | IMUL | 18, 1, 6 |
|
|
+ 4 - / | IADD | 18, 7 |
|
|
4 - / | BIPUSH 4 | 18, 7, 4 |
|
|
- / | ISUB | 18, 3 |
|
|
/ | IDIV | 6 |
INSTRUCTION TYPES
Dyadic operations combine two operands to produce a result. All
ISAs perform additions, subtractions, multiplications, divisions, and Boolean
AND, OR, NOT, EXCLUSIVE OR, NOR, and NAND operations. An important
use of AND is to extract bits from words. It can be used to
mask a part of a message. AND with 0 will cause 0 to be printed.
AND with 1 will have the exact message. In the example below A is
the original message. Only bits 9 to 16 are to be forwarded.
The rest of the message is to be masked. AND with B with 0 in the
masked part and 1 in the forwarded part will achieve it.
A
10110111 10111100 11011011 10001011
B (mask) 00000000 11111111
00000000 00000000
A AND B 00000000 10111100 00000000 00000000
forwarded message.
A similar result may be obtained using OR. Here 1 is used to mask
and 0 to forward.
A
10110111 10111100 11011011 10001011
B (mask) 11111111 00000000
11111111 11111111
A OR B 11111111 10111100 11111111 11111111
forwarded message.
A combination of AND and OR can pack bits to change the rightmost 8 bits of a 32-bit word, without disturbing the other 24 bits. First the unwanted 8 bits are masked out and then the new characters are ORed in.
A
10110111 10111100 11011011 10001011
B (mask)
11111111 11111111 11111111 00000000
A AND B
10110111 10111100 11011011 00000000
C
00000000 00000000 00000000 01010111
A AND B OR C 10110111 10111100
11011011 01010111
The AND operation removes 1's while the OR operation inserts 1's.
EXCLUSIVE OR is used to encode and decode messages since using it twice regains the original message.
A
10110111 10111100 11011011 10001011
code
11000101 01011100 10111011 00110011
coded message
01110010 11100000 01100000 10111000
same code
11000101 01011100 10111011 00110011
original message
10110111 10111100 11011011 10001011
Monadic Operations
Monadic operations have one operand and produce one result. The instructions are shorter but more information may have to be specified. Shifts are operations in which the bits are moved to the left or right, with bits shifted off the end of the word being lost. Rotates are shifts in bits pushed off one end reappear on the other end.
A
00000000 00000000 00000000 0110011
A shifted right 2 bits
00000000 00000000 00000000 0001100
A rotated right 2 bits
11000000 00000000 00000000 0001100
Right shifts with sign extension means that positions vacated on the left end of the word are filled up with the original sign bit, 0 or 1. A negative number will remain negative.
A
11111111 11111111 11111111 11110000
A shifted without sign extension
00111111 11111111 11111111 11111100
A shifted with sign extension
11111111 11111111 11111111 11111100
If a positive integer is left shifted k bits, the result, barring overflow, is the original number multiplied by 2k. If it is right shifted it is divided by 2k. To compute 18 x n (n is a positive integer), compute 16 x n by a left shift of 4 bits, and 2 x n by a left shift of 1 bit and add. Addition is faster than multiplication. But one factor must be constant.
For example 1010 is 0000 10102
Left shift by 4 bits yields 1010 0000
Left shift by 1 bit yields 0001 0100
Add
1011 01002 which is 18010.
16 is 10000. Right shift by 2 bits is 00100 which is 4.
Shifting negative numbers, even with sign extension, provides different answers. For example the one's complement number, -1 shifted 1 bit to the left yields -3. Another 1-bit shift to the left yields -7.
11111111 11111111 11111111 11111110
-1 in One's complement
11111111 11111111 11111111 11111100
-1 shifted left 1 bit = -3
11111111 11111111 11111111 11111000
-1 shifted left 2 bits = -7
But right shifting does division correctly for one's complement.
11111111 11111111 11111111 11110111
-8 in One's complement
11111111 11111111 11111111 11111011
-8 shifted right 1 bit = - 4
11111111 11111111 11111111 11111101
-8 shifted right 2 bits = - 2
In the case of two's complement, right shifting is correct for integers.
11111111 11111111 11111111 11111000
-8 in two's complement
11111111 11111111 11111111 11111100
-8 shifted right 1 bit = - 4
11111111 11111111 11111111 11111110
-8 shifted right 2 bits = - 2
But for fractions
11111111 11111111 11111111 11111111
-1 in two's complement
11111111 11111111 11111111 11111111
-1 shifted right 6 bits = -1 not -1/64.
Left shifting multiplies correctly for two's complement.
11111111 11111111 11111111 11111111
-1 in Two's complement
11111111 11111111 11111111 11111110
-1 shifted left 1 bit = -2
11111111 11111111 11111111 11111100
-1 shifted left 2 bits = -4
Some common monadic operations is incrementing by 1 and negating.
Comparisons and Conditional Branches
Programs should test data and alter the sequence operations based on
the result. If we need the square root of x, it should print the
square root if x is 0 or positive, and an error message if x is negative.
It must also test for zero, and for overflow. Numbers must be compared
to check for largest and smallest. Depending on whether the numbers
are signed or unsigned the results can be different.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The decimal equivalents of the binary numbers are in parentheses.
Procedure Call Instructions
A procedure is a group of instructions that perform some task and can be invoked (called) from several places in the program. Other names are subroutines, functions, and methods. When it is over, it must return to the statement immediately after the call statement. So, the return address must be stored. It could be in memory, register, or stack. The worst is in a single fixed memory location. It could be lost if that procedure has to call another procedure. If it is the first word of the procedure and the first executable instruction being the second word, the procedure can return by branching to the first word. But it can still be lost in recursion when the procedure calls itself. If stored in a register, even if the procedure is recursive, it will be in a different place. But the best location is in a stack. When the procedure has finished, it pops the return address off the stack and stuffs it into the program counter. IJVM uses this method.
Flow of control refers to the sequence in which instructions are executed dynamically, that is, during program execution. In the absence of branches and procedure calls, successively-executed instructions are fetched from consecutive memory locations. Procedure calls cause the flow of control to be altered, stopping the procedure currently executing and starting the called procedure.
Coroutines
In the usual calling sequence, there is a clear distinction between the calling procedure and the called procedure. If A calls B, B computes for a while and then returns to A. Execution starts not at the beginning of A but at the statement following the call. If A runs for a while and then calls B again, execution starts at the beginning of B, not the statement following the previous return. B begins at the beginning all over again each and every time it is called, whereas A never starts over again. When A calls B, it uses the procedure call instruction, which puts the return address (address of the statement following the call) on top of the stack. It then puts the address of B into the program counter. When B returns, it does not use the call instruction but instead uses the return instruction, which pops the return address from the stack and puts it into the program counter.
Two procedures A and B may sometimes call each other. When B returns to A, it branches to the statement following the call to B. When A transfers control to B, it does not go to the beginning (except the first time) but to the statement following the most recent "return," that is, the most recent call of A. Two such procedures are called coroutines. A common use for coroutines is to simulate parallel processing on a single CPU. Each coroutine runs in pseudo-parallel with the others, as though it had its own CPU. Neither the usual CALL or RETURN instruction works for calling coroutines, because the address to branch to comes from the stack like a return, but, unlike a return, the coroutine call itself puts a return address somewhere for the subsequent return to it.
A trap is a automatic procedure call initiated by some condition caused by the program, like an floating-point overflow, floating-point underflow, integer overflow, protection violation, undefined opcode, stack overflow, attempt to start nonexistant I/O device, attempt to fetch a word from an odd-numbered address, and division by zero. If the result of an arithmetic operation exceeds the largest number, a trap occurs, and the flow of control is switched to a memory location, where there is a branch to a procedure called the trap handler, which performs some appropriate actions such as an error message. (This is called exception in Java). The action is initiated by some exceptional condition caused by the program itself and detected by the hardware or the microprogram. Traps save time and memory compared with explicit programmer-controlled checking.
Interrupts
Interrupts are changes in the flow of control caused not by the running program, but by something else, usually related to I/O. If the program instructs the disk to start transferring information, and sets the disk up to provide an interrupt as soon as the transfer is over. Like the trap, the interrupt stops the running program and transfers control to an interrupt handler, which performs some appropriate action. When finished, the interrupt handler returns control to the interrupted program. It must restart the interrupted process in exactly the same state it was in when the interrupt occurred, so all internal registers must be restored to their pre interrupt state.
Traps are synchronous with the program, while interrupts are asynchronous.
In a program run many times with the same inputs, the traps will reoccur
in the same place each time, but the interrupts may vary, depending when
a person at a terminal hits carriage return. Traps are caused directly
by the program, while interrupts are caused indirectly by the program.
|
|
|
|