|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 奥普瓯江 于 2018-11-19 00:24 编辑
这个破问题可是坑哭我了,弄了很久很久,如有什么不对的地方还望指点一二,如果有什么更简单高效的书写方法也请不吝指教谢谢谢谢
- assume cs:code, ds:data1, ds:data2, ds:data3
- data1 segment
- dw 123, 12666, 1, 8, 3, 38, 0
- data1 ends
- data2 segment
- db 10 dup (0)
- data2 ends
- data3 segment
- db 20 dup (0)
- data3 ends
- code segment
- start:
- mov di, 0
- mov si, 0
- one_str:
- mov ax, data1
- mov ds, ax
- mov ax, word ptr ds:[si]
- mov cx, ax
- jcxz one_end
- push si
-
- mov si, 0
- mov bx, data2
- mov ds, bx
- mov bx, data3
- mov es, bx
- call div_str
-
- pop si
- add si, 2
- jmp short one_str
- one_end:
- mov dh, 8
- mov dl, 3
- mov cl, 2
- call show_str
-
- mov ax, 4C00H
- int 21H
-
- div_str:
- mov dx, 0
- mov bx, 10
- div bx
- add dl, 30H
- mov byte ptr ds:[si], dl
- mov cx, ax
- jcxz div_end
- inc si
- jmp short div_str
- div_end:
- mov al, byte ptr ds:[si]
- mov byte ptr es:[di], al
- mov cx, si
- inc di
- jcxz chang_str
- dec si
- jmp short div_end
- chang_str:
- mov byte ptr es:[di], 20h
- inc di
- ret
-
- show_str:
- dec dh
- mov ax, 0A0H
- mul dh
- mov bx, ax
-
- mov ax, 2
- mul dl
- sub ax, 2
-
- add bx, ax
-
- mov ax, 0b800h
- mov ds, ax
- mov si, 0
- mov di, 0
- mov al, cl
- ok:
- mov cl, byte ptr es:[si]
- mov ch, 0
- jcxz good
- mov byte ptr ds:[bx + di], cl
- mov byte ptr ds:[bx + di + 1], al
- inc si
- add di, 2
- jmp short ok
- good:
- ret
-
- code ends
- end start
复制代码
以下为我按照我的理解所做的注释
- assume cs:code, ds:data1, ds:data2, ds:data3
- data1 segment
- dw 123, 12666, 1, 8, 3, 38, 0
- data1 ends
- data2 segment
- db 10 dup (0)
- data2 ends
- data3 segment
- db 20 dup (0)
- data3 ends
- code segment
- start:
- mov di, 0 ;初始化di寄存器为零
- mov si, 0 ;初始化si寄存器为零
- one_str:
- mov ax, data1 ;把data1数据段的段地址传给ax
- mov ds, ax ;把ax数据传给ds寄存器,使得数据段可以被调用
- mov ax, word ptr ds:[si] ;把data1中的两个字节的数据传给ax寄存器
- mov cx, ax ;把ax中数据传给cx已被jcxz验证
- jcxz one_end ;判断cx是否为零如果不为零不执行该条语句
- push si ;使得si寄存器的数据进入栈中暂时保存,这里要注意栈的调用只能是两个字节也就是十六位数据不能是八位数据
-
- mov si, 0 ;再次初始化si,这里可以再次调用si是因为si以进栈,在循环重复的时候si将被pop从新赋值所以不影响si的使用
- mov bx, data2 ;把data2数据段的段地址传给bx因为8086中只有ax和bx能被直接赋值,所以他俩需要交替使用,在这里ax以被使用所以就调用bx使他间接赋值给ds
- mov ds, bx ;把bx中的数据传给ds,因为这个循环是从one_str开始的所以从新付给ds数据并不冲突
- mov bx, data3 ;把data3的值付给bx
- mov es, bx ;把bx数据传给es使得可以向data3数据段中读取写入数据
- call div_str ;跳转到div_str标记处
-
- pop si ;把si的数值从栈中取回,并在此赋给si
- add si, 2 ;data1中的si加2
- jmp short one_str ;无条件跳转回one_str,该程序一共需要循环6次,因为data1中有六组word数据第七组是0
- one_end: ;上面的循环执行完毕后跳转到该处向下执行上面数据转换和排序等执行完毕后,以下的数据就是显示数据
- mov dh, 8 ;把他显示在第八行
- mov dl, 3 ;第三列这个地方
- mov cl, 2 ;显示是字体所呈现的属性,绿字
- call show_str ;跳转到字符标记处show_str:,当遇到ret这条语句就跳转回来,并继续向下执行
-
- mov ax, 4C00H ;结束语句
- int 21H ;结束语句
-
- div_str: ;16进制数转换成10进制的方法是用10除以16进制数每次的余数就是十进制数的一个元素,直到被除数为0结束
- mov dx, 0 ;初始dx寄存器数据,这里初始dx主要是为了div运算如果不初始化div运算就会报错
- mov bx, 10 ;初始bx中的数据为10
- div bx ;执行除法运算,被除数高位存放在dx中低位存放在了ax中,除数存放在了bx中,商存放在ax中余数存放在dx中
- add dl, 30H ;给余数加30h因为在ascii码中1的代码是31剩下的以此类推
- mov byte ptr ds:[si], dl ;把加30h后的余数传到data2中暂时储存
- mov cx, ax ;把被除数的数据传给cx
- jcxz div_end ;如果cx中的数据是0那么执行本条语句,跳转到div_end标记处,如果cx中的数据不是0那么什么也不做继续执行下一条语句
- inc si ;使得si自动加1
- jmp short div_str ;无条件跳转到div_str标记处,jmp与jcxz是搭配使用的jcxz是他的结束条件
- div_end: ;下列语句主要是把顺序倒了的数据调转过来并传到data3数据段
- mov al, byte ptr ds:[si] ;把data2中本次本次循环si这个字节传给al八位寄存器
- mov byte ptr es:[di], al ;al八位寄存器中的数据传给data3这个数据段偏移地址di这个位置
- mov cx, si ;把si中的数据传给cx
- inc di ;di自动加1
- jcxz chang_str ;当cx中的数据为0的时候跳转到chang_str这个标记位置,如果cx中的数据不是0就什么也不做继续执行下一条语句
- dec si ;si 自动减1
- jmp short div_end ;无条件跳转回div_end
- chang_str:
- mov byte ptr es:[di], 20h ;给米格段后面加上一个空格
- inc di ;di自动加一
- ret ;返回call div_str向下执行
-
- show_str:
- dec dh ;先让行数自动减一因为计算机是从0开始计算的,8行计算机计算的时候是从0开始的到7
- mov ax, 0A0H ;因为每一行是160个字节换算成16进制就是A0H,把被乘数赋给ax因为mul计算的时候是用ax乘一个寄存器或者内存单元
- mul dh ;乘法运算,最后乘积保存在ax中
- mov bx, ax ;把ax传给bx暂时保存,因为我们还有第二个乘法需要使用到ax寄存器
-
- mov ax, 2 ;第二个乘法被乘数传给ax
- mul dl ;乘法运算,乘积传给ax,3列每一列时2个字节一个字所以这里乘以2
- sub ax, 2 ;乘积减2这里的减2是因为计算机是从0开始运算的所以上面那三个列是从0开始的也就是0到2,这所说的列是一字为单位的不是以字节所以上面乘以2
-
- add bx, ax ;用行数字节数加上列数字节数最后定位到的就是我们要在屏幕那个地方输出,最后数据传输给bx
-
- mov ax, 0b800h ;把0B800H这个段地址传给ax
- mov ds, ax ;把ax中的数据传给ds使得他可以被读写
- mov si, 0 ;初始化si寄存器为零
- mov di, 0 ;初始化di寄存器为零
- mov al, cl ;把cl中字体的属性参数传给al因为我们下面要调用cl
- ok:
- mov cl, byte ptr es:[si] ;把data3中si位置的数据传给cl中,这样可以及可以传输数据也可以有做下面的jcxz做判断是否跳转,因为汇编规定,内存段中不能相互传输数据,必须得借助寄存器
- mov ch, 0 ;初始化ch防止ch中有数据
- jcxz good ;如果cx中数据是0及执行该条语句跳转到good标记处,如果不是0就不执行该语句
- mov byte ptr ds:[bx + di], cl ;把cl中的数据传给显示段地址0B800H偏移地址bx+di处
- mov byte ptr ds:[bx + di + 1], al ;把属性传给段地址0B800H偏移地址bx+di+1处
- inc si ;si+1
- add di, 2 ;di+2因为显示段一次性是输入两个字节的数据所以di+2
- jmp short ok ;跳转回ok标记处继续执行输出
- good: ;如果jcxz good处检测到cx寄存器的数据是0就跳转到该处,并向下执行
- ret ;返回call show_str处并向下执行结束语句
-
- code ends
- end start
复制代码 |
|