0

32 ビット Ubuntu の NASM アセンブリで再帰を学ぶ途中ですが、配列内のすべての要素を再帰的に追加しようとしています。配列の要素はすべて 4 バイトです。

うまくいきそうな解決策を思いついた。

基本的に、配列に要素を追加するには、何らかの方法でそれらをカウントする必要がありますよね? だから私はESI私のカウンターとして持っています。ただし、このレジスタは関数の先頭に設定する必要が0あります-しかし、現在の関数呼び出しが最初のものなのか、2番目または3番目のものなのかを知る方法はないと思います...修正するにはこれには、初期呼び出し再帰呼び出しの 2 つの関数があります。最初のものは再帰呼び出しを設定ESIしてから呼び出します。0要素はすべて に追加され、最初の呼び出しでEAXも に設定されます。0

しかし、私が以前に行った2つの再帰関数とは多少異なるため、私はそれを心配しています:

まず第一に、2 つの関数を使用しています。1 つは開始用で、もう 1 つは実際の再帰部分用です。また、私はカウンターを使用していますが、これは非常に反復的なソリューションのように感じます。

私の質問は次のとおりです。上に投稿した2つの再帰関数に似た解決策はありますか? 現在のソリューションは再帰的と見なすことができますか?

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

1 に答える 1

2

まず、あなたの定義sizeが間違っています。あなたの方法で配列の合計バイト数が得られます。これはあなたが望むものではありません。配列は DWORDS で構成されています。合計要素を知りたいので、4 (DWORD のサイズ) で割ります。

size:   equ ($-array) / 4

これを行う 2 つの方法は、配列の末尾または先頭から開始します。

最後から:

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
于 2013-10-17T02:08:51.577 に答える