2013-05-04 117 views
0

我在NASM中編寫一個計算斐波那契序列並打印它的程序。它需要用戶輸入兩個種子值和迭代次數,將它們存儲在堆棧中,然後調用'fib'子例程來進行計算和打印。我正在使用一個來自here的庫來執行諸如讀取輸入/打印等事情。堆棧在NASM中的問題

這裏是我的asm_main:

asm_main: 
     enter 0,0     ; setup routine 
     pusha 

    mov eax, prompt1  ; access first prompt 
    call print_string  ; print prompt 
    call read_int  ; read input and stores in eax 
    push eax   ; store input on stack 

    mov eax, prompt2  ; access second prompt 
    call print_string  ; print prompt 
    call read_int  ; read input and stores in eax 
    push eax   ; store input on stack 

    mov eax, prompt3  ; access third prompt 
    call print_string  ; print prompt 
    call read_int  ; read input and stores in eax 
    push eax   ; store input on stack 

    call fib   ; call fib subroutine to calculate sequence 
    call print_nl  ; end with a newline 

這裏是FIB子程序:

fib: 
    pop ecx   ; retrieve number of iterations from stack 
    pop ebx   ; retrieve second seed value from stack 
    pop eax   ; retrieve first seed value from stack 

    _looper:   ; section to be looped 
     mov edx, eax 
     add edx, ebx ; sum = a + b 
     call print_int 
     call print_nl 
     mov eax, ebx ; a = b 
     mov ebx, edx ; b = sum 
     loop _looper 
    ret 

然而,這pushing和popping不能正常工作,我想不通爲什麼。當我輸入「3」作爲所述第一種子值,「5」作爲第二種子值,以及「7」的迭代次數,這裏是稱爲FIB內的寄存器轉儲的結果:

Register Dump # 1 
EAX = 00000005 EBX = 00000007 ECX = 080484D4 EDX = BF97A1B4 
ESI = 00000000 EDI = 00000000 EBP = BF97A168 ESP = BF97A144 
EIP = 08048480 FLAGS = 200282  SF 

我在這裏錯過了什麼嗎?根據我的理解,堆棧應該是後進/先出,並且我無法弄清楚發生了什麼問題。謝謝

回答

1

當你call fib然後裏面fib你會彈出堆棧的第一件事是返回地址。彈出關閉是好的,只要確保在彈出參數後重新打開它,否則ret指令最後會將您發送到您不想要的地方。

你可能例如做

fib: 
    pop edx   ; pop return address 
    pop ecx   ; retrieve number of iterations from stack 
    pop ebx   ; retrieve second seed value from stack 
    pop eax   ; retrieve first seed value from stack 
    push edx  ; put return address back on stack 
    ... 

但更傳統的方法是建立與

push ebp 
    mov ebp, esp 

堆棧幀然後用

mov ecx, [ebp+8] 
    mov ebx, [ebp+12] 

等訪問這些參數在

,然後彈出堆棧幀的參數在最後:

mov esp, ebp 
    pop ebp 
    ret 12 

後一種方法可以讓你在需要時訪問這些參數 - 不只是在進入程序。