nasm汇编语言小程序:计算多个指定位置的Fibonacci值

来源:互联网 发布:Python For Finance 编辑:程序博客网 时间:2024/04/30 19:19

题目要求如下:输入多个参数,每个参数间以空格隔开,最后以回车结束输入,要求输出指定参数位置的Fibonacci值

我的编程环境:Ubuntu 14.04 64位系统 + DOSBox + NASM + gedit

首先,考虑输入问题,我采取的是逐个读入字符的方式,读到空格则代表上一个数据输入完毕,读入回车则代表所有数据输入完毕:

    1)利用buffer存取每一个数据,将buffer初始化为0,每读入一个数字后buffer = buffer*10 + digit,其中digit为刚刚读入数字的值(由于读入是字符,所以digit要减30h)

    2)读入空格后,将buffer压栈,然后将buffer清零,继续执行输入,直到输入回车

之后,处理完所有数据的输入后,将数据出栈,根据出栈顺序计算当前数据对应的Fibonacci值,计算完后跳转到输出,输出完后再跳转回下一个数据的计算

    1)利用循环计算Fibonacci值,循环次数即为出栈的数据值

    2)单独处理出栈数据为1和2的情况

此处有一问题:出栈数据顺序与输入数据顺序相反,而计算顺序是根据出栈顺序决定的,而且我是在计算完后进行输出,于是输出顺序与输入顺序相反,此处我采用了控制光标(int 10h中的2h)的方法用以控制输出数据的行的位置,实际上计算顺序的确是反的,但显示上是正确的顺序


大数的计算:申请多个内存单元,每个单元存至多99,超过99便进位同时将该单元的值减100


;1 1 2 3 5 8 13 21 34 55 89org100hsection .textstart:movbyte[buffer], 0; 初始化buffer为0movbyte[num_count], 0; 初始化输入数据个数为0movbyte[color], 07h; 初始化颜色jmpinputinput:movah, 07h; 读入字符(包括控制字符)int21hmovdl, al; 回显读入字符movah, 2hint21hcmpal, 0dh; 若读入回车则结束输入jeanalysiscmpal, 20h; 判断输入字符是否为空格je      push_data; 是空格则压入数据subal, 30hmovbyte[digit], almoval, byte[buffer]movbl, 10mulbladdal, byte[digit]movbyte[buffer], al; buffer = buffer*10 + digitjmp inputpush_data:addbyte[num_count], 1; 统计输入数据个数movah, 0moval, byte[buffer]pushax; 数据压栈,此处数据需要是16位movbyte[buffer], 0; buffer清零jmpinput; 继续输入analysis:addbyte[num_count], 1; 统计输入数据个数movah, 0moval, byte[buffer]pushax; 数据压栈,此处数据需要是16位movdl, 0ah; 换行movah, 02hint21hmovdl, 0dh; 回车movah, 02hint21h; 读取光标位置movah, 03hmovbh, 0int10hmovbyte[row], dhsubbyte[row], 1; 设置输出行的起始位置adddh, byte[num_count]movbyte[final_row], dhsubbyte[final_row], 1; 设置最后的光标位置calculate:popdxfibonacci:movbyte[digit_count], 0; 数字位数初始化为0; 初始化a1,a2以及最终结果a3为1movcx, 15set:movbx, num1addbx, cxsubbx, 1movbyte[bx],0movbx, num2addbx, cxsubbx, 1movbyte[bx], 0movbx, num3addbx, cxsubbx, 1movbyte[bx],0Loop setmovbyte[num1+15], 1movbyte[num2+15], 1movbyte[num3+15], 1cmp     dx, 1; 输入1    je      output    cmpdx, 2; 输入2jeoutputsubdx, 2; 输入数大于等于3movbyte[num3+15], 0; 若输入大于等于3,将最终结果初始化为0movcx, dx; 初始化计算Fibonacci循环次数adding:pushcxmovbyte[cf], 0; 初始化进位为0movcx, 16next:; 计算an=an-1+an-2movbx, num1addbx, cxsubbx, 1moval,byte[bx]movbx, num2addbx, cxsubbx, 1addal,byte[bx]movbx, num3addbx, cxsubbx, 1addal, byte[cf]movbyte[bx], almovbyte[cf], 0; 进位加完后归0cmpbyte[bx], 100; 每个单元存放的值最多为99,使用十进制的思想jbendsubbyte[bx], 100movbyte[cf], 1; 若大于等于100,则进位end:Loop nextmovcx, 16copy:movbx, num2addbx, cxsubbx, 1moval,byte[bx]movbx, num1addbx, cxsubbx, 1movbyte[bx], al; 将an-1赋值给an-2movbx, num3addbx, cxsubbx, 1moval,byte[bx]movbx, num2addbx, cxsubbx, 1movbyte[bx], al; 将an赋值给an-1Loop copypopcxLoop addingoutput:movcx, 16divide:movbx, num3addbx, cxsubbx, 1moval,byte[bx]movah, 0movdl, 10divdlmovzxdx, ahpushdxmovah, 0movdl, 10divdlmovzxdx, ahpushdxLoop divide; 设置光标位置movah, 02hmovbh, 0movdh, byte[row]adddh, byte[num_count]; 当前光标位置 = 起始位置+第x个数据movdl, 0int10hmovcx, 32; 32=2*16,每个单元最多存两位(99),共16个单元addbyte[color], 1movbyte[flag_nz], 0; 用于标记遇到第一个非零的数字print:movword[loop_time], cx; 保存循环次数; 设置颜色movah, 09hmovbh, 0mov bl, byte[color]movcx, 1int 10hpopdxcmpbyte[flag_nz], 1jenot_zero; 遇到非零数后便正常输出剩下所有数字cmpdx, 0jezero; 若一直未遇到非零数便跳过输出movbyte[flag_nz], 1; 遇到非零数改变标志not_zero:adddx, 30hmovah, 2hint21hzero:movcx, word[loop_time]; 恢复循环次数Loop printsubbyte[num_count], 1; 总数字个数减一cmpbyte[num_count], 0jnecalculateexit:; 设置最后的光标位置movah, 02hmovbh, 0movdh, byte[final_row]int10hmovax, 4c00hint21hsection .bssnum1resb16; an-2项num2resb16; an-1项num3resb16; an项cfresb1; 进位flag_nzresb1; 非零标志位bufferresb1; 之前读入数字的值digitresb1; 读入的一位数字num_countresb1; 输入数据的总个数digit_countresb1; 每个数据的位数colorresb1; 颜色rowresb1; 起始行数final_rowresb1; 最终行数loop_timeresw1; 用于保存循环次数


0 0