580 likes | 838 Views
IA32 Addressing Modes. Chapter 5 The ISA Level cont’d. addressing. Opcode indicates what operation is to be performed. Operands specify the location of data. Example of addressing modes that we have already used: A = 12 B dword 52 mov eax, 1 ; immediate mov ebx, eax ; register
E N D
IA32 Addressing Modes Chapter 5 The ISA Level cont’d.
addressing • Opcode indicates what operation is to be performed. • Operands specify the location of data. • Example of addressing modes that we have already used: A = 12 B dword 52 mov eax, 1 ; immediate mov ebx, eax ; register mov ecx, A ; immediate mov edx, B ; direct memory
IA32 addressing modes • Immediate • Direct memory • Register • Register indirect (new) • Indexed (new) • Based-indexed (new)
Register indirect • Consider the following: B dword 52 … mov eax, B ; eax now equals 52 • In the above example, the operand actually contains the address of B. • That’s not very flexible.
Register indirect • Say B is located at memory location (address) 400. We load the address of B into a register. mov ebx, 400 ;load the address of B mov eax, ebx ;eax is now 400 mov eax, [ebx] ;eax now equals 52 • This is the register indirect addressing mode. The register does not contain the value but contains a reference to (pointer to/location of) the value in memory.
Register indirect • But how do we get the address of something into a register to start with? • We don’t know where the assembler and linker place A in memory! • Just as we have instructions that load values from memory, we have instructions that load the address of values in memory. lea eax, A ;store addr of A in eax ;lea = load effective addr mov eax, offset A ;same result
How can we use the register indirect addressing mode to sum up the values in a table?
Sum up values in a table tbl dword 1, 2, 7, 22, 59, 100 mov eax, offset tbl ;eax points to the first table entry mov ebx, [eax] ;ebx contains the first table entry ;how can we make eax point to the next table entry?
Sum up values in a table tbl dword 1, 2, 7, 22, 59, 100 mov eax, offset tbl ;eax points to the first table entry mov ebx, [eax] ;ebx contains the first table entry add eax, 4 ;eax now points to next table entry
Sum up values in a table tbl dword 1, 2, 7, 22, 59, 100 mov eax, offset tbl ;eax points to the first table entry mov ebx, [eax] ;ebx contains the first table entry add eax, sizeof dword ;even better
Sum up values in a table tbl dword 1, 2, 7, 22, 59, 100 mov eax, offset tbl ;eax points to the first table entry mov ebx, [eax] ;ebx contains the first table entry add eax, 4 ;eax now points to next table entry ;how can we sum the next entry?
Sum up values in a table tbl dword 1, 2, 7, 22, 59, 100 mov eax, offset tbl ;eax points to the first table entry mov ebx, [eax] ;ebx contains the first table entry add eax, 4 ;eax now points to next table entry add ebx, [eax] ; sum the second entry …
Sum up values in a table tbl dword 1, 2, 7, 22, 59, 100 mov eax, offset tbl ;eax points to the first table entry mov ebx, [eax] ;ebx contains the first table entry add eax, 4 ;eax now points to next table entry add ebx, [eax] ;sum the second entry add eax, 4 add ebx, [eax] ;sum the third add eax, 4 add ebx, [eax] ;sum the fourth add eax, 4 add ebx, [eax] ;sum the fifth add eax, 4 add ebx, [eax] ;sum the sixth Note: If we know that we have N entries in the table, we can use a loop instead.
Indexed Used to: • reference memory at a constant offset from a register • when register points to object and data member is a know offset from start of object • reference memory using a register as an additional offset • when register is used as an offset to an array element
Indexed A dword 592h, 50h, 60h, 70h, 80h, 90h mov eax, 4 mov ebx, A[eax] ;what’s in ebx? mov ecx, [A+eax] ;what’s in ecx?
Indexed A dword 592h, 50h, 60h, 70h, 80h, 90h mov eax, 4 mov ebx, A[eax] ;what’s in ebx? mov ecx, [A+eax] ;what’s in ecx?
Using indexed addressing to sum up values in a table tbl dword 1, 2, 7, 22, 59, 100 mov eax, 0 ;eax is offset from start of table mov ebx, tbl[eax] ;ebx contains the first table entry add eax, 4 ;eax now is offset to next table entry add ebx, tbl[eax] ;sum the second entry add eax, 4 add ebx, tbl[eax] ;sum the third add eax, 4 add ebx, tbl[eax] ;sum the fourth add eax, 4 add ebx, tbl[eax] ;sum the fifth add eax, 4 add ebx, tbl[eax] ;sum the sixth
Based-indexed • Address is computed by adding two registers (base and index) plus an optional offset (displacement). • One of the two registers (but not both) may also be optionally scaled. • Offset = base + (index*scale) + displacement
Using based-indexed addressing to sum up values in a table (approach #1) tbl dword 1, 2, 7, 22, 59, 100 mov eax, 0 ;offset from start of table mov ebx, tbl[eax*4] ;get first table entry inc eax ;subscript of next table entry add ebx, tbl[eax*4] ;sum the second entry inc eax add ebx, tbl[eax*4] ;sum the third inc eax add ebx, tbl[eax*4] ;sum the fourth inc eax add ebx, tbl[eax*4] ;sum the fifth inc eax add ebx, tbl[eax*4] ;sum the sixth
Using based-indexed addressing to sum up values in a table (approach #2) tbl dword 1, 2, 7, 22, 59, 100 mov eax, offset tbl ;point to start of table mov ebx, 0 ;offset from start of table mov ecx, [eax+ebx*4] ;get first table entry inc ebx ;subscript of next table entry add ecx, [eax+ebx*4] ;sum the second entry inc ebx add ecx, [eax+ebx*4] ;sum the third inc ebx add ecx, [eax+ebx*4] ;sum the fourth inc ebx add ecx, [eax+ebx*4] ;sum the fifth inc ebx add ecx, [eax+ebx*4] ;sum the sixth
Using based-indexed addressing to sum up values in a table (approach #3) tbl dword 1, 2, 7, 22, 59, 100 mov eax, offset tbl ;points to start of table mov ebx, 0 ;offset from start of table mov ecx, [eax+ebx] ;get first table entry add ebx, 4 ;offset of next table entry add ecx, [eax+ebx] ;sum the second entry add ebx, 4 add ecx, [eax+ebx] ;sum the third add ebx, 4 add ecx, [eax+ebx] ;sum the fourth add ebx, 4 add ecx, [eax+ebx] ;sum the fifth add ebx, 4 add ecx, [eax+ebx] ;sum the sixth
Methods of passing arguments to functions • Methods: • Use registers. • Use stack. • Use one register which points to a parameter block.
Stack temporarily keeps return address. main PROC ;program execution begins here mov eax, offset afterCall ;addr of inst after call f call dump ;show contents of regs call f afterCall: mov eax, input(prompt) ;prompt the user exit ;end of program main ENDP ;---------------------------------------------------------------------- f PROC mov eax, [esp] ;gets return address call dump ret f ENDP
main PROC ;program execution begins here mov eax, offset afterCall ;addr of inst after call f call dump ;show contents of regs call f afterCall: mov eax, input(prompt) ;prompt the user exit ;end of program main ENDP ;---------------------------------------------------------------------- f PROC mov eax, [esp] ;gets addr of return address call dump ret f ENDP Note: In f, esp points to return address which is location of afterCall.
Passing arguments to functions via the stack main PROC ;program execution begins here mov eax, 7 push eax ;push the contents of eax on the stack push 4 ;push the value 4 on the stack call f pop eax ;must clean up stack! pop eax ;must clean up stack! mov eax, input(prompt) ;prompt the user exit ;end of program main ENDP ;---------------------------------------------------------------------- f PROC mov eax, [esp+4] ;eax = 4 mov ebx, [esp+8] ;ebx = 7 call dump ret f ENDP
Passing arguments to functions via the stack main PROC ;program execution begins here mov eax, 7 push eax ;push the contents of eax on the stack push 4 ;push the value 4 on the stack call f pop eax ;must clean up stack! pop eax ;must clean up stack! mov eax, input(prompt) ;prompt the user exit ;end of program main ENDP ;---------------------------------------------------------------------- f PROC mov eax, [esp+4] ;eax = 4 mov ebx, [esp+8] ;ebx = 7 call dump ret f ENDP Can you suggest another way to perform this clean up?
Passing arguments to functions via the stack main PROC ;program execution begins here mov eax, 7 push eax ;push the contents of eax on the stack push 4 ;push the value 4 on the stack call f add esp, 8 ;must clean up stack! mov eax, input(prompt) ;prompt the user exit ;end of program main ENDP ;---------------------------------------------------------------------- f PROC mov eax, [esp+4] ;eax = 4 mov ebx, [esp+8] ;ebx = 7 call dump ret f ENDP Another way to perform this clean up.
Passing arguments to functions via the stack main PROC ;program execution begins here mov eax, 7 push eax ;push the contents of eax on the stack push 4 ;push the value 4 on the stack call f add esp, 8 ;must clean up stack! mov eax, input(prompt) ;prompt the user exit ;end of program main ENDP ;---------------------------------------------------------------------- f PROC mov eax, [esp+4] ;eax = 4 mov ebx, [esp+8] ;ebx = 7 call dump ret f ENDP But this functions modifies eax and ebx. How can we modify this function to NOT change any registers?
Passing arguments to functions via the stack f PROC push eax ;save reg used push ebx ;save reg used mov eax, [esp+12] ;get arg mov ebx, [esp+16] ;get another arg . . . pop ebx ;restore reg used pop eax ;restore reg used ret f ENDP We modified this to NOT change any registers.
n! (n factorial) • The number of ways n objects can be permuted (arranged). • For example, consider 3 things, A, B, and C. 3! = 6 • ABC • ACB • CAB • CBA • BCA • BAC • The first few factorials for n = 0, 1, 2, 3, 4, 5 are 1, 1, 2, 6, 24, 120.
n! (n factorial) • n! for some non negative integer n is defined as: • n! = n * (n-1) * (n-2) * … * 2 * 1 • 0! is defined as 1. • from http://mathworld.wolfram.com/Factorial.html
Java version (iterative) public static int fact1 ( int n ) { int result = 1; for (int ecx=n; ecx>0; ecx--) { result = result * ecx; } return result; }
Iterativefactorial fact1 proc ;input: eax contains n (value to calculate n!) ;output: eax contains the result (n!) ;all other registers except edx are preserved push ecx ;save register used mov ecx, eax ;init loop counter to n mov eax, 1 ;to accumulate result (also n! = 1 for n<=1) cmp ecx, 1 ;check for 1! jle fact1Done ;br if 1! fact1Loop: mul ecx ;accumulate the result of n! jo fact1Error ;br if result is larger than 32 bits dec ecx ;dec our loop counter jnz fact1Loop ;br if not finished fact1Done: pop ecx ;restore register used ret ;return to caller fact1Error: ;handle errors pushad ;save all registers print SADD("fact1: overflow",CR,LF) ;output error message popad ;restore all registers pop ecx ;restore register used ret ;return to caller fact1 endp • Two things to note: • This is a common version of the for-loop. • How can we also preserve edx? (Where does edx change?)
n! (n factorial) • n! for some non negative integer n can be rewritten as: • 0! = 1 for n = 0 • 1! = 1 for n = 1 • n! = n * (n-1)! for all other n > 1
Mathematical induction • The idea of sequences in which later terms are deduced from earlier ones, which is implicit in the principle of mathematical induction, dates to antiquity. • The truth of an infinite sequence of propositions Pi for i=1, ..., is established if • P1 is true, and • Pk implies Pk+1 for all k. • This principle is sometimes also known as the method of induction. • from http://mathworld.wolfram.com/RecursiveSequence.html and http://mathworld.wolfram.com/PrincipleofMathematicalInduction.html
Mathematical induction • The idea of sequences in which later terms are deduced from earlier ones, which is implicit in the principle of mathematical induction, dates to antiquity. • The truth of an infinite sequence of propositions Pi for i=1, ..., is established if • P1 is true, and • Pk implies Pk+1 for all k. base case(s) inductive case(s)
Back to n! (n factorial) • n! for some non negative integer n can be rewritten as: • 0! = 1 for n = 0 • 1! = 1 for n = 1 • n! = n * (n-1)! for all other n > 1 base cases inductive case
Let’s code n! (n factorial) • n! for some non negative integer n can be rewritten as: • 0! = 1 for n = 0 • 1! = 1 for n = 1 • n! = n * (n-1)! for all other n > 1 public static int nFactorial ( int n ) { } base cases inductive case
Let’s code n! (n factorial) • n! for some non negative integer n can be rewritten as: • 0! = 1 for n = 0 • 1! = 1 for n = 1 • n! = n * (n-1)! for all other n > 1 public static int nFactorial ( int n ) { //base cases if (n==0) return 1; } base cases inductive case
Let’s code n! (n factorial) • n! for some non negative integer n can be rewritten as: • 0! = 1 for n = 0 • 1! = 1 for n = 1 • n! = n * (n-1)! for all other n > 1 public static int nFactorial ( int n ) { //base cases if (n==0) return 1; if (n==1) return 1; } base cases inductive case
Let’s code n! (n factorial) • n! for some non negative integer n can be rewritten as: • 0! = 1 for n = 0 • 1! = 1 for n = 1 • n! = n * (n-1)! for all other n > 1 public static int nFactorial ( int n ) { //base case if (n<=1) return 1; //more generic/robust } base cases inductive case
Let’s code n! (n factorial) • n! for some non negative integer n can be rewritten as: • 0! = 1 for n = 0 • 1! = 1 for n = 1 • n! = n * (n-1)! for all other n > 1 public static int nFactorial ( int n ) { //base case if (n<=1) return 1; return n * nFactorial( n-1 ); } base cases inductive case
Let’s code n! (n factorial) • n! for some non negative integer n can be rewritten as: • 0! = 1 for n = 0 • 1! = 1 for n = 1 • n! = n * (n-1)! for all other n > 1 public static int nFactorial ( int n ) { //base case if (n<=1) return 1; return n * nFactorial( n-1 ); } This is an example of a recursive function (a function that calls itself)! To use this function: int result = nFactorial( 10 );