装配新手,试图让循环工作[重复]

问题描述 投票:0回答:1

我刚刚开始使用 Assembly (NASM),我尝试创建一个变体来解决 Project Euler 问题 1(将 1000 以下的 3 或 5 的所有倍数相加)。我尝试制定算法的变体利用了倍数以重复模式间隔的事实(+3、+2、+1、+3、+1、+2、+3 和重复),但是循环在第一次迭代后退出。

原理应该和这个C解一样,计算出正确的结果:

int sum = 0, s = 0;
int steps[7] = {3,2,1,3,1,2,3};

for (int n = steps[s]; n < 1000; n += steps[s]) {
    sum += n;
    s++;

    if (s == 7)
        s = 0;
}

我的汇编看起来像这样:

section .data
    msg db "%d", 10, 0              ;return string for printf (just the result)
    steps dd 3, 2, 1, 3, 1, 2, 3    ;how the multiples of 3 and 5 are spaced

section .text
extern printf
global main

main:
    xor     rax, rax        ;prepare rax which will store the result
    xor     rbx, rbx        ;prepare rbx, which will be the current number

arr0:
    xor     rcx, rcx        ;prepare rcx, which will be the array index

countup:
    add     rbx, [steps + rcx * 4]  ;add steps@rcx to rbx
    add     rax, rbx                ;add rbx to the result
    inc     rcx                     ;increase the array index
    cmp     rcx, 7                  ;check if we reached the end of the array
    je      arr0                    ;if yes, jump to arr0
    cmp     rbx, 1000               ;check if we reached 1000
    jl      countup                 ;if not, loop again

... print and exit come next

程序编译得很好,但结果只有 3,所以显然循环不会重复,只执行一次。为了使其正常工作,我需要改变什么?

如果我手动创建如下所示的重复模式,它工作正常,显然直到我到达数组的末尾。

    add     rbx, [steps + rcx * 4]  ;add steps@rcx to rbx
    add     rax, rbx                ;add rbx to the result
    inc     rcx                     ;increase the array index
    add     rbx, [steps + rcx * 4]  ;add steps@rcx to rbx
    add     rax, rbx                ;add rbx to the result
    inc     rcx                     ;increase the array index
    add     rbx, [steps + rcx * 4]  ;add steps@rcx to rbx
    add     rax, rbx                ;add rbx to the result
    inc     rcx                     ;increase the array index
...
assembly nasm
1个回答
0
投票

感谢您的评论,我能够解决问题。正如 Erik 所指出的,主要问题是 32/64 位混合。一旦我将所有内容更改为仅使用 eXX 寄存器,或者将数组的数据类型调整为 dq 并将索引的乘数调整为 8,它就完美地工作了。

ecm 当然也是对的,所以我稍微调整了检查和结构:

section .data
    msg db "%d", 10, 0              ;return string for printf (just the result)
    steps dd 3, 2, 1, 3, 1, 2, 3    ;how the multiples of 3 and 5 are spaced

section .text
extern printf
global main

main:
    xor     eax, eax        ;result
    xor     ebx, ebx        ;current number
    xor     ecx, ecx        ;array index

arr0:
    cmp     ecx, 7          ;check if we reached the end of the array
    jl      countup         ;if not, continue counting
    xor     ecx, ecx        ;else reset counter

countup:
    add     eax, ebx                ;add current number to result
    add     ebx, [steps + ecx * 4]  ;add steps@ecx to current number
    inc     ecx                     ;increase the array index 
    cmp     ebx, 1000               ;check if we reached 1000
    jl      arr0                    ;if not, continue
© www.soinside.com 2019 - 2024. All rights reserved.