【问题标题】:Recursively adding all the elements in an array in NASM Assembly在 NASM Assembly 中递归地添加数组中的所有元素
【发布时间】:2013-10-25 08:04:17
【问题描述】:

我仍在学习 NASM 程序集(32 位 Ubuntu)中的递归,我现在正在尝试递归地添加数组中的所有元素。数组的元素每个都是 4 字节。

我想出了一个似乎可行的解决方案。

基本上,要在数组中添加元素,我需要对它们进行计数,对吗?所以我有ESI 作为我的计数器。但是,这个寄存器需要在函数的开头设置为0——但我认为没有任何方法可以判断当前函数调用是第一个,还是第二个或第三个......所以要解决这个问题,我有两个函数:初始调用递归调用。第一个将ESI 设置为0,然后调用递归调用。元素全部添加到EAX,在初始调用中也设置为0..

但我很关心它,因为它与我之前做过的两个递归函数有些不同:

因为,首先,我使用了两个函数,一个用于开始,另一个用于实际的递归部分。另外,我正在使用一个计数器,感觉非常像一个迭代解决方案。

所以我的问题是:有没有更类似于我上面发布的两个递归函数的解决方案?我当前的解决方案可以被认为是递归的吗?

; --------------------------------------------------------------------------
; Recursive function that adds all the elements in an array into EAX.
; The array's elements are 4-bytes each.
; --------------------------------------------------------------------------

SECTION .data
    array:  dd  1,5,3,7,4,8,5,2
    size:   equ $-array

SECTION .text
    global  main
    main:

    ; ------------------------------------------------------------------
    ; * Main
    ; ------------------------------------------------------------------
    call    addVector
    breakpoint:     ; Used for GDB to inspect the result later

    ; ------------------------------------------------------------------
    ; * Exit
    ; ------------------------------------------------------------------
    mov     EAX,0
    int     0x80

    ; ------------------------------------------------------------------
    ; * Initial function call, before doing the recursive calls
    ;   Sets ESI to 0, which will be used to count the array's elements
    ;   Also sets EAX to 0, for storing the result
    ; ------------------------------------------------------------------
    addVector:
    push    ESI
    mov     ESI,0
    mov     EAX,0
    call    recursiveCall
    pop     ESI
    ret

    ; ------------------------------------------------------------------
    ; * Recursive part of the function
    ;   Adds to EAX to current element, and increases the ESI counter by
    ;   4 (because the array's elements are 4-bytes each).
    ;   If the counter happens to be >= the array's size, stop.
    ; ------------------------------------------------------------------
    recursiveCall:
    cmp     ESI,size
    jge     endRecursiveCall
    add     EAX,[array + ESI]
    add     ESI,4
    call    recursiveCall
    endRecursiveCall:
    ret

【问题讨论】:

    标签: arrays algorithm assembly recursion nasm


    【解决方案1】:

    首先,您对size 的定义是错误的,您的方式会给您数组的总字节数;这不是你想要的。您的数组由 DWORDS 组成,您想知道总元素,所以我们除以 4(DWORD 的大小):

    size:   equ ($-array) / 4
    

    有两种方法,从数组末尾或开头开始:

    从结尾:

    array:  dd  1,5,3,7,4,8,5,2
    size:   equ ($-array) / 4
    
    SECTION .text
    global  main
    main:
    
        xor     eax, eax                        ; clear out eax
        mov     esi, size - 1                   ; set our index to array end
        call    recursiveCall
    
        push    eax
        push    fmtint
        call    printf
        add     esp, 4 * 2
    
    .exit:
        call    exit
    
    recursiveCall:
        add     EAX, dword[array + 4 * ESI]
        dec     ESI
        js      .endRecursiveCall
        call    recursiveCall
    
    .endRecursiveCall:
        ret
    

    从头开始:

    SECTION .text
    global  main
    main:
    
        xor     eax, eax                        ; clear out eax
        xor     esi, esi                        ; set out index to start of array
        call    recursiveCall
    
        push    eax
        push    fmtint
        call    printf
        add     esp, 4 * 2
    
    .exit:
        call    exit
    
    recursiveCall:
        add     EAX, dword[array + 4 * ESI]
        inc     esi
        cmp     esi, size - 1
        jg      .endRecursiveCall
        call    recursiveCall
    
    .endRecursiveCall:
        ret
    

    【讨论】:

    • 所以基本上总会有一个初始调用,总会有一个计数器?顺便问一下fmtint 是什么?
    • 初次通话?嗯,当然!如果不诉诸巫术,您将如何“进入”该功能? fmtint 是我用于 printf 打印返回值的格式说明符 fmtint db "%d", 0 一个计数器?是的,您需要知道何时停止递归调用 - 计数器、布尔值等等。
    • 很好,谢谢。虽然我认为size 常量很好,因为无论如何我每次都将它增加4。不过不错,它让事情变得更简单。
    猜你喜欢
    • 2020-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-26
    • 2014-08-07
    • 2015-06-21
    相关资源
    最近更新 更多