assembly 汇编语言使用循环的代码

62lalag4  于 7个月前  发布在  其他
关注(0)|答案(2)|浏览(85)

我已经得到了这个代码,但我如何使用循环来实现它呢?基本上,它是一个代码,将x数组中的第一个值添加到下一个值中,将其保存到y数组中的第一个值中,然后将x数组中的第二个值添加到第三个值中,并将其存储到y数组中的第二个值中,以此类推,然后取x的最后一个值,将其与x的第一个值相加,并将其保存到y的最后一个值。

.data  
    x   sword   10,20,30,-10,-20, -30  
    y   sword   6 dup (?)

    mov     ax,x                                
    add     x+2,ax  
    mov         y,ax

    mov     ax,x+2                              
    add     x+4,ax  
    mov         y+2,ax

    mov     ax,x+4                              
    add     x+6,ax  
    mov         y+4,ax

    mov     ax,x+6                              
    add     x+8,ax  
    mov         y+6,ax

    mov     ax,x+8                              
    add     x+10,ax  
    mov         y+8,ax

    mov     ax,x+10                             
    add     x,ax  
    mov         y+10,ax

字符串

vsikbqxv

vsikbqxv1#

这是一段代码,它将x数组中的第一个值加到下一个值将其保存到y中的第一个值,然后将x中的第二个值加到第三个值中,并将其存储在y中的第二个值中,依此类推。然后将x的最后一个值加到x的第一个值中,并将其保存到y的最后一个值中。
这是一个模棱两可的措辞!“adds it to the next”并不一定意味着将和写入 X 数组,就像“saves it to the first value in y”并不一定意味着它是原始值(在加法之前)进入 Y 数组。这就是你展示给我们的展开代码的方式,但它不是@SevaAlekseyev的答案中的伪代码的方式,所以要小心!
我的答案中的代码片段就像 * 你 * 所展示的那样,因为句子“然后它取x的最后一个值,然后将其添加到x的第一个值,并将其保存到y的最后一个值。”

编写循环

最简单的解决方案是为 X 数组使用一个地址寄存器,为 Y 数组使用另一个地址寄存器。如果这需要是8086代码,那么你可以在BX,SI,DI和BP之间进行选择。“索引”寄存器SI和DI是逻辑选择。由于你的数组有6个元素,但处理最后一个元素有些特殊,你可以将CX中的计数器初始化为小于1,so 5,然后在循环外单独处理最后一个元素。这将避免插入条件分支:

.data  
    x   sword   10, 20, 30, -10, -20, -30  
    y   sword   6 dup (?)

  mov  di, OFFSET y
  mov  si, OFFSET x
  mov  cx, 5
more:
  mov  ax, [si]         ; mov  ax, x
  add  si, 2
  add  [si], ax         ; add  x+2, ax
  mov  [di], ax         ; mov  y, ax
  add  di, 2
  loop more
  mov  ax, [si]         ; mov  ax, x+10
  add  x, ax            ; add  x, ax
  mov  [di], ax         ; mov  y+10, ax

字符串
接下来是另一种方法,它也避免了插入条件分支。注意在 X 数组末尾的额外单词,我将在第六次常规迭代中使用它,然后在 X 数组的第一个元素上纠正add。既然我们假设8086,为什么不使用lodswstosw字符串原语来缩短代码:

.data  
    x   sword   10, 20, 30, -10, -20, -30, ?
    y   sword   6 dup (?)

  mov  di, OFFSET y
  mov  si, OFFSET x
  mov  cx, 6
more:
  lodsw                 ; mov  ax, x
  add  [si], ax         ; add  x+2, ax
  stosw                 ; mov  y, ax
  loop more
  add  x, ax            ; add  x, ax


下一段代码展示了如何使用单个索引而不是单独的指针。索引递增2,因为它实际上是数组中的偏移量,数组中保存 word 大小的元素。这段代码还演示了你不必使用loop指令本身。在8086代码中,这是可以的,但不要在32-bit中使用loop。位代码,其中它是慢指令:

.data  
    x   sword   10, 20, 30, -10, -20, -30  
    y   sword   6 dup (?)

  xor  bx, bx           ; Current offset in the arrays
more:
  mov  ax, [x + bx]     ; mov  ax, x
  mov  [y + bx], ax     ; mov  y, ax
  add  bx, 2
  add  [x + bx], ax     ; add  x+2, ax
  cmp  bx, 10           ; Continue for the first 5 word-sized elements
  jb   more
  mov  ax, [x + bx]     ; mov  ax, x+10
  add  x, ax            ; add  x, ax
  mov  [y + bx], ax     ; mov  y+10, ax

kqhtkvqz

kqhtkvqz2#

首先,要读/写一个内存位置,你需要使用[]。[ax]是ax处的内存位置,依此类推。对数组也有效:[x+2]表示x的第二个元素(因为它们每个都是两个字节)。
继续。你可以用一个索引或者运行指针来完成一个数组循环。让我们考虑第一种。
所以你需要运行一个从0到5的索引(i)。对于每个值,你需要给y[i]赋值x[1] + x[i+1]的值,除了最后一个。你需要一个条件来处理最后一个。
在Intel中,有两个寄存器专门设计为索引-SIDI。你可以用它们来寻址数组-像[array+SI*2]这样的结构。
为了执行循环,你需要一个条件跳转:如果索引小于数组大小,再次执行循环。
所以,在伪代码中,故意使用变量名而不是寄存器:

i=0
Loop:
copy x[i] into y[i] (more than one command in assembly)
if i = array_size-1 then add x[0] to y[i] (conditional jump here)
else add x[i+1] to y[i]

increment i
if i = array_size then jump to loop

字符串

相关问题