2013-10-17 72 views
0

繼續在我學習NASM Assembly,32位Ubuntu中的遞歸的方式中,我現在試圖遞歸地添加數組中的所有元素。數組的元素都是4個字節。在NASM Assembly中遞歸地添加數組中的所有元素

我想出了一個似乎可行的解決方案。

基本上,要添加一個數組中的元素,我莫名其妙地需要他們吧?所以我有ESI作爲我的櫃檯。然而,這個寄存器需要在函數的開始處設置爲0 - 但我不認爲有任何方法可以判斷當前的函數調用是第一個還是第二個或第三個...因此修復此問題,我有兩個功能:初始呼叫遞歸呼叫。第一個設置ESI0,然後調用遞歸調用。這些元素都加入到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 

回答

2

首先,你的size定義是錯誤的,用自己的方式給你的陣列的總字節數;這不是你想要的。你的陣列由DWORDS的,你想知道總的元素,所以我們通過圖4(a 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 
+0

所以基本上總是會有一個初始呼叫,並且還將有總是成爲櫃檯?順便說一下'fmtint'是什麼? – Voldemort

+0

初次通話?嗯,當然!如果不訴諸巫術,你會如何「進入」這個功能? 'fmtint'是我用於'printf'打印返回值的格式說明符'fmtint \t db \t「%d」,0'一個計數器?是的,你需要知道何時停止遞歸調用 - 一個計數器,布爾值,不管。 – Gunner

+0

不錯,謝謝。雖然我認爲「大小」常數是好的,因爲無論如何我每次都用「4」來增加它。雖然很好,但它使事情變得更簡單。 – Voldemort