CS222 Lecture: Data Structures and VAX Address Modes 10/7/91 revised 1/21/99
Materials:
1. Transparency of address modes table in programming card
2. Transparency of possible floating literal mode values
3. Transparency/handout of all modes in use
4. Transparency/handout of translation of various Pascal constructs
I. Internal Representation of Structured Data Types
- -------- -------------- -- ---------- ---- -----
A. Thus far, we have dealt with VAX facilities for handling simple,
unstructured data types: bytes, words, longwords, floating point numbers,
etc. These correspond directly to the primative types of higher-level
languages - e.g. Pascal char (byte), integer (longword), and real
(F-float).
B. We now turn to a consideration of how some of the structured types are
represented and manipulated. In particular, we will deal with records,
arrays, and pointers. (We save sets and files for later.)
C. The data type record is represented internally by representing each of its
components, in turn, in successive memory locations.
1. Example:
Pascal: var
student: record
id: integer;
gpa: real
end;
MACRO: STUDENT: .BLKL 1
.BLKF 1
2. Individual fields are accessed by adding a constant offset to the base
address of the record. Example:
Pascal student.gpa := 0.0;
MACRO: CLRF STUDENT+4
(Note that the offset is 4 because the first field
occupies 4 bytes. Note, too, that the assembler does
the address arithmetic at assembly time.)
3. Sometimes, additional, invisible fields are included within a record
to align fields on certain address boundaries.
a. Example: Consider the following record structure:
var
grade_point_info: record
grade: char;
value: real
end;
There is some performance advantage to be gained by having a
floating point number begin on a longword address boundary. Indeed,
some machines (but not the VAX) require this. Thus, the record
might be stored as follows:
GRADE_POINT_INFO: .BLKB 1
.BLKB 3 ; Filler
.BLKF 1
b. The inclusion or exclusion of such filler fields is the essence of
the distinction between the Pascal types record and packed record.
(On the VAX, the filler fields are not included, however, regardless
of whether the record is declared packed. The keyword packed does
have some significance, however, when it comes to certain data
items that occupy less than a full byte.)
D. In similar fashion, an array type is represented by representing each of
its elements in successive locations in memory.
1. Example:
Pascal: var
grades: array[1..100] of real;
MACRO: GRADES: .BLKF 100
2. Access to an individual element of an array requires a RUN-TIME
address calculation, using a formula like:
Address of element i = base_address + element_size * (i - lower_limit)
3. Actually using such a computed address requires us to do one of three
things:
a. If the subscript value is a constant, then we can do all the needed
computation at assembly time.
Example: grades[10] := 0.0;
CLRF GRADES+36 ; 36 because grades[1] is at 0,
; grades[2] at 4 .. grades[10]
; at 36
Or let the assembler do the computation:
CLRF GRADES+<4*<10-1>>
- Note use of <> instead of parentheses (required, since parentheses
have another meaning.)
- Note need to parenthesize more fully than normal. MACRO evaluates
arithmetic expressions left to right - it does not have rules of
operator precedence. (So the more natural construct,
GRADES+4*<10-1> would be taken as <GRADES+4>*<10-1>!
b. If the subscript contains a variable, then we can modify the address
field of the instruction to contain the computed address.
Example: grades[i] := 0.0;
SUBL3 #1, I, R0
MULL2 #4, R0
ADDL2 R0, CLR_INST + 2
CLR_INST: CLRF @#GRADES
i. This was the approach taken on the VonNeumann machine and some
other early computers.
ii. It is now frowned upon, for several reasons:
- Self-modifying code must be reinitialized before each use
(e.g., in the above, the address field of CLR_INST must be
reset to point to the base address of GRADES if the above
sequence is contained in a loop.)
- Self-modifying code is notoriously difficult to debug.
- Self-modifying code cannot be shared by multiple users on a
multi-user system.
- Self-modifying code cannot be stored in read-only memory
(which is often used to contain the code for microprocessor
controlled systems.)
c. The preferred approach is to make use of a special addressing mode
that allows use of an address computed at run time. One such mode
is called indirect addressing.
Example: Addressing mode 6 on the VAX is called register-deferred
mode. It uses the specified register as the ADDRESS (in
memory) of the operand. It can be used, in conjunction
with the MOVA instruction (which moves the ADDRESS of its
operand), to achieve the same result as above as follows:
MOVAF GRADES, R0
SUBL3 #1, I, R1
MULL2 #4, R1
ADDL2 R1, R0
CLRF (R0)
Actually, this could be done somewhat more efficiently as
follows:
MOVAF GRADES-4, R0
MULL3 #4, I, R1
ADDL2 R1, R0
CLRF (R0)
d. We will see later in this lecture that the VAX has a number of
different addressing modes that can be used for working with
arrays, to deal with a variety of different common operations
that occur.
E. Finally, a pointer type is represented in memory by a longword containing
the address of an item. Indirect addressing can be used to follow the
pointer (DEREFERENCE IT) to get to the item.
Example:
Pascal: var
p: ^integer;
...
p^ := 0;
MACRO: MOVL P, R0
CLRL (R0)
(Actually, for this case there is an addressing mode
that would allow the above to be done by a single
instruction. We will learn this one shortly.)
F. Of course, we can combine these representations to build more complex
structures.
Example:
Pascal: type
student = record
id: integer;
name: packed array[1..12] of char;
gpa: real
end;
var
class_list: array[1..100] of ^student;
...
class_list[i]^.gpa := 0.0;
MACRO: CLASS_LIST: .BLKA 100
...
MOVAL CLASS_LIST-4, R0
MULL3 #4, I, R1
ADDL2 R1, R0
MOVL (R0), R0
ADDL2 #16, R0
CLRF (R0)
II. VAX Addressing modes
-- --- ---------- -----
A. In discussing structured data types, we saw the need for a new addressing
mode, called REGISTER-DEFERRED. We now turn to a thorough study of the
various addressing modes. Many will turn out to be useful in dealing
with various sorts of manipulations on structured data types.
B. Recall the general format of a VAX operand specifier, used for all
instructions EXCEPT branches:
_______________
| mode | reg. | (sometimes followed by 1 or more additional bytes)
---------------
1. With a 4 bit mode specifier, 16 modes are possible.
2. Each of these modes can, in principle, be used with any of the 16
general registers. However, two registers are special when used as
the register in an operand specifier.
R14 = SP (stack pointer)
R15 = PC (program counter)
3. Therefore, we will first discuss the meaning of the different mode
specifiers when used with a general register (R0 .. R13), and then
when used with the PC and SP.
4. We will discover that the special modes we have learned with the PC
turn out to be direct results of the general behavior of these modes.
C. TRANSPARENCY OF PROGRAMMING CARD MATERIAL ON MODES - GO OVER COLUMNS
III. Addressing Modes for use with General Registers (R0 .. R13)
--- ---------- ----- --- --- ---- ------- --------- -----------
A. We have already met REGISTER MODE
1. Mode = 5; any register except PC. (The result of using this mode
with the PC is unpredictable; this is because most VAX processors do
some amount of instruction lookahead.)
2. Assembler mnemonic: Rn Example: R5
3. Uses:
a. Registers are often used for local/temporary variables, because
access to a data item in a register is much faster than access
to an item in memory.
i. There is no direct analogue to this in HLL programs. However,
most good compilers will use registers for the most active
variables in a program, to improve program speed.
ii. This is one reason why you need to specify /NOOPT with the /DEBUG
qualifier on Pascal programs; otherwise, the compiler will
generally put some of your local variables in registers where
they will not be accessible to commands like EXAMINE and DEPOSIT.
b. This mode is also used for loading a register in preparation for
its use with one of the other modes.
B. We have likewise already met REGISTER-DEFERRED MODE.
1. Mode = 6; any register except PC. (The result of using this mode
with the PC is unpredictable; this is because most VAX processors do
some amount of instruction lookahead.)
2. Assembler mnemonic: (Rn) Example: (R5)
3. Uses: This mode can be used whenever the address of an operand must
be calculated at run-time - e.g.
a. Address of an array element when the subscript contains variables.
b. Dereferencing a pointer variable.
4. Note carefully the difference between this mode and register mode.
The following example may help:
type
nodeptr = ^node;
node = record
info: integer;
link: nodeptr
end;
var
p,q: nodeptr; (* ASSUME THE COMPILER OPTIMIZES BY
PLACING P IN R2 AND Q IN R3 *)
....
p := q; MOVL R3, R2
vs
p^.info := q^.info; MOVL (R3), (R2)
C. AUTOINCREMENT MODE
1. Mode = 8; any register INCLUDING THE PC. (We will discuss use with
the PC separately later.)
2. Assembler mnemonic: (Rn)+ Example: (R5)+
3. Meaning: Same as Register-Deferred, except that AFTER the operand
address is calculated, the register is incremented by the size
of the operand.
Example: Suppose R0 contains 1000
Following MOVL (R0)+, R1
R1 will contain the contents of memory location 1000
R0 will contain 1004
Note: If the MOVL moved some other size operand, the
value in R0 would differ as follows
Operation R0 final value
MOVB 1001
MOVW 1002
MOVL, MOVF 1004
MOVQ, MOVD, MOVG 1008
MOVO, MOVH 1010
4. Uses
a. Step systematically through any kind of table
Example: TABLE: .BLKL 100
Sum up all elements of table and put sum in R2:
MOVAL TABLE, R0
MOVL #100, R1 ; Counter
CLRL R2
LOOP: ADDL2 (R0)+, R2
SOBGTR R1, LOOP
b. Special uses with SP, PC to be covered later
D. AUTODECREMENT MODE
1. Mode = 7; any register except the PC. (The result of using this mode
with the PC is unpredictable; this is because most VAX processors do
some amount of instruction lookahead.)
2. Assembler mnemonic: -(Rn) Example: -(R5)
3. Meaning: Same as Register-Deferred, except that BEFORE the operand
address is calculated, the register is decremented by the size
of the operand.
NOTE WELL: With autodecrement, the register is decremented BEFORE the
operand address is calculated; with autoincrement, it is
incremented AFTER the address is calculated.
Example: Suppose R0 contains 1000
Following MOVL -(R0), R1
R1 will contain the contents of memory location FFC
R0 will contain FFC
Note: If the MOVL moved some other size operand, the
address accessed and the value in R0 would
differ as follows
Operation Item accessed / R0 final value
MOVB FFF
MOVW FFE
MOVL, MOVF FFC
MOVQ, MOVD, MOVG FF8
MOVO, MOVH FF0
4. Uses
a. Step systematically through any kind of table, going backwards
Example: TABLE: .BLKL 100
Find value of LAST non-zero element of table and put in R2:
MOVAL TABLE+400, R0
MOVL #100, R1 ; Counter
LOOP: MOVL -(R0), R2
BNEQ FINI
SOBGTR R1, LOOP
FINI:
b. Special use with SP to be covered later
E. AUTOINCREMENT DEFERRED MODE
1. Mode = 9; any register INCLUDING THE PC. (We will discuss use with
the PC separately later.)
2. Assembler mnemonic: @(Rn)+ Example: @(R5)+
3. Meaning: The register contents is taken as a memory address, and the
contents of that location in memory is taken as the address of the
operand. The register is then incremented by 4 (the size of an
address). Note that TWO LEVELS OF INDIRECT ADDRESSING are involved.
Example: Suppose R0 contains 1000, and memory location 1000
contains 2000
Following MOVL @(R0)+, R1
R1 will contain the contents of memory location 2000
R0 will contain 1004
Note: If the MOVL moved some other size operand, the
value in R0 would still be the same
4. Uses
a. Step systematically through the objects referenced by a table of
POINTERS
Example: The FORTRAN library includes a built in function called
MAX which takes any number of integers (up to 255) as
arguments and returns the largest
e.g. MAX(2, 3) would return 3
MAX(1, 19, 12, 37, 16, 4) would return 37
On the VAX, procedures are called with the AP register
(R12) pointing to an argument list that has the
following format:
Number of arguments (0 .. 255)
First argument
Second argument
Third argument
...
Each argument is a longword. In the case of FORTRAN,
it is always the ADDRESS of the actual argument (a
pointer to it) - like a var parameter in Pascal.
The MAX function could be written like this. The value
will be returned to the caller in R0, which is the
convention for function values on the VAX.
.ENTRY MAX, ^M<R2>
MOVL (AP)+, R1 ; Number of arguments
BEQL ERROR ; Error - no arguments
MOVL @(AP)+, R0 ; Assume first argument biggest
DECL R1 ; Count this one off
BEQL FINI ; If only one, it must be max
LOOP: MOVL @(AP)+, R2
CMPL R2, R0
BLEQ SMALL
MOVL R2, R0
SMALL: SOBGTR R1, LOOP
FINI: RET ; R0 contains maximum
ERROR: Something has to be done here
Note: The first MOVL uses plain autoincrement, not
autoincrement deferred, because the argument count in
the list is an actual value, not a pointer to a value.
b. Special use with PC to be covered later
F. BYTE/WORD/LONGWORD DISPLACEMENT MODES
1. Mode = A/C/E; any register INCLUDING THE PC. (We will discuss use with
the PC separately later.)
2. Assembler mnemonic: B^displ(Rn) Examples: B^5(R5)
W^displ(Rn) W^200(R5)
L^displ(Rn) L^120000(R5)
Note: The B^, W^, or L^ may be omitted, in which case the assembler
will choose the correct mode based on the size of the
displacement - e.g.
5(R5) is equivalent to B^5(R5)
120000(R5) is equivalent to L^120000(R5)
3. Meaning: The displacement value and contents of the register specified
are added to form the address of the operand. The register contents
is unchanged.
4. Uses: Many!
a. For accessing array elements:
Example:
Pascal: var
grades: array[1..100] of real;
...
grades[i] := 0.0;
MACRO: GRADES: .BLKF 100
...
MULL3 #4,I,R0
CLRF GRADES-4(R0)
- Note how much shorter this is than using register-deferred mode
b. For accessing components of a record structure pointed to by a
pointer variable.
Example:
Pascal: type
student_ptr = ^student;
student = record
id: integer;
gpa: real;
link: student_ptr
end;
var
p: student_ptr;
...
p^.gpa := 0.0;
p := p^.link;
Macro: P: .BLKA 1
...
MOVL P, R0
CLRF 4(R0)
MOVL 8(R0), P
c. For accessing arguments of a procedure when passed by VALUE:
Example:
C: int f(int i)
{
return i + 2;
}
/* Example is in C because VAX Pascal always passes
parameters by reference - even when they are value
parameters. */
MACRO: .ENTRY F, 0
ADDL3 #2,4(AP),R0
RET
- Offset of 4, because first word of argument list (to
which AP points) is count of number of arguments.
d. Special uses with SP, PC to be covered later
G. BYTE/WORD/LONGWORD DISPLACEMENT DEFERRED MODES
1. Mode = B/D/F; any register INCLUDING THE PC. (We will discuss use with
the PC separately later.)
2. Assembler mnemonic: @B^displ(Rn) Examples: @B^5(R5)
@W^displ(Rn) @W^200(R5)
@L^displ(Rn) @L^120000(R5)
Note: The B^, W^, or L^ may be omitted, in which case the assembler
will choose the correct mode based on the size of the
displacement - e.g.
@5(R5) is equivalent to @B^5(R5)
@120000(R5) is equivalent to @L^120000(R5)
3. Meaning: The displacement value and contents of the register specified
are added to form the address of a memory location. The contents of
this location is then taken as the address of the operand. The
register contents is unchanged.
4. Uses:
a. For accessing objects through an array of pointers
Example:
Pascal: type
nodeptr = ^node;
node = record
info: integer;
link: nodeptr
end;
var
nodes: array[1..100] of nodeptr;
...
nodes[i]^.info := 0;
MACRO: NODES: .BLKA 100
...
MULL3 #4,I,R0
CLRL @NODES-4(R0)
- Note this only works when the field we want is at the beginning
of the object pointed to by the pointer.
b. For accessing the item pointed to by a pointer which is itself a
component of a record structure pointed to by a pointer variable.
Example:
Pascal: type nodeptr, node as above
var
p: nodeptr;
...
p^.link^.info := 0;
Macro: P: .BLKA 1
...
MOVL P, R0
CLRL @4(R0)
- Note this only works when the field we want is at the beginning
of the object pointed to by the second pointer.
c. For accessing arguments of a procedure when passed by REFERENCE:
Example:
Pascal: function f(var i: integer): integer;
begin
f := i + 2
end;
(* Note: in VAX Pascal, parameters are passed by
reference even if non-var; but var parameters are
ALWAYS passed by reference. *)
MACRO: .ENTRY F, 0
ADDL3 #2,@4(AP),R0
RET
- Offset of 4, because first word of argument list (to
which AP points) is count of number of arguments.
d. Special use PC to be covered later
H. LITERAL MODE
1. We have already seen that the VAX has an immediate mode that allows
an operand to be embedded within an instruction. One problem is that
immediate mode consumes a fair amount of space in an instruction.
Example: An immediate mode longword operand requires 5 bytes: 1 for
the operand specifier (8F) and four for the value.
2. Many times, immediate operands are small numbers - e.g. 2, 3, etc.
For such operands, the VAX provides a shorter way to include them
in an instruction. This option is available for:
a. Integer operands in the range 0 .. 63
b. Floating point operands that can be represented with a 3 bit
exponent and 3 bit mantissa - e.g.
i. One of the following true exponents: 0 .. 7
ii. One of the following mantissas: (binary)
.1000 = 1/2 Note: The leading 1 is the hidden bit,
.1001 = 9/16 so only three bits are needed
.1010 = 5/8 to store the mantissa
.1011 = 11/16
.1100 = 3/4
.1101 = 13/16
.1110 = 7/8
.1111 = 15/16
iii. Complete set of possible floating values: TRANSPARENCY P. 68
3. The addressing modes that provide this feature are called the
LITERAL MODES. In brief, when the high-order two bits of the
operand specifier are 00, the remaining 6 bits are taken as a short
integer or floating point value (depending on the type of instruction
being executed.)
a. This corresponds to "modes" 0, 1, 2, 3 - i.e. the leftmost two
bits of the mode field are 00 and the rightmost two bits are
part of the literal value.
b. For these "modes" the 4 bits used for the register field form
part of the literal value.
Example: The literal value 24 (Hex) would be encoded as "mode" 2
"register" 4 - i.e. 24
The literal value 0.75 (decimal) would be encoded as
00 000 100
which looks like "mode" 0, "register" 4
4. The assembler syntax is S^#value
a. Examples: MOVL S^#^X24, R0
MOVF S^#0.75, R0
b. When the syntax #value is used, the assembler chooses between
immediate and literal mode, preferring literal mode wherever
possible - e.g.
MOVL #3, R0 -- would be translated as if S^#3
MOVL #100, R0 -- would be translated as if I^#100
I. INDEX MODE
1. The final mode we need to consider is mode 4. It is called INDEX MODE.
a. When an operand specifier calls for mode 4, the register it
specifies is called the INDEX REGISTER.
b. Unlike all other modes, this one never stands by itself - it is
always used in conjunction with some other mode, called the BASE
MODE.
c. The assembly language syntax is to enclose the index register
in square brackets FOLLOWING the base mode - e.g.
(R0)[R5] - would specify base mode register deferred
with R0, plus index register R5
TABLE[R5] - would specify base mode relative, plus index
register R5
d. In the machine language code, the mode 4 / index register specifier
comes FIRST - before the base mode operands specifier, and
must be immediately followed by the base mode operand specifier.
This base mode operand specifier - plus any additional bytes it
needs - is used to calculate an address in the ordinary way. Then
the contents of the index register is multiplied by the operand
size, and the result is added to the address calculated previously
to form the operand address.
Example: Suppose we have the following instruction
60 41 D4 CLRW (R0)[R1]
Suppose further that R0 contains 1000 (hex) and R1
contains 3.
The address of the location to be cleared is calculated
as follows: the base address specifier specifies 1000.
To this is added the operand size (word - 2) times the
contents of the index register (3) to yield 1006 as
the address of the word to clear.
NOTE WELL: The base mode specifier comes BEFORE the index
specifier in the assembly language code, but AFTER it
in the machine language code.
e. Some special rules apply to this mode
i. It must only be used with base address specifiers that specify
a memory address - e.g. it cannot be used with register mode,
literal mode, or immediate mode. (The result of doing so is
either a fault or an unpredicatable result.)
ii. If the base mode modifies its register in some way (e.g.
autoincrement, autodecrement, autoincrement deferred), then
the usual modification to the base register is done.
iii. It is not usually meaningful to use the same register as both
an index register and part of the base mode. If this is done,
and the base mode modifies its register, then the results are
unpredictable.
2. The primary use for this mode is for array subscripting, provided
the array elements are of some standard hardware type (such as
longword.)
a. Example:
Pascal: var
grades: array[1..100] of real;
...
grades[i] := 0;
MACRO: MOVL I,R0
CLRF GRADES-4[R0]
b. Example:
Pascal: type
student = record
gpa: real
id: integer;
name: packed array[1..12] of char;
end;
var
stu_array: array[1..100] of student;
...
student[i].gpa := 0.0;
MACRO: Cannot be done using index mode - size of an array
element (20) is not a standard hardware size, and
is not the size of the item being cleared anyway.
We must use displacement mode as in previous examples.
IV. Addressing modes for use with SP
-- ---------- ----- --- --- ---- --
A. As we noted in our introduction to the architecture of the VAX, the
architecture divides memory into four major regions:
-------------------------
| | 00000000
| P0 space |
| | 3FFFFFFF
|-----------------------+---------
| | 40000000
| P1 space |
| | 7FFFFFFF
|-----------------------+---------
| | 80000000
| System space |
| | BFFFFFFF
|-----------------------+---------
| | C0000000
| (Reserved) |
| | FFFFFFFF
-------------------------
1. The code and global data for each process resides in its P0 space.
2. P1 space is used for a process's stack, which grows from high
addresses toward low. Processor register 14 (SP) always points
to the current top location on the stack.
a. To push a new item on the stack, it is necessary to SUBTRACT the
item's size from SP.
b. To pop an item from the stack, it is necessary to ADD the item's
size to SP.
B. We have noted that all of the addressing modes can be used with the
stack pointer register. Four have special uses:
1. Access top item on stack - use register deferred on SP (SP)
Example: If the top item on the stack is an integer, then to copy
it into R2 (leaving it also on the stack) we would write:
MOVL (SP), R2
2. Pop an item from stack - use autoincrement with SP (SP)+
Example: If the top item on the stack is an integer, to pop
it off the stack and into R2, we would write:
MOVL (SP)+, R2
3. Push an item on stack - use autodecrement with SP -(SP)
a. Example: To push the real number X on the stack, we could write:
MOVF X, -(SP)
b. For reasons of efficiency, it is the convention to always push
items on the stack whose size is one or more longwords. Thus,
to push a byte (say in R0) we would normally use:
CVTBL R0, -(SP)
or
MOVZBL R0, -(SP)
(though simply MOVB R0, -(SP) would be legal.)
Of course, for items larger than a longword we can just push
them as is - e.g. to push an H-float:
MOVH R0, -(SP)
c. Actually, because pushing is done so often we can often use
the special PUSHL instruction instead - e.g. to push the real X:
PUSHL X
(But note that this special instruction is only available for
longwords.)
4. One important use of the stack is to create working space for the
local variables of a procedure. This can be done by subtracting
a constant from SP and then referencing the variables by using
displacement mode on SP:
a. Example:
Pascal: procedure foo;
var
i, j: integer;
...
i := j+1;
MACRO: .ENTRY FOO, ^M<>
SUBL #8, SP
...
ADDL3 #1, 4(SP), (SP)
(Note: We used register deferred for i because the
displacement would be 0 - i.e.
(SP) is equivalent to 0(SP) but one byte shorter.
b. In conjunction with our lectures on procedures, we will see that
another register called the FRAME POINTER (R13 = FP) is always
used to point to the base address of working space for a procedure.
Thus, the above instruction might also be coded as:
ADDL3 #1, -8(FP), -4(FP)
5. Finally, we note that it is possible to use the hardware stack to
directly handle 0-address (stack machine) code.
Example:
Pascal: A := B + C * D - E
Stack machine code: PUSH B
PUSH C
PUSH D
MUL
ADD
PUSH E
SUB
POP A
VAX equivalent: PUSHL B
PUSHL C
PUSHL D
MULL2 (SP)+, (SP)
ADDL2 (SP)+, (SP)
PUSHL E
SUBL2 (SP)+, (SP)
MOVL (SP)+, A
C. We have discussed the use of a stack whose top is pointed to by the SP
register.
1. This stack is automatically set up by the operating system when a
program is entered, and is used by hardware instructions like BSBB,
BSBW, JSB, RSB, CALLS, CALLG, and RET.
2. It is possible for a program to create another stack (anywhere in
its memory) by using another register as a stack pointer.
Example: We saw in CS122 that one way to reverse the order of
the characters in a string would be to push them onto a
stack and then pop them back off. This could be done
in MACRO as follows:
THE_STRING: .BLKB 100
MY_STACK: .BLKB 100
...
MOVAB THE_STRING, R0
MOVAB MY_STACK, R1
MOVL #100, R2
LOOP1: MOVB (R0)+, -(R1)
SOBGTR R2, LOOP1
MOVAB THE_STRING, R0
MOVL #100, R2
MOVB (R1)+, (R0)+
SOBGTR R2, LOOP1
V. Addressing modes for use with PC
- ---------- ----- --- --- ---- --
A. Several of the addressing modes produce some interesting and important
effects when used with the PC. These effects come about as a direct,
natural result of the definitions of the modes. We are now able to
see why these modes work the way they do.
B. IMMEDIATE MODE Mode = 8; register = PC (F)
1. This is actually autoincrement on the PC.
2. To see how it works, consider the following example:
MACRO: MOVW #^X1234, R0
Machine language: 50 1234 8F B0
- When the first operand specifier (8F) is fetched, the PC is
advanced to point to just after it - i.e. to the value 1234.
- This value, then, is the operand, since it is what register F (the
PC) now points to.
- Register F is incremented by the size of a word 2. This makes
register F (the PC) point to the next operand specifier (50),
which is what we now want to continue instruction execution.
C. ABSOLUTE MODE Mode = 9; register = PC (F)
1. This is actually autoincrement-deferred on the PC.
2. To see how it works, consider the following example:
MACRO: MOVW @#^X1234, R0
Machine language: 50 00001234 9F B0
- When the first operand specifier (9F) is fetched, the PC is
advanced to point to just after it - i.e. to the address 00001234.
- This value, then, is the address of operand, since it is what
register F (the PC) now points to.
- Register F is incremented by the size of an address (4). This makes
register F (the PC) point to the next operand specifier (50),
which is what we now want to continue instruction execution.
D. BYTE, WORD, and LONG RELATIVE MODES Mode = A, C, E; register = PC (F)
1. These are actually byte, word, or long displacement mode on the PC.
2. To see how it works, consider the following example. Assume
that the instruction begins at address 1000, and that TABLE is
at 2000.
MACRO: MOVL TABLE, R0
Machine language: 50 0FFFC CF D0
- When the first operand specifier (CF) is fetched, the PC is
advanced to point to just after it - i.e. to the displacement 0FFFC.
- Since the mode is word displacement, this word value is fetched,
and the PC is advanced to just after it - i.e. to 1004.
- The displacement is added to register F (the PC) to yield the
operand address 2000.
- Register F (the PC) now points to the next operand specifier (50),
which is what we now want to continue instruction execution.
E. BYTE, WORD, and LONG RELATIVE DEFERRED MODES
Mode = B, D, F; register = PC (F)
1. These are actually byte, word, or long displacement-deferred mode on
the PC.
2. These work just like relative, except that the calculated address is
used as the address of the address of the operand, not as the address
of the operand.
VI. Summary of VAX Addressing Modes
-- ------- -- --- ---------- -----
A. TRANSPARENCY/HANDOUT showing all modes
B. TRANSPARENCY/HANDOUT showing translation of various Pascal constructs
C. Go over programming card TRANSPARENCY again.
VII. MIPS Addressing Modes
--- ---- ---------- -----
A. We have seen that the VAX has a very rich and powerful set of
addressing modes, which can be used with practically any instruction.
(The one exception is the branch instructions, which always use
relative addressing.)
B. In contrast, MIPS has a very small set of addressing modes, and
only certain modes can be used with any given instruction.
1. Computational instructions (add etc) always use register mode
for the destination and one of the sources. The second source
can use either register mode or immediate mode (e.g. add uses
register mode for all three operands; addi uses immediate mode
for the second source operand and register mode for the other
two operands.)
2. Memory reference instructions (load, store) use displacement mode.
The instruction has the following format:
op (6) | rs (5) | rt (5) | displacemenT (16)
The address of the operand is calculated by adding the offset to
rs. rt is the register to load/store, as the case may be.
ASK: Which VAX address mode does this most closely corrrespond to?
ANS: word displacement - mode C
3. Jump/branch instructions use relative mode - except jr uses
register mode.
C. Despite this simplicity, most addressing modes on the VAX can be
synthesized by one or more MIPS instructions.
1. We have already seen that the MIPS equivalent of a VAX instruction
that does computation on values in memory is to load the operands
into registers, perform the computation, and then store the
result back to memory.
2. We now consider how various VAX addressing modes can be synthesized
for the MIPS load/store instructions.
a. Register mode - use the add instruction with $0 as the second
source.
b. Register deferred mode
ASK
Use displacement mode with a displacement of 0
c. Autodecrement mode
ASK
First use addi to add an appropriate negative value (-1, -2, -4,
etc.) to the register, then same as register deferred
d. Autoincrement mode
ASK
Same as register mode, then use addi to add an appropriate value
(1, 2, 4, etc.) to the register.
e. Autoincrement-deferred
ASK
Example: VAX: movl @(r2)+, r3
MIPS: lw $1, 0($2) ; $1 = address of operand
lw $3, 0($1)
addi $2, $2, 4
f. Displacement - trivial
g. Displacement-deferred
ASK
Use same strategy as above
h. Immediate - use addi with $0 as the first source.
i. Absolute - load the address into a temporary register, then
same as register deferred. (Note VAX mnemonic - @#!)
j. Relative - No MIPS equivalent. (Other RISCS have a relative
mode version of the load/store instructions with a different
format)
Copyright ©1999 - Russell C. Bjork