Garbage values when assigning values to two dimensional array
Question
I'm completely new to assembly and I've encountered an issue when assigning values to my two dimensional "array". My array is a .space
named screen
and is allocated with HEIGHT * WIDTH * 4
, so there is enough space.
Before I do the commands below the array contains only 0
values (I know this because before issuing the commands below I loop through the array and set all values to 0
, and verified it by printing out all values).
This is what I do:
movl $0, %eax
movl $1, %ebx
movl $20, screen(%eax, %ebx, 4)
And this is what it results in (when listing all rows and columns):
x:0 y:0 value:0
x:0 y:1 value:20
x:0 y:2 value:0
x:0 y:3 value:0
x:0 y:4 value:0
x:1 y:0 value:335544320
x:1 y:1 value:0
x:1 y:2 value:0
x:1 y:3 value:0
x:1 y:4 value:0
x:2 y:0 value:1310720
x:2 y:1 value:0
x:2 y:2 value:0
x:2 y:3 value:0
x:2 y:4 value:0
x:3 y:0 value:5120
x:3 y:1 value:0
x:3 y:2 value:0
x:3 y:3 value:0
x:3 y:4 value:0
x:4 y:0 value:20
x:4 y:1 value:0
x:4 y:2 value:0
x:4 y:3 value:0
x:4 y:4 value:0
What I was expecting was only to see a change in screen[0][1]
: x:0 y:1 value:20
. What is causing these "garbage" values (335544320
, 1310720
, 5120
etc)?
As I mentioned I'm a complete beginner, so be nice!
Edit: I'm supplying the zero filling function and the function for listing all the values in the array.
HEIGHT = 5
WIDTH = 5
EMPTY = 0
.section .data
counter: .int 0
counter2: .int 0
str3: .string "x:%d y:%d value:%d\n"
.section .text
#################################
# Fill screen array with zeroes
init_screen:
#################################
movl $0, counter
init_screen_array_x:
movl $0, counter2
init_screen_array_y:
movl counter, %ebx
movl counter2, %ecx
movl $EMPTY, screen(%ebx, %ecx, 4)
incl counter2
cmpl $HEIGHT, counter2
jl init_screen_array_y
incl counter
cmpl $WIDTH, counter
jl init_screen_array_x
ret
#################################
# end init_screen
#################################
#################################
# Debugging function, list all values in array
list_screen_array:
#################################
movl $0, counter
list_screen_array_x:
movl $0, counter2
list_screen_array_y:
movl counter, %ebx
movl counter2, %ecx
pushl screen(%ebx, %ecx, 4)
pushl counter2
pushl counter
pushl $str3
call printf
addl $16, %esp
incl counter2
cmpl $HEIGHT, counter2
jl list_screen_array_y
incl counter
cmpl $WIDTH, counter
jl list_screen_array_x
ret
#################################
# end list_screen
#################################
Edit 2: After the input from Andreas, I made this function:
# x should be stored in %eax
# y should be stored in %ebx
# saves address to screen[%eax][%ebx] in %eax
screen_get_address:
imull $4, %eax
imull $4, %ebx
imull $WIDTH, %ebx
addl %ebx, %eax
addl screen, %eax
ret
Edit 3 There's still something that isn't right. Now when doing this:
movl $0, %eax
movl $2, %ebx
call screen_get_address
movl $20, (%eax)
I get (3x3 array):
x:0 y:0 value:0
x:0 y:1 value:0
x:0 y:2 value:20
x:1 y:0 value:0
x:1 y:1 value:20
x:1 y:2 value:0
x:2 y:0 value:20
x:2 y:1 value:0
x:2 y:2 value:0
Solution
Your code to compute the address is wrong. To access the (%ebx=x,%ecx=y) element of a 2D dword array you need to access the data at
screen + 4*(%ecx*WIDTH + %ebx)
you are accessing screen(%ebx, %ecx, 4), which is
screen + %ebx + 4*%ecx
i.e. the wrong position. Prior to your movl instruction you have to generate the address first (e.g using MUL, or, if WIDTH is a power of 2, using the shift instruction). If you only want to loop over all elements, you can spare the complicated address calculation by using just a single pointer which is continuously incremented.