Garbage values when assigning values to two dimensional array
题
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
解决方案
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.