IA32 Addressing Modes

advertisement
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
B
=
12
dword 52
mov
mov
mov
mov
eax, 1
ebx, eax
ecx, A
edx, B
; immediate
; register
; immediate
; direct memory
IA32 addressing modes
1. Immediate
2. Direct memory
3. Register
4. Register indirect
5. Indexed
6. Based-indexed
(new)
(new)
(new)
REGISTER INDIRECT
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
mov
eax, offset A
;store addr of A in eax
;lea = load effective addr
;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
mov
add
eax, offset tbl ;eax points to the first table entry
ebx, [eax]
;ebx contains the first table entry
eax, 4
;eax now points to next table entry
Sum up values in a table
tbl
dword 1, 2, 7, 22, 59, 100
mov
mov
add
eax, offset tbl ;eax points to the first table entry
ebx, [eax]
;ebx contains the first table entry
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
mov
add
add
…
eax, offset tbl
ebx, [eax]
eax, 4
ebx, [eax]
;eax points to the first table entry
;ebx contains the first table entry
;eax now points to next table entry
; sum the second entry
Sum up values in a table
tbl
dword 1, 2, 7, 22, 59, 100
mov
mov
add
add
add
add
add
add
add
add
add
add
eax, offset tbl
ebx, [eax]
eax, 4
ebx, [eax]
eax, 4
ebx, [eax]
eax, 4
ebx, [eax]
eax, 4
ebx, [eax]
eax, 4
ebx, [eax]
;eax points to the first table entry
;ebx contains the first table entry
;eax now points to next table entry
;sum the second entry
;sum the third
;sum the fourth
;sum the fifth
;sum the sixth
Note: If we know that
we have N entries in
the table, we can use
a loop instead.
INDEXED
Indexed
Used to:
1. 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
2. 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
mov
mov
eax, 4
ebx, A[eax]
ecx, [A+eax]
;what’s in ebx?
;what’s in ecx?
Indexed
A
dword
592h, 50h, 60h, 70h, 80h, 90h
mov
mov
mov
eax, 4
ebx, A[eax]
ecx, [A+eax]
;what’s in ebx?
;what’s in ecx?
Using indexed addressing to sum
up values in a table
tbl
dword 1, 2, 7, 22, 59, 100
mov
mov
add
add
add
add
add
add
add
add
add
add
eax, 0
ebx, tbl[eax]
eax, 4
ebx, tbl[eax]
eax, 4
ebx, tbl[eax]
eax, 4
ebx, tbl[eax]
eax, 4
ebx, tbl[eax]
eax, 4
ebx, tbl[eax]
;eax is offset from start of table
;ebx contains the first table entry
;eax now is offset to next table entry
;sum the second entry
;sum the third
;sum the fourth
;sum the fifth
;sum the sixth
BASED-INDEXED
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
Based-indexed
Using based-indexed addressing to
sum up values in a table (approach #1)
tbl
dword 1, 2, 7, 22, 59, 100
mov
mov
inc
add
inc
add
inc
add
inc
add
inc
add
eax, 0
ebx, tbl[eax*4]
eax
ebx, tbl[eax*4]
eax
ebx, tbl[eax*4]
eax
ebx, tbl[eax*4]
eax
ebx, tbl[eax*4]
eax
ebx, tbl[eax*4]
;offset from start of table
;get first table entry
;subscript of next table entry
;sum the second entry
;sum the third
;sum the fourth
;sum the fifth
;sum the sixth
Using based-indexed addressing to
sum up values in a table (approach #2)
tbl
dword
mov
mov
mov
inc
add
inc
add
inc
add
inc
add
inc
add
1, 2, 7, 22, 59, 100
eax, offset tbl
;point to start of table
ebx, 0
;offset from start of table
ecx, [eax+ebx*4] ;get first table entry
ebx
;subscript of next table entry
ecx, [eax+ebx*4] ;sum the second entry
ebx
ecx, [eax+ebx*4] ;sum the third
ebx
ecx, [eax+ebx*4] ;sum the fourth
ebx
ecx, [eax+ebx*4] ;sum the fifth
ebx
ecx, [eax+ebx*4] ;sum the sixth
Using based-indexed addressing to
sum up values in a table (approach #3)
tbl
dword
mov
mov
mov
add
add
add
add
add
add
add
add
add
add
1, 2, 7, 22, 59, 100
eax, offset tbl
;points to start of table
ebx, 0
;offset from start of table
ecx, [eax+ebx] ;get first table entry
ebx, 4
;offset of next table entry
ecx, [eax+ebx] ;sum the second entry
ebx, 4
ecx, [eax+ebx] ;sum the third
ebx, 4
ecx, [eax+ebx] ;sum the fourth
ebx, 4
ecx, [eax+ebx] ;sum the fifth
ebx, 4
ecx, [eax+ebx] ;sum the sixth
USING THESE ADDRESSING MODES
Methods of passing arguments to
functions
• Methods:
1. Use registers.
2. Use stack.
3. 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
mov
call
call
eax, offset afterCall
dump
f
;program execution begins here
;addr of inst after call f
;show contents of regs
afterCall:
mov
eax, input(prompt) ;prompt the user
exit
;end of program
main
ENDP
Note: In f, esp points to
;---------------------------------------------------------------------return address which is
location of afterCall.
f
PROC
f
mov
call
ret
ENDP
eax, [esp]
dump
;gets addr of return address
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
Can you suggest
pop
eax
;must clean up stack!
another way to
perform this clean
pop
eax
;must clean up stack!
up?
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
push
push
call
add
eax, 7
eax
4
f
esp, 8
;push the contents of eax on the stack
;push the value 4 on the stack
;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
push
push
call
add
eax, 7
eax
4
f
esp, 8
;push the contents of eax on the stack
;push the value 4 on the stack
;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
f
push
push
mov
mov
.
.
.
pop
pop
ret
ENDP
eax
ebx
eax, [esp+12]
ebx, [esp+16]
;save reg used
;save reg used
;get arg
;get another arg
We modified this to
NOT change any
registers.
ebx
eax
;restore reg used
;restore reg used
CALCULATING FACTORIAL
n! (n factorial)
•
•
The number of ways n objects can be permuted
(arranged).
For example, consider 3 things, A, B, and C.
1.
2.
3.
4.
5.
6.
•
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;
}
fact1
proc
push
mov
mov
cmp
jle
;input:
eax contains n (value to calculate n!)
;output: eax contains the result (n!)
;all other registers except edx are preserved
ecx
;save register used
ecx, eax
;init loop counter to n
eax, 1
;to accumulate result (also n! = 1 for n<=1)
ecx, 1
;check for 1!
fact1Done
;br if 1!
mul
jo
dec
jnz
ecx
fact1Error
ecx
fact1Loop
Iterative
factorial
fact1Loop:
fact1Done:
pop
ret
fact1Error:
fact1
pushad
print
popad
pop
ret
endp
ecx
;accumulate the result of n!
;br if result is larger than 32 bits
;dec our loop counter Two things to note:
;br if not finished
1. This is a common version
of the for-loop.
;restore register used
;return to caller
2. How can we also
;handle errors
preserve edx? (Where
;save all registers
does edx change?)
SADD("fact1: overflow",CR,LF) ;output error message
;restore all registers
ecx
;restore register used
;return to caller
BUT CAN WE DO IT RECURSIVELY?
n! (n factorial)
• n! for some non negative integer n can be
rewritten as:
– 0! = 1
– 1! = 1
– n! = n * (n-1)!
for n = 0
for 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
1. P1 is true, and
2. 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
1. P1 is true, and
2. 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
– 1! = 1
– n! = n * (n-1)!
for n = 0
for 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
– 1! = 1
– n! = n * (n-1)!
for n = 0
for 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
– 1! = 1
– n! = n * (n-1)!
for n = 0
for 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
– 1! = 1
– n! = n * (n-1)!
for n = 0
for 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
– 1! = 1
– n! = n * (n-1)!
for n = 0
for n = 1
for all other n > 1
base cases
inductive
case
public static int nFactorial ( int n ) {
//base case
if (n<=1)
return 1; //more generic/robust
}
Let’s code n! (n factorial)
• n! for some non negative integer n can be rewritten
as:
– 0! = 1
– 1! = 1
– n! = n * (n-1)!
for n = 0
for 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
– 1! = 1
– n! = n * (n-1)!
for n = 0
for n = 1
for all other n > 1
public static int nFactorial ( int n ) {
//base case
This is an example of a
if (n<=1)
return 1;
recursive function (a
return n * nFactorial( n-1 );
}
function that calls
itself)!
To use this function:
int result = nFactorial( 10 );
fact2
proc
cmp
jle
push
mov
dec
call
mul
jo
pop
ret
;input:
eax contains n (value to calculate n!)
;output: eax contains the result (n!)
;all other registers except edx are preserved
eax, 1
;base case when eax=1
fact2One
;br if 1 (actually <=1)
ebx
;save reg used
ebx, eax
;save copy of n so we can calculate (n-1)!
eax
;get ready to calculate (n-1)!
fact2
;calculate (n-1)!
ebx
;calculate n*[(n-1)!]
fact2Error
;br if result is larger than 32 bits
ebx
;restore reg used
;return to caller
Recursive
factorial
fact2One:
mov
ret
fact2Error:
fact2
pushad
print
popad
pop
ret
endp
eax, 1
;1! = 1
;return to caller
;handle errors
;save all registers
SADD("fact2: overflow",CR,LF) ;output error message
;restore all registers
ebx
;restore reg used
;return to caller
Summary of IA32 addressing
modes
1. Immediate
2. Direct memory
3. Register
4. Register indirect
5. Indexed
6. Based-indexed
mov
mov
mov
mov
mov
mov
mov
eax, 12
eax, X
ebx, eax
ebx, [eax]
ebx, T[eax]
ebx, [T+eax]
ecx, [eax + ebx*2 + T]
Methods of passing arguments to
functions
• Methods:
1. Use registers.
2. Use stack.
3. Use one register which points to a
parameter block.
.data
Point3D
struct
x
dword
0
y
dword
0
z
dword
0
Point3D
ends
//structure defn.
p1
p2
//p1 w/ default values
//p2 w/ specified values
Point3D
Point3D
{}
{1, 2, 3}
.data
Point3D struct
x
dword 0
y
dword 0
z
dword 0
Point3D ends
p1
p2
//structure defn.
Point3D { }
Point3D {1, 2, 3}
mov
mov
mov
call
eax, p2.x
ebx, p2.y
ecx, p2.z
dump
//p1 w/ default values
//p2 w/ specified values
;get x value
;get y value
;get z value
.data
Point3D struct
x
dword 0
y
dword 0
z
dword 0
Point3D ends
p1
p2
//structure defn.
Point3D { }
Point3D {1, 2, 3}
lea
mov
call
eax, p2
ebx, offset p2
dump
//p1 w/ default values
//p2 w/ specified values
;get addr of p2
;get addr of p2 via another method
.data
Point3D struct
x
dword 0
y
dword 0
z
dword 0
Point3D ends
p1
p2
//structure defn.
Point3D { }
Point3D {1, 2, 3}
//p1 w/ default values
//p2 w/ specified values
lea
mov
call
eax, p2
ebx, offset p2
dump
mov
mov
mov
mov
mov
call
Point3D.x[eax], 5
Point3D.z[eax], 10
eax, p2.x
ebx, p2.y
ecx, p2.z
dump
;get addr of p2
;get addr of p2 via another method
eax contains the base address of
structured data that can be
referenced by called functions!
(Point3D.x is simply the offset to x
;get x
from the start of the struct.)
;get y
;get z
Download