Recursion HLA汇编递归斐波那契程序
我已经编写了一些代码来解决此提示: 创建提示用户输入数字的HLA汇编语言程序。创建并调用计算斐波那契序列中的值的函数。在数学中,斐波那契数列是以意大利比萨数学家莱昂纳多的名字命名的。莱昂纳多生前被称为斐波那契。斐波那契序列从1和1开始。序列中后面的每一项都是前两个值的总和。所以这个系列是:1,1,2,3,5,8,13等等。为了获得全额积分,您必须使用递归来解决此问题,构建一个签名为: 程序fibRec(值:int8)@节点显示@无框架; 以下是一些示例程序对话,以指导您的工作: 提供一个数字:3 fib(3)=2 提供一封信:5 fib(5)=5 为了帮助您专注于构建汇编程序,我想为您提供以下与上述程序规范相匹配的C语句。如果愿意,可以将它们用作构建汇编程序的基础Recursion HLA汇编递归斐波那契程序,recursion,assembly,intel,hla,Recursion,Assembly,Intel,Hla,我已经编写了一些代码来解决此提示: 创建提示用户输入数字的HLA汇编语言程序。创建并调用计算斐波那契序列中的值的函数。在数学中,斐波那契数列是以意大利比萨数学家莱昂纳多的名字命名的。莱昂纳多生前被称为斐波那契。斐波那契序列从1和1开始。序列中后面的每一项都是前两个值的总和。所以这个系列是:1,1,2,3,5,8,13等等。为了获得全额积分,您必须使用递归来解决此问题,构建一个签名为: 程序fibRec(值:int8)@节点显示@无框架; 以下是一些示例程序对话,以指导您的工作: 提供一个数字:3
SAMPLE C CODE:
------------------------
int main( )
{
int value;
printf( "Provide a value: " );
scanf( "%d", &value );
int f = fibRec( value );
printf( "fib( %d ) = %d\n", value, f );
return( 0 );
}
int fibRec( int value )
{
int result = 1;
if (value == 1 || value == 2) // base case
result = 1;
else
result = fibRec( value-1 ) + fibRec( value-2 );
return( result );
}
我的方法是尝试使用C实现并将其转换为HLA。
当我运行程序时,我得到一个无限循环(cmd崩溃),可能是因为我使用递归的方式。我不知道如何实施这个计划
否则
结果=fibRec(值-1)+fibRec(值-2)
C实现的一部分
以下是我所拥有的:
program fib;
#include("stdlib.hhf");
static
value : int8;
//returnAddress : dword;
//temp: int16;
procedure fibRec( value : int8 ); @nodisplay; @noframe;
begin fibRec;
mov(CL, value);
mov(1, DL);
cmp(CL, 1);
je Res1;
cmp(CL, 2);
je Res1;
jmp Else1;
//else result = fibRec( value-1 ) + fibRec( value-2 );
Else1:
//mov(1, DL);
dec(CL);
call fibRec;
sub(2, CL);
call fibRec;
add(CL, DL);
jmp ProgExit;
Res1:
mov(1, DL);
jmp ProgExit;
ProgExit:
end fibRec;
/////////////////////////////////////////////////////////////////////////////////////////////////////
begin fib;
stdout.put( "Provide a value: " );
stdin.get(value); //CHANGED TO IVALUE
mov(CL, value); //SAVES THE INPUT TO A REGISTER
call fibRec; // MUST CALL THE PROCEDURE
stdout.put("fib(");
stdout.puti8(value);
stdout.put(") = ");
stdout.put(DL);
end fib;
了解如何调试代码,如果您尝试跳过它,会出现明显的问题,例如在开始时,您在
CL
中用值覆盖用户输入
然后在过程中指定参数“value”,但改为使用CL
,覆盖value
的内容(不确定它在HLA、堆栈变量或内存中是什么?)
您使用CL/DL 8位寄存器作为值,但C示例使用int
(32b带符号)
您使用“@noframe”:
@NOFRAME选项告诉HLA,您不希望编译器自动为过程生成入口和出口代码。这告诉HLA不要自动生成RET指令(以及其他几个指令)
但是,在过程的末尾没有“ret();”,因此在过程结束后,将继续执行一些随机代码
最后是关于递归问题
ASM不是C,当您调用子程序时,寄存器始终处于“活动”状态,只有一组寄存器
所以这是完全错误的:
dec(CL);
call fibRec;
sub(2, CL);
call fibRec;
add(CL, DL);
第一次调用后,您的CL
和DL
已被覆盖。
保存寄存器值的最简单和最直接的方法是使用堆栈,即在调用之前推送ecx,edx,然后从堆栈中还原它们
例如,小谎。用x86 32b汇编程序编写的子例程(NASM Intel语法!因此它是mov目的地,源代码,与HLA不同的方式!):
是的,现在你只需要修改HLA的语法。。。(更像是重写它,这样您就可以确保了解它是如何工作的)
学习如何调试代码,我想我忘了提到这一点
我也说过你应该调试你的代码吗
我确实调试了这个我的,所以我100%确定它能按预期工作(对于小的“n”,比如几百/几千,不确定linux elf32二进制文件的默认堆栈有多大,并且我不打算尝试它何时会在堆栈溢出时崩溃)。听起来像一个sch赋值。有关x86的递归Fib(n),请参阅。(这是一个关于玩具asm的答案的一部分,但我使用了两个宏和x86语言的公共子集来编写一个递归Fib(n),它对这两种语言都适用。)无论如何,这对其他人没有用处,研究不足,而且充满了大量不相关的文本。这篇文章的前半部分可能是“我有一项任务要在HLA中实现斐波那契(n)”。“HLA最初被认为是一种教授汇编语言编程的工具。”-所以,是的,在ASM中添加类似C的东西,使其“更容易”。。。我不同意这种做法。尤其是那些对C一无所知(1-2学期)的学生。
fibRecursion:
; expects unsigned "n" (1+) in eax, returns fibonacci(n) in eax
; will crash on large "n" due to stack overflow
cmp eax,2
ja moreThanTwo
mov eax,1 ; n: 0, 1 and 2 returns "1"
ret
moreThanTwo:
push edx ; preserve edx
dec eax
push eax ; store n-1 in stack
call fibRecursion ; eax = fib(n-1)
xchg eax,[esp] ; store fib(n-1) in stack, get n-1 into eax
dec eax
call fibRecursion ; eax = fib(n-2)
pop edx ; edx = fib(n-1)
add eax,edx ; eax = fib(n) = eax+edx
pop edx ; restore edx
ret