Assembly Language Part 7 (homogeneous arrays)

advertisement
cs3843
syllabus
outline
lecture notes
programming
assignments
recitations
homework
set up
Homogeneous Arrays
Homogeneous arrays are arrays where each element has the
same data type and size.
We will discuss
 One-dimensional arrays
o size of array and elements
o how to reference an element
 Two-dimensional arrays
o size of elements, rows, and arrays
o how to reference an element
One-dimensional Array and Element Sizes
For one-dimensional arrays in C, the lower bounds of the
subscript is always zero. The size of each element is always
the same.
Some programming languages (e.g., PL/I) allow specification
of both the lower bounds and upper bounds for each array
dimension. Other languages use 1 as the lower bounds.
Example declarations in C:
char
szString[10];
char
*pszString[10];
long
lvalM[5];
long
*plvalM[5];
double dvalM[5];
double *pdvalM[5];
unsigned short usvalM[8];
How to reference an element in one-dimensional arrays
Given array A having an element size of E, how do you find
the address of element A[i]?
sum the beginning address of A and i * E
Using i in the calculation is determining element address
Array Name
szString
pszString
lvalM
plvalM
dvalM
pdValM
usvalM
Element Size
(bytes)
1
Total Array
Size (bytes)
10
4
20
8
4
2
40
20
16
If β is the starting address of A and E is 4, this shows the
address of each element.
subscript 0
1
2
3
4
β
β+E
β+2E
β+3E
β+4E
using a subscript reference.
For most one-dimensional arrays of primitive data, what are
the element sizes? 1, 2, 4, 8
In IA32 assembly code, is it necessary to multiply i by E?
Code for sumArray
4 int sumArray(int iValueM[], int iCnt)
5 {
6
int i;
7
int isum = 0;
8
for (i = 0; i < iCnt; i++)
9
{
10
isum += iValueM[i];
11
}
12
return isum;
13 }
Using pointer advancement
Another approach to referencing elements is pointer
advancement.
 Use a register as a cursor pointer which will contain
the address of the current array element.
 That cursor pointer register begins with the beginning
address of the array.
 Advancing to the next element is done by adding the
element size, E, to that register.
 Terminate the loop when the cursor pointer advances
past the last element. If there are N elements in the
array, terminate when we reach β+E*N. That
sumArray using gcc -O0 which used subscript reference
3 .globl sumArray
4
.type
5 sumArray:
6
pushl
7
movl
8
subl
9
movl
10
movl
11
jmp
12 .L3:
#
# loop body
#
13
movl
14
sall
15
addl
16
movl
17
addl
18
addl
19 .L2:
#
loop test
20
movl
21
cmpl
22
jl
# After loop
23
movl
24
leave
25
ret
sumArray, @function
%ebp
%esp, %ebp
$16, %esp
$0, -8(%ebp)
$0, -4(%ebp)
.L2
#
#
#
#
-4(%ebp), %eax
$2, %eax
8(%ebp), %eax
(%eax), %eax
%eax, -8(%ebp)
$1, -4(%ebp)
# i -> %eax
# i * 4 -> %eax
# addr of array + i * 4
# value of element of array -> %eax
# add element to isum
# i++
-4(%ebp), %eax
12(%ebp), %eax
.L3
# i -> %eax
# compare i:iCnt
# i < iCnt, continue loop
-8(%ebp), %eax
get 16 bytes on stack
0 -> isum
0 -> i
jump to loop test
# prepare isum for return
5 sumArray:
# Register Usage:
#
%edx - address just past last element (endPtr)
#
%eax - work and then isum
#
%ecx - pointer cursor into array
6
pushl
%ebp
7
movl
%esp, %ebp
# no locals, not calling anything, not modifying callee save registers
# so we do not need automatic memory
8
movl
8(%ebp), %ecx # address of array -> %ecx
9
movl
12(%ebp), %eax
# icnt -> %eax
# determine end pointer
10
leal
(%ecx,%eax,4), %edx # array addr + 4*icnt -> %edx
11
movl
$0, %eax
# 0 -> isum
#
# see if cursor >= endPtr, if so skip loop
#
12
cmpl
%edx, %ecx
# compare cursor:endPtr
13
jae
.L3
# if cursor >= endPtr, skip loop
address is our end pointer.
Two-dimensional Arrays
C stores two-dimensional arrays in row major order. This
means the entire first row is in memory followed by the
entire second row, and so on.
14 .L6:
#
# Loop body
#
15
addl
16
addl
#
#
if cursor
17
cmpl
18
ja
19 .L3:
# Why didn't we
20
popl
21
ret
(%ecx), %eax
$4, %ecx
# Add element to sum
# Add element size to pointer
< endPtr, loop
%ecx, %edx
.L6
# compare endPtr:cursor
# if endPtr > cursor, loop
do a leave?
%ebp
int A[4][3];
Shown as two-dimensional:
Column 0
Column 1
Row 0
0
1
Row 1
10
11
Row 2
20
21
Row 3
30
31
Shown contiguous in memory:
0
1
2
10
11
[0][0]
[0][1]
first row
row 0
[0][2]
[1][0]
12
[1][1]
[1][2]
second row
(row 1)
Column 2
2
12
22
32
20
21
22
30
[2][0]
[2][1]
third row
(row 2)
[2][2]
[3][0]
31
32
[3][1]
[3][2]
fourth row
(row 3)
How big is a two-dimensional array
Assuming an element is size E, the number of rows is R, and
the number of columns is C:
row size is E*C
array size is E*C*R
For A in the previous example:
 E is 4
 R is 4
 C is 3
Therefore,
 row size = E*C = 4*3 = 12
 array size is E*C*R = 12 * 4 = 48 bytes
How to reference an element in two-dimensional arrays
Given array A having
 β as its beginning address
 element size of E
 R rows
 C columns
How do you find the address of element A[i][j] using a
subscript reference approach?
β + rowSize*i + E*j
Assume:
 i is in %eax
 j is in %ecx
 β is in %ebx
 E is 4
Depending on the value of C, what could we do to compute the
address of element A[i][j]?
Number of
Instructions
Columns (C)
β + C*E*i + E*j
β + (C*i + j) * E
2
leal (%ecx, %eax, 2), %edx
leal (%ebx, %edx, 4), %edx
The multiplication by E uses shifting since E is usually 1, 2, 4
or 8.
3
Depending on the value of C, multiple leal instructions or a
imull instruction is used.
4
leal
addl
sall
leal
leal
(%eax, %eax, 2), %edx
%ecx, %edx
2, %edx
(%ecx, %eax, 4), %edx
(%ebx, %edx, 4), %edx
leal
addl
sall
leal
sall
addl
sall
(%eax, %eax, 4), %edx
%ecx, %edx
2, %edx
(%eax, %eax, 4), %edx
1, %edx
%ecx, %edx
2, %edx
5
10
C code for function sum2dArray
4 int sum2dArray(int iValueM[][5], int iRowCnt)
5 {
6
int i;
7
int j;
8
int isum = 0;
9
for (i = 0; i < iRowCnt; i++)
10
{
11
for (j = 0; j < 5; j++)
12
{
13
isum += iValueM[i][j];
14
}
15
}
16
return isum;
17 }
sum2dArray using gcc -O0
# Parameters:
#
i 8(%ebp) iValueM[][5] - address of 2d array with 5 columns
#
i 12(%ebp) iRowCnt - count of rows in the 2d array
# Locals:
#
-4(%ebp)
i - row subscript
#
-8(%ebp)
j - column subscript
#
-12(%ebp)
iSum - sum of the elements
3 .globl sum2dArray
4
.type
sum2dArray, @function
5 sum2dArray:
6
pushl
%ebp
7
movl
%esp, %ebp
8
subl
$16, %esp
9
movl
$0, -12(%ebp)
# 0 -> iSum
10
movl
$0, -4(%ebp)
# 0 -> i
11
jmp
.L2
# Jump to Outer Loop test
# Outer Loop Body
12 .L5:
13
movl
$0, -8(%ebp)
# 0 -> j
14
jmp
.L3
# Jump to inner loop test
15 .L4:
#
Inner Loop Body
#
Calculate the rowAddress &iValueM + i*20
#
16
movl
-4(%ebp), %edx
# i -> %edx
17
movl
%edx, %eax
# i -> %eax
18
sall
$2, %eax
# i * 4 -> %eax
19
addl
%edx, %eax
# i * 5 -> %eax
20
sall
$2, %eax
# i * 20 -> %eax. 20 is row size
21
movl
%eax, %edx
# i * 20 -> %edx
22
addl
8(%ebp), %edx
# add &iValueM to %edx. This is
# the rowAddress
23
movl
-8(%ebp), %eax
# j -> %eax
#
The next instruction computes the address of the element by
#
adding j*4 and the row address. It then takes the element's
value
#
and places it in %eax
24
movl
(%edx,%eax,4), %eax # value at (j*4 + rowAddress) -> %eax
25
addl
%eax, -12(%ebp)
# Add element value to iSum
26
addl
$1, -8(%ebp)
# j++
27 .L3:
#
Inner Loop Test
28
cmpl
$4, -8(%ebp)
# compare j:4
29
jle
.L4
# if j <= 4, stay in inner loop
# After Inner Loop
30
addl
$1, -4(%ebp)
# i++
31 .L2:
# Outer loop test
32
movl
-4(%ebp), %eax
# i -> %eax
33
cmpl
12(%ebp), %eax
# compare i:iRowCnt
34
jl
.L5
# if i < iRowCnt, loop to .L5
# After Outer loop
35
movl
-12(%ebp), %eax
# return iSum
36
leave
37
ret
How can we make lines 16-25 more efficient?
We had:
16
17
18
19
20
21
22
%edx.
23
24
25
movl
movl
sall
addl
sall
movl
addl
-4(%ebp), %edx
%edx, %eax
#
$2, %eax
#
%edx, %eax
#
$2, %eax
#
%eax, %edx
#
8(%ebp), %edx #
# i -> %edx
i -> %eax
i * 4 -> %eax
i * 5 -> %eax
i * 20 -> %eax.
i * 20 -> %edx
add &iValueM to
movl
movl
addl
-8(%ebp), %eax
# j -> %eax
(%edx,%eax,4), %eax # element value
%eax, -12(%ebp) # Add element value
More efficient for 5 columns, but using subscripts
16
movl
-4(%ebp), %eax
# i -> %eax
17
leal
(%eax,%eax,4), %edx # i*5 -> %edx
18
addl
-8(%ebp), %edx
# i*5 + j -> %edx
19
movl
8(%ebp), %ecx
# &iValueM -> %ecx
# next instruction computes the address of the element and moves its
# value to %eax
20
movl
(%ecx,%edx,4), %eax
# element value in %eax
21
addl
%eax, -12(%ebp)
# Add element value to iSum
Download