【问题标题】:How can I find the last 0 on an array in nasm?如何在 nasm 中找到数组的最后一个 0?
【发布时间】:2019-08-17 14:03:42
【问题描述】:

我正在编写代码来查找数组中的最后一个 0。

基本上我需要在每个数组的“顶部”移动一个新值,如果它只有零,则将其放在末尾,如果找到其他值,则将其放在最后一个 0(我正在对待我的数组作为堆)。

到目前为止,我的子例程在大多数情况下都可以正常工作,但有时它会重写一个我不想要的值(而不是获取与 0 不同的第一个值,而是获取下一个值)。这是我用来获取数组“顶部”的代码。

TOP:
    xor ecx,ecx
    xor ebx,ebx
TOP_FOR:                    
    mov bx,word[eax+ecx*2]   ;eax has the pointer of the array
    cmp ecx,n                ;n is the array's length
    je END_TOP
    inc ecx
    cmp bx,0
    je TOP_FOR
                    ;here i get the direction of the first value different
END_TOP:            ;from 0 but in my code i need the last 0, so
    dec ecx         ;i decrease ecx (result of this subrutine)
    ret

例如, 如果我放置一个 0,2 的数组,我期望 ecx = 0,但使用该输入实际上得到 1。

  • 使用数组 1,2 我得到 0(这是我想要的)
  • 使用数组 0,0 我得到 1(我想要的,再次)

编辑:尝试在 n-1 上启动循环,它给了我更奇怪的结果。

TOP:
    xor ecx,ecx
    ;xor ebx,ebx
    mov ecx,n-1
TOP_FOR:
    ;mov bx,word[eax+ecx*2]
    cmp word[eax+ecx*2],0
    je FIN_TOPE
    dec ecx
    cmp ecx,0
    jne TOP_FOR

END_TOP:

    ret

【问题讨论】:

  • 您更新的代码不会运行i=0 的循环体,因此它从不查看第一个元素。这就是我在回答中使用dec ecx / jge 的原因;它仅在 ECX 变为-1 后才离开循环。另请注意,dec 设置标志,您不需要单独的 cmp 和 0。

标签: arrays assembly x86 nasm


【解决方案1】:

你的逻辑是完全倒退的。 当您找到第一个非零值时,您的 cmp/je 循环条件将退出循环。(并且您已经在加载后但在检查之前增加了 ECX)。

所以在你的循环之后,ECX = 元素的索引第一个非零元素之后。

您至少有 2 个选项:

  • 在另一个寄存器中记住最后出现的 0,并在循环结束时使用它
  • 循环向后,从 ECX = n-1 开始,并在第一个零处退出循环。 (或在 dec ecx 上产生 0。)

其中一个显然比另一个更高效、更容易。 :P

我将由您来解决非 1 问题,但您可能希望在循环底部检查 ecx < necx >= 0,例如dec ecx / jge TOP_FOR。即do{}while(--i) 循环。


此外,通常 EBX 是一个调用保留寄存器。不过,您根本不需要使用它。 cmp word [eax + ecx*2], 0 工作正常。

同样在您当前的代码中,您读取了数组末尾之后的 2 个字节。如果它位于页面的末尾,则可能会出错。 (不过,您不使用它,因此除此之外它不是正确性问题。)您使用 ECX 作为索引检查它是否太大!如果你只使用内存,这个问题就会消失,立即cmp

此外,通常指针增量更有效。在循环之后,您可以减去并右移以获得索引。

【讨论】:

    猜你喜欢
    • 2020-04-24
    • 2021-12-24
    • 2013-06-14
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多