首页 > 解决方案 > 如何编写一个在最后一次迭代中执行不同操作的循环?

问题描述

给定程序的输出应该是 1--2--3--4--5--6--7--8。但是,我的一直给我1--2--3--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

标签: loopsassemblyx86

解决方案


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

<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

推荐阅读