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入一些可用于内存寻址的寄存器,然后改用它。您可能需要查看Wikipedia 以了解 8086 内存寻址模式

所以,更换

mov ds:si[i],1

with (ds这里不需要段,因为它也是 , 的默认值si) :bxbx+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

或者,如果您想保存 1 个字节并使用loop指令。

 @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 回答