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