0

わかりました。できるだけ簡単にするために、aというラベルの付いた配列のいくつかの要素を変更するために使用したい基本的なループがあるとします。次のサンプルコードでは、aのすべての要素を1に置き換えようとしましたが、実際には機能しません。

assume cs:code ,ds:data
data segment
  a db 1,2,3,4
  i db 0
data ends

code segment
start:
  mov ax,data
  mov ds,ax

  lea si,a

  the_loop:
    mov cl,i
    cmp cl,4
    jae the_end

    mov ds:si[i],1      ; this is the part that i don't really understand since
    inc i               ; i'm expecting i=0 and ds:si[i] equiv to ds:si[0] which
  loop the_loop         ; is apparently not the case here since i actually receives the
                        ; the value 1
  the_end:
    mov ax,4c00h
    int 21h
code ends
end start

命令alの後に格納されている要素を変更するだけでこれを実行でき、それを格納するだけでよいことを認識しています。lodsbしかし、私が上で試したようなことをすることが可能かどうか知りたいです。

4

2 に答える 2

5

x86アセンブリでは、メモリに格納されている値を使用して、メモリを間接的にアドレス指定することはできません。

iメモリアドレス指定に使用できるレジスタを読み込んで、代わりに使用する必要があります。ウィキペディアで8086メモリアドレッシングモードを確認することをお勧めします。

だから、交換してください

mov ds:si[i],1

with(セグメントはデフォルトであるため、ここでdsは不要です):sibxbx+si

xor bx,bx
mov bl,[i]
mov [bx+si],byte 1 ; some other assemblers want byte ptr

コードには他にも問題があります。ループ全体を簡単にして、次のように修正できます。

    lea  si,a

    xor  cx,cx
    mov  cl,[i]

@fill_loop:
    mov  [si], byte 1
    inc  si
    dec  cx
    jnz  @fill_loop

loopまたは、1バイトを節約して命令を使用したい場合。

 @fill_loop:
    mov  [si], byte 1
    inc  si
    loop @fill_loop

16ビットモードでは、loop命令はデクリメントされ、デクリメント後にゼロでないcx場合はラベルにジャンプすることに注意してください。cxただし、32ビットモードではloopデクリメントecxし、64ビットモード(x86-64)ではデクリメントしますrcx

于 2013-02-20T12:55:18.073 に答える
1

あなたのコードはアセンブラを介してさえ実行されないと思います。

mov ds:si[i],1

は有効なアドレスモードではありません。

次のようなものを使用します

mov byte ptr [si],1  ; store value 1 at [SI]
inc si               ; point to next array element

代わりに(MASMを使用して構文を検証しました)。

これがデフォルトであるため、DS:プレフィックスは不要です。[si]

80x86アドレッシングモードも参照してください。

于 2013-02-20T12:55:36.217 に答える