2012-03-14 32 views
2

私はAckermann関数をプログラムする必要があります。これは私がこれまで持っているものです:アセンブリx86:Ackermann関数をプログラムする必要があります

私はNまたはMの値を入れて、私はいつも私がなぜ知っていると思うの答えは0を得るものは何でも
.model small 
; 
    extrn putstrng:far 
    extrn newline:far 
    extrn getdec$:far 
    extrn putdec$:far 
; 
; 
    .stack 1024     
; 
    .const 


    .data 

    .code 
    assume ds:dgroup 
; 
debut: mov  ax, seg dgroup  
    mov  ds, ax 
    mov  es, ax 
; 

    mov  ax,2 ; value of N 
    mov  bx,ax 
    mov  ax,2 ; Value of M 
    mov  dx,ax 
    mov  cx,0 

    push dx 
    push bx 

    call ackermann 

    pop  bx 
    pop  dx 

    MOV ax, 0 
    MOV ax, cx 
call putdec$ 
call newline 


    mov  ax, 4c00h   
    int  21h 

ackermann proc far C uses cx 

    mov dx, [bp+6] 
    mov bx, [bp+4] 
    cmp bx, 0 
    JE firstCase 
    cmp dx, 0 
    JE secondCase 
    dec dx 
    push dx 
    push bx 
    CALL ackermann 
    pop bx 
    pop dx 
    dec bx 
    push dx 
    push bx 
    CALL ackermann 
    pop bx 
    pop dx 
    ret 


firstCase: 
    MOV cx, dx 
    inc cx 
    ret 


secondCase: 
    DEC bx 
    push dx 
    push bx 
    call ackermann 
    pop bx 
    pop dx 
    ret 

ackermann endp 

    end  debut 

。この部分:

MOV ax, 0 
MOV ax, cx 
call putdec$ 
call newline 

おそらく間違っていますが、私はそれをどうすればいいのかわかりません。

ご協力いただきますようお願い申し上げます。

ありがとうございました。あなたのアッカーマン関数は、実際にを動作し、cxレジスタにその結果を残し、そしてputdec$axレジスタの値を出力し、あなたが示してきたそのコードセグメントと間違って何も絶対にありませんことをすると仮定すると

答えて

4

最初にaxにゼロを読み込んだ後、cxに置き換えます。

したがって、あなたの問題は、のいずれかである:

  • putdec$axを印刷しません。
  • あなたのAckermann機能が期待通りに機能しません。
  • あなたのAckermann関数は、その値をcxに返しません。

拳のステップは、あなたのデバッガを起動し、mov ax, 0命令にブレークポイントを設定することです - これはアッカーマン関数が動作しているかどうかを確認するために値がcx(および他のレジスタ)であるものを教えてくれます。

次に、いくつかの紙と鉛筆を使用して、各段階で何が起こるかを比較して、関数を一歩前に戻す必要があるかもしれません。

一つのこと、私はよく分からない:静的コード解析のビット、およびこのアッカーマン関数は、実際に:-)を行うことを意味しているものへの迅速な調査を


は、私は次のことを見分けることができますあなたは権利を持っています(もしAckermann関数のWikipedia定義を使用しているのなら、 here)が第2のケースです。予想通り

 /n + 1    if m = 0 
A(m,n) = | A(m-1,1)   if m > 0 and n = 0 
     \ A(m-1,A(m,n-1)) if m > 0 and n > 0 

あなたの第二ケースコードがbx/mをデクリメントではなく、1に設定するよりも、一人でdx/n葉:それはと述べています。あなたの第三の場合

(私は密接に見ていないが)あなたは二回関数を呼び出しますが、nowehere、私はプッシュレジスタの一つのいずれかに、cxの転送、まず、インナーA()呼び出しの結果を見ることができます外側の呼び出しのためのスタックに。これは、A(x,A(y,z))のような入れ子関数を計算する上で不可欠なステップです。

代わりに、オリジナルの値のバリエーションを使用しているようです。

これらの2つの有用なポインタは、デバッグのスキルを磨いてより良い開発者になるための良いスタートになるはずです:-)

関連する問題