2013-02-20 88 views
0

好的,为了使事情尽可能简单,说我有一个基本的循环,我想用来修改标记为a的数组的一些元素。在下面的示例代码中,我尝试用1替换1的所有元素,但这并不起作用。8086程序集 - 如何访问循环内的数组元素

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 

我知道我可以简单地通过修改存储在allodsb指令之后的元素做到这一点,只是存储。但我想知道是否有可能做到像我上面尝试过的那样。

回答

5

在x86汇编中,不能使用存储在内存中的值间接寻址内存。

您需要将i读入可用于存储器寻址的某个寄存器,然后使用该寄存器。您可能需要检查Wikipedia for 8086 memory addressing modes

所以,更换

mov ds:si[i],1 

与(段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 

或者,如果你想节省1个字节,并使用loop指令。

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

注意,在16位模式loop指令递减cx,并跳转到标签如果cx不递减后为零。但是,在32位模式下,loop递减ecx,在64位模式(x86-64)下递减rcx

+1

'mov bx,[i]'如果'i'是一个字节就不会组装或工作正常。你用'movzx'弄明白了。但知道这是80386+指令可能很重要。 – 2013-02-20 13:09:31

+0

@AlexeyFrunze你是对的,所以我修复它并转换为8088/8086代码。 – nrz 2013-02-20 13:12:00

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]是不必要的,因为这是默认值。请参阅The 80x86 Addressing Modes