2013-10-17 2 views
0

여전히 NASM 어셈블리 인 32 비트 우분투에서 재귀를 배우려고합니다. 이제 배열의 모든 요소를 ​​재귀 적으로 추가하려고합니다. 배열 요소는 모두 각각 4 바이트입니다.NASM 어셈블리의 배열에있는 모든 요소를 ​​반복적으로 추가합니다.

나는 작동하는 해결책을 생각해 냈습니다.

기본적으로 배열에 요소를 추가하려면 어떻게 든 으로 계산해야합니다. 맞습니까? 그래서 내 카운터로 ESI 있습니다. 그러나이 레지스터는 함수 시작 부분에 0으로 설정해야합니다. 그러나 현재 함수 호출이 첫 번째 호출인지 또는 두 번째 또는 세 번째 호출인지 여부를 알 수있는 방법이 없다고 생각합니다. 이 문제를 해결하려면 초기 호출재귀 호출의 두 가지 기능이 있습니다. 첫 번째는 ESI에서 0으로 설정 한 다음 재귀 호출을 호출합니다. 요소는 모든

.. 또한 초기 호출에 0로 설정 EAX에 추가됩니다하지만 약간이 재귀 함수에서 다른 내가 한 일이기 때문에 나는 그것으로 걱정하기 전에 :

, 때문에 무엇보다도 먼저, 나는 두 가지 기능, 시작 하나, 실제 재귀 부분에 대한 또 다른를 사용하고 있습니다. 또한, 반복적 인 솔루션과 매우 흡사 한 카운터를 사용하고 있습니다.

제 질문은 : 제가 위에 게시 한 두 가지 재귀 함수와 유사한 솔루션이 있습니까? 현재 솔루션을 재귀 적으로 간주 할 수 있습니까?

; -------------------------------------------------------------------------- 
; 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의 당신의 정의가 잘못, 당신은 배열의 총 바이트 수를 줄 것이다 당신의 방법; 이것은 당신이 원하는 것이 아닙니다. 귀하의 배열이 DWORD에 구성되어, 당신은 총 요소를 알고 싶은, 그래서 우리는 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

관련 문제