190 likes | 675 Views
Assembly Language. Part 5. Reference parameter/global variable model. C++ reference parameters are references to the actual arguments (as opposed to copies of the values) At assembly language level, the address of the actual argument is pushed on the stack
E N D
Assembly Language Part 5
Reference parameter/global variable model • C++ reference parameters are references to the actual arguments (as opposed to copies of the values) • At assembly language level, the address of the actual argument is pushed on the stack • in the previous example, the actual arguments were global variables; therefore we could use the name of the corresponding symbol to refer to the address • Code used to push the address of global variable is a load instruction with immediate addressing
A program with reference parameters #include <iostream.h>int a, b; // global variablesvoid swap (int& r, int& s) { int temp; temp = r; r = s; s = temp;}void order (int& x, int& y) { if (x > y) { swap (x, y); } // ra2} int main () { cout << "Enter an integer: "; cin >> a; cout << "Enter an integer: "; cin >> b; order (a, b); cout << "Ordered they are: " << a << ", " << b << endl; // ra1 return 0;}
Pep/8 equivalent ;******* main () main: STRO msg1,d DECI a,d ;cin >> a STRO msg1,d DECI b,d ;cin >> b LDA a,i ;push address of a STA -2,s LDA b,i ;push address of b STA -4,s SUBSP 4,i ;push params CALL order ;order (a, b) ra1: ADDSP 4,i ;pop params STRO msg2,d DECO a,d STRO msg3,d DECO b,d CHARO '\n',i STOP msg1: .ASCII "Enter an integer: \x00" msg2: .ASCII "Ordered they are: \x00" msg3: .ASCII ", \x00" .END int main () { cout << "Enter an integer: "; cin >> a; cout << "Enter an integer: "; cin >> b; order (a, b); cout << "Ordered they are: " << a << ", " << b << endl; // ra1 return 0;}
Pep/8 equivalent x: .EQUATE 4 ;formal parameter y: .EQUATE 2 ;formal parameter order: LDA x,sf ;if (x > y) CPA y,sf BRLE endIf LDA x,s ; push x STA -2,s LDA y,s ; push y STA -4,s SUBSP 4,i ; push params CALL swap ; swap (x, y) ADDSP 4,i ; pop params endIf: RET0 ;pop retAddr void order (int& x, int& y) { if (x > y) { swap (x, y); } // ra2} • This procedure (order) calls a second • procedure, swap • The order procedure received two • reference parameters, x and y, whose • addresses are already stored on the • runtime stack • Since the swap procedure is also • expecting reference parameters, the • order procedure simply passes on the • address of x to swap
Pep/8 equivalent BR main a: .BLOCK 2 ;global variable b: .BLOCK 2 ;global variable ; ;******* void swap (int& r, int& s) r: .EQUATE 6 ;formal parameter s: .EQUATE 4 ;formal parameter temp: .EQUATE 0 ;local variable swap: SUBSP 2,i ;allocate local LDA r,sf ;temp = r STA temp,s LDA s,sf ;r = s STA r,sf LDA temp,s ;s = temp STA s,sf RET2 ;deallocate local, ;pop retAddr int a, b; // global variablesvoid swap (int& r, int& s) { int temp; temp = r; r = s; s = temp;} • Procedure swap needs to translate the line • temp = r; into assembly language – meaning, • it must access the value of a parameter • whose address is on the runtime stack • The mechanism for this access is stack-relative • deferred addressing
Yet another addressing mode • Recall that the relation between the operand and its specifier in stack-relative addressing is: operand = Memory[SP + operand specifier] • the key point is, the operand itself is stored on the runtime stack • with reference parameters, the operand’s address is on the stack • The addressing mode in use is stack-relative deferred addressing, in which the operand/specifier relation is: operand = Memory[Memory[SP + operand specifier]]
Translating pass-by-reference calls involving global variables: summary • Argument is pushed on the stack via a load instruction with immediate mode addressing: LDA a, i STA -2, s • Formal parameter is accessed using stack-relative deferred addressing: LDA r, sf ; temp = r; STA temp, s ; reference parameter on right side of = ; with local variable on left side LDA s, sf ; r = s; STA r, sf ; reference parameters on both sides of =
More common situation: reference parameter with local variables // C++ program with method for finding perimeter of rectangle #include <iostream.h>void rect (int& p, int w, int h) { p = (w + h) * 2;}int main () { int perim, width, height; cout << "Enter width: "; cin >> width; cout << "Enter height: "; cin >> height; rect (perim, width, height); // ra1 cout << "perim = " << perim << endl; return 0;}
Pep/8 equivalent • Procedure rect uses its reference parameter, p, as we saw with the previous example: STA p, sf stores the value in A using stack-relative deferred addressing • Note the line before that: what does ASLA do? ;File: fig0629.pep ;Computer Systems ;Figure 6.29 ; BR main ; ;******* void rect (int& p, int w, int h) p: .EQUATE 6 ;formal parameter w: .EQUATE 4 ;formal parameter h: .EQUATE 2 ;formal parameter rect: LDA w,s ;p = (w + h) * 2 ADDA h,s ASLA STA p,sf endIf: RET0 ;pop retAddr ;
Pep/8 equivalent: first part of main • Local variables perim, width and height are pushed on runtime stack • The symbol perim is not the absolute address of its value, as it was in the global case; its value (4) is only the address relative to the stack top – so can’t use: LDA perim, i STA -2, s • The instructions: MOVSPA ADDA perim, i STA -2, S are used to : • copy SP value to A • Add value of perim (4) to A • Put address of perim in stack cell that will be the reference parameter, p ;******* main () perim: .EQUATE 4 ;local variable width: .EQUATE 2 ;local variable height: .EQUATE 0 ;local variable main: SUBSP 6,i ;allocate locals STRO msg1,d DECI width,s STRO msg2,d DECI height,s MOVSPA ;push address of perim ADDA perim,i STA -2,s LDA width,s ;push value of width STA -4,s LDA height,s ;push value of height STA -6,s SUBSP 6,i ;push params
Pep/8 equivalent: rest of main CALL rect ;rect (perim, width, height) ra1: ADDSP 6,i ;pop params STRO msg3,d DECO perim,s CHARO '\n',i ADDSP 6,i ;deallocate locals STOP msg1: .ASCII "Enter width: \x00" msg2: .ASCII "Enter height: \x00" msg3: .ASCII "perim = \x00" .END
Value-returning method • The previous example was typical in the sense that most programs use local variables rather than global, but atypical in its use of a reference parameter in a void method to change one value • It is usual in this sort of situation (one value to be changed) to write a function – that is, a value-returning method or procedure • Pages 268-270 of your text illustrate a value-returning method with an added twist: recursion
Translating boolean values • C++ treats boolean values as 0 (meaning false) and anything else (meaning true) • Java treats these values similarly, if not transparently • At the bit level, it would seem obvious to extend this practice: • 0000 means false • 0001 means true
The complications of convenience • Consider the basic logical operations AND, OR and NOT • 0000 AND 0001 is 0000 (false, as it should be) • 0000 OR 0001 is 0001 (true, also as expected) • NOT 0000 is 1111 – oops… • Many architectures resolve this by using XOR instead of NOT, since • p 0 = p and • p 1 = !p
Indexed addressing and arrays • Recall these basic concepts concerning variables: • A variable in HLL is a memory chunk at machine level • In HLL, we refer to variable by name; at machine level, we refer to it by address • A variable in assembly language may be referred to by name, but the value of that name is the address of the memory chunk
Indexed addressing and arrays • An array at either level is just a bigger chunk of memory • At the high level, we refer to an array by name, and its individual elements by index • The index is an offset added to the initial address (referred to by name) • The amount added is the index multiplied by the size of the data item • At the machine architecture and assembly levels, we refer to the address of the array’s start – in assembly language, the symbol of an array is the address of the first element
Arrays and addressing modes • Pep/8 programs with arrays use the following addressing modes: • indexed: Memory[Op specifier + X] • stack-indexed: Memory[SP + Op specifier + X] • stack-indexed deferred: Memory [Memory[SP + Op specifier] + X] • Each element of an array is accessed by: • loading its index into X • multiplying by the number of bytes per cell • using stack-indexed addressing
Local array variables & array parameters • Local array variables are allocated on the runtime stack during program execution: • SUBSP allocates space for array • ADDSP deallocates it • To pass array as parameter: • address of first element is pushed on runtime using MOVSPA and ADDA with immediate addressing • Element is accessed by loading its index into X, multiplying by # bytes per cell, and using stack-indexed deferred addressing