题目要求如下:输入多个参数,每个参数间以空格隔开,最后以回车结束输入,要求输出指定参数位置的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 89 org 100h section .text start: mov byte[buffer], 0 ; 初始化buffer为0 mov byte[num_count], 0 ; 初始化输入数据个数为0 mov byte[color], 07h ; 初始化颜色 jmp input input: mov ah, 07h ; 读入字符(包括控制字符) int 21h mov dl, al ; 回显读入字符 mov ah, 2h int 21h cmp al, 0dh ; 若读入回车则结束输入 je analysis cmp al, 20h ; 判断输入字符是否为空格 je push_data ; 是空格则压入数据 sub al, 30h mov byte[digit], al mov al, byte[buffer] mov bl, 10 mul bl add al, byte[digit] mov byte[buffer], al ; buffer = buffer*10 + digit jmp input push_data: add byte[num_count], 1 ; 统计输入数据个数 mov ah, 0 mov al, byte[buffer] push ax ; 数据压栈,此处数据需要是16位 mov byte[buffer], 0 ; buffer清零 jmp input ; 继续输入 analysis: add byte[num_count], 1 ; 统计输入数据个数 mov ah, 0 mov al, byte[buffer] push ax ; 数据压栈,此处数据需要是16位 mov dl, 0ah ; 换行 mov ah, 02h int 21h mov dl, 0dh ; 回车 mov ah, 02h int 21h ; 读取光标位置 mov ah, 03h mov bh, 0 int 10h mov byte[row], dh sub byte[row], 1 ; 设置输出行的起始位置 add dh, byte[num_count] mov byte[final_row], dh sub byte[final_row], 1 ; 设置最后的光标位置 calculate: pop dx fibonacci: mov byte[digit_count], 0 ; 数字位数初始化为0 ; 初始化a1,a2以及最终结果a3为1 mov cx, 15 set: mov bx, num1 add bx, cx sub bx, 1 mov byte[bx],0 mov bx, num2 add bx, cx sub bx, 1 mov byte[bx], 0 mov bx, num3 add bx, cx sub bx, 1 mov byte[bx],0 Loop set mov byte[num1+15], 1 mov byte[num2+15], 1 mov byte[num3+15], 1 cmp dx, 1 ; 输入1 je output cmp dx, 2 ; 输入2 je output sub dx, 2 ; 输入数大于等于3 mov byte[num3+15], 0 ; 若输入大于等于3,将最终结果初始化为0 mov cx, dx ; 初始化计算Fibonacci循环次数 adding: push cx mov byte[cf], 0 ; 初始化进位为0 mov cx, 16 next: ; 计算an=an-1+an-2 mov bx, num1 add bx, cx sub bx, 1 mov al, byte[bx] mov bx, num2 add bx, cx sub bx, 1 add al, byte[bx] mov bx, num3 add bx, cx sub bx, 1 add al, byte[cf] mov byte[bx], al mov byte[cf], 0 ; 进位加完后归0 cmp byte[bx], 100 ; 每个单元存放的值最多为99,使用十进制的思想 jb end sub byte[bx], 100 mov byte[cf], 1 ; 若大于等于100,则进位 end: Loop next mov cx, 16 copy: mov bx, num2 add bx, cx sub bx, 1 mov al, byte[bx] mov bx, num1 add bx, cx sub bx, 1 mov byte[bx], al ; 将an-1赋值给an-2 mov bx, num3 add bx, cx sub bx, 1 mov al, byte[bx] mov bx, num2 add bx, cx sub bx, 1 mov byte[bx], al ; 将an赋值给an-1 Loop copy pop cx Loop adding output: mov cx, 16 divide: mov bx, num3 add bx, cx sub bx, 1 mov al, byte[bx] mov ah, 0 mov dl, 10 div dl movzx dx, ah push dx mov ah, 0 mov dl, 10 div dl movzx dx, ah push dx Loop divide ; 设置光标位置 mov ah, 02h mov bh, 0 mov dh, byte[row] add dh, byte[num_count] ; 当前光标位置 = 起始位置+第x个数据 mov dl, 0 int 10h mov cx, 32 ; 32=2*16,每个单元最多存两位(99),共16个单元 add byte[color], 1 mov byte[flag_nz], 0 ; 用于标记遇到第一个非零的数字 print: mov word[loop_time], cx ; 保存循环次数 ; 设置颜色 mov ah, 09h mov bh, 0 mov bl, byte[color] mov cx, 1 int 10h pop dx cmp byte[flag_nz], 1 je not_zero ; 遇到非零数后便正常输出剩下所有数字 cmp dx, 0 je zero ; 若一直未遇到非零数便跳过输出 mov byte[flag_nz], 1 ; 遇到非零数改变标志 not_zero: add dx, 30h mov ah, 2h int 21h zero: mov cx, word[loop_time] ; 恢复循环次数 Loop print sub byte[num_count], 1 ; 总数字个数减一 cmp byte[num_count], 0 jne calculate exit: ; 设置最后的光标位置 mov ah, 02h mov bh, 0 mov dh, byte[final_row] int 10h mov ax, 4c00h int 21h section .bss num1 resb 16 ; an-2项 num2 resb 16 ; an-1项 num3 resb 16 ; an项 cf resb 1 ; 进位 flag_nz resb 1 ; 非零标志位 buffer resb 1 ; 之前读入数字的值 digit resb 1 ; 读入的一位数字 num_count resb 1 ; 输入数据的总个数 digit_count resb 1 ; 每个数据的位数 color resb 1 ; 颜色 row resb 1 ; 起始行数 final_row resb 1 ; 最终行数 loop_time resw 1 ; 用于保存循环次数