1

私はアセンブリにまったく慣れていませんが、2次元の「配列」に値を割り当てるときに問題が発生しました。私の配列は.space名前が付けられscreenており、が割り当てられてHEIGHT * WIDTH * 4いるため、十分なスペースがあります。

以下のコマンドを実行する前に、配列には値のみが含まれています(以下のコマンドを発行する前に、配列をループしてすべての値をに設定し、すべての値を出力して検証した0ため、これを知っています)。0

これが私がすることです:

movl $0, %eax
movl $1, %ebx
movl $20, screen(%eax, %ebx, 4)

そして、これが結果になります(すべての行と列をリストする場合):

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

私が期待していたのは、screen[0][1]:の変化を見ることだけでしたx:0 y:1 value:20。これらの「ガベージ」値(、、など)の原因は3355443201310720ですか5120

私が言ったように、私は完全な初心者なので、いい人になりましょう!

編集: ゼロフィル関数と配列内のすべての値を一覧表示する関数を提供しています。

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
#################################

編集2:アンドレアスからの入力の後、私はこの関数を作成しました:

# 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

編集3 まだ正しくないことがあります。今これを行うとき:

movl $0, %eax
movl $2, %ebx
call screen_get_address
movl $20, (%eax)

私は(3x3配列)を取得します:

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
4

1 に答える 1

1

アドレスを計算するためのコードが間違っています。2D dword配列の(%ebx = x、%ecx = y)要素にアクセスするには、次のデータにアクセスする必要があります。

 screen + 4*(%ecx*WIDTH + %ebx)

あなたはscreen(%ebx、%ecx、4)にアクセスしています。

screen + %ebx + 4*%ecx

つまり、間違った位置です。movl命令の前に、最初にアドレスを生成する必要があります(たとえば、MULを使用するか、WIDTHが2の累乗の場合は、shift命令を使用します)。すべての要素をループするだけの場合は、継続的にインクリメントされる単一のポインターを使用することで、複雑なアドレス計算を回避できます。

于 2012-10-18T23:30:39.697 に答える