在NASM Assembly中递归添加数组中的所有元素

时间:2013-10-17 00:51:41

标签: arrays algorithm assembly recursion nasm

仍在我学习32位Ubuntu的NASM程序集中的递归,我现在试图以递归方式添加数组中的所有元素。数组的元素都是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

1 个答案:

答案 0 :(得分:2)

首先,您对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