我需要编程Ackermann功能。这就是我到目前为止所做的:
.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
无论我为N或M的价值做什么,我总能得到答案0.我想我知道为什么。这部分:
MOV ax, 0
MOV ax, cx
call putdec$
call newline
可能是错的,但我不知道如何处理它。
非常感谢任何帮助。
感谢。
答案 0 :(得分:5)
假设您的Ackermann函数实际正常工作并将其结果保留在cx
寄存器中,并且putdec$
打印ax
寄存器中的值,那么你所展示的代码段绝对没有错。
首先将{0}首先加载到ax
,然后将其替换为cx
。
因此,你的问题在于:
putdec$
无法打印ax
。cx
中返回其值。 Fist步骤是启动调试器并在mov ax, 0
指令处设置断点 - 这将告诉您cx
(以及其他寄存器)中的值,以检查Ackermann功能是否正常工作
然后你可能需要返回并单步执行该功能,将它与你期望在每个阶段用纸和铅笔进行比较。
通过一些静态代码分析,以及对Ackermann函数实际意图做什么的快速调查:-),我可以看出以下内容:
我不确定你有没有一件事(如果你使用维基百科定义的Ackermann函数here)是第二种情况。它声明:
/ 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
但仅留下dx/n
,而不是将其设置为一个。
在你的第三种情况下(虽然我没有仔细查看过)你确实两次调用该函数但是现在我可以看到cx
的转移,即第一次内部A()
调用的结果,将任何一个寄存器压入堆栈以进行外部调用。这是计算A(x,A(y,z))
等嵌套函数的重要步骤。
相反,您的外部调用似乎使用原始值的某些变体。
这两个有用的指针应该是一个良好的开端,磨练你的调试技巧并成为一个更好的开发人员: - )