简体   繁体   中英

Recursively adding all the elements in an array in NASM Assembly

Still on my way to learn recursion in NASM Assembly, 32-bit Ubuntu, I am now trying to add all the elements in an array recursively. The array's elements are all 4-bytes each.

I came up with a solution that seems to work.

Basically, to add the elements in an array, I somehow need to count them, right? So I have ESI as my counter. However, this register needs to be set to 0 at the beginning of the function - but I don't think there is any way I can tell whether the current function call is the first one, or the second or third... So to fix this, I have two functions: the initial call , and the recursive call . The first one sets ESI to 0 and then calls the recursive call. The elements are all added to EAX , which is also set to 0 in the initial call..

But I'm concerned with it because it is somewhat different from two recursive functions I've done before:

Because, first of all, I'm using two functions, one for the start, and another for the actual recursive part. Also, I am using a counter, which feels awfully a lot like an iterative solution.

So my questions are: is there a solution that resembles better the two recursive functions I posted above? Can my current solution be considered recursive?

; --------------------------------------------------------------------------
; 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

First, your definition of size is wrong, your way will give you the total bytes of the array; this is not what you want. Your array is made of DWORDS, you want to know the total elements, so we divide by 4 (The size of a DWORD):

size:   equ ($-array) / 4

Two ways of doing this, start from the end of the array or the beginning:

From end:

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

From start:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM