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
Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top