如何编写一个在上次迭代中有所不同的循环?

时间:2019-02-20 16:21:05

标签: loops assembly x86

给定程序的输出应为1--2--3--3--4--5--6--7--8。 但是,我一直给我1--2--3--4--4--5--6--7-8--。我需要在8点后摆脱“-”,但我不知道怎么做。有人可以帮我吗?

INCLUDE Irvine32.inc 
.data

arrayb byte 1,2,3,4,5,6,7,8
space byte "--",0

.code
main PROC
    mov eax,0
    mov edx,offset space
    mov esi,offset arrayb

    mov ecx, 8      

    printb:

         mov al, [esi]
         call writedec
         call writestring
         inc esi
         mov eax, 8

    loop printb

exit
main ENDP

end main

1 个答案:

答案 0 :(得分:4)

您的代码(特别是循环)当前执行以下操作:

<init state>
counter = 8
printb:
  output number
  output "--"
  loop to printb
<exit>

如果在头上穿过它,很明显为什么在最后一个数字后会显示“-”。

调整代码的方式有很多,在现实世界中,进行格式化的代码时,我经常使用某种join函数,该函数采用列表和分隔符,并产生格式化的字符串,或者手动进行格式化,我可能会在循环之前对输出“ 1”进行硬编码,将状态初始化为好像从“ 2”开始一样开始循环,并在循环中首先输出“-”,即:

<init state>
output number
advance state as if it was printed inside loop
counter = 8-1   ; one value is already out
printb:
  output "--"   ; the loop body starts with "--" output
  output number
  loop to printb
<exit>

即在您的代码中(通过一些修改“改善”了一些我不喜欢的东西:

...
mov   edx,offset space
mov   esi,offset arrayb
movzx eax, BYTE PTR [esi]
inc   esi
call  writedec
mov   ecx, 8-1

printb:
    call  writestring
    movzx eax, BYTE PTR [esi]
    inc   esi
    call  writedec
loop printb
exit
...

编辑

彼得·科德斯(Peter Cordes)通过注释使最后一个项目变成特殊情况的想法可能会在通用情况下导致更好的代码,在通用情况下,项目的数量是可变的(固定为“ 8”,您可以显示第一个元素,然后再显示7个元素)被循环)。

让我们想象一下汇编中的这种功能,在寄存器中接受参数:

; esi = byte array to output
; ecx = amount of bytes
; will modify eax, ecx, edx, esi
OutputByteArray PROC
    jecxz   NoItemsToOutput     ; if ecx=0
    dec     ecx
    jz      OutputLastItem      ; if ecx=1, display only last item
    ; 1 < count, so "0 < ecx" here (ecx = count-1) => do the loop
    mov     edx,offset space
printb:     ; output number and "--" "count-1" times
        movzx eax, BYTE PTR [esi]
        inc   esi
        call  writedec
        call  writestring
    loop    printb
OutputLastItem:
    movzx   eax, BYTE PTR [esi]
    call    writedec
NoItemsToOutput:
    ret
ENDP