汇编语言(王爽)P200页 课程设计的啰嗦答案

作者在 2010-09-01 01:30:08 发布以下内容
汇编语言(王爽)P200课程设计的啰嗦答案.
这个程序是我看这本书第五天时编的. 我刚学汇编5天----纯粹的一个初学者,编写这个程序不是一帆风顺,遇到问题没有人去咨询没有人去商量,只能自己一点点的摸索,真的痛苦不堪!. 两个不眠之夜,多少次想放弃汇编不去学了,但是最后还是坚持的做下去,最后结果是我成功了!!!!!!!我很自豪.
相当高兴,现在将这个东西放在这里和大家分享.里边有很多注释,话语是我一贯的作风----啰嗦!
还有一个啰嗦就是程序比较啰嗦,有很多地方可以简化,但是我还要继续看后边的中断部分这里就不在进行了.但是我在下边提出了一些关于简化的想法,只要有机会我还是会按照我的想法重新做的.毕竟做一个纯粹的程序员不是通过编程序而去混饭吃,而是见程序当做音乐的音符去编写不留杂音的.好的程序员他编写的程序在具有同等功能的其他程序中他的程序最"安全"!最"精炼"
好了不不再啰嗦了,有兴趣的继续看下边的程序吧!
下边的源代码我用masm for windows调试的,希望对初学者有帮助,同时希望高手提出宝贵的意见,谢谢!!!
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;对下边程序的文字说明
;data2---->a seg
;data3---->b seg
;c1---->d 运算之后的数据存放在d
;c1 最后所有的数据都汇总的c1,当然也可以声调这个步骤直接写入显存.
;在a.b.d.中重新写入的数据是有格式的,数据的第一位是数据的长度(字节数),这个位的生成是在dtoc中
;         最后一位是结束位表示这个字节结束了,结束位的标志是'00',当然这个字节可以省略
;show_str代码中也有关于字符结束的认定,就是当它读入一个字符为'00'时认为已经读完数据开始ret
;在strcls中设置的全部输出为空'20h',在2001中设置字节值为'00'
;data2/data3----->c1  c1仅仅作为一个中间方.
;strnote 一个字作为一个记录,低位为长度,高位为起始地址,
;screndata 每次用完数据要整理一次全部变成1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
assume cs:li
data1 segment
 db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
 db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
 db '1993','1994','1995'
 ;21个字符串     合计 84 byte          54h
data1 ends
data2 segment
 dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
 dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
 ;21个dword数据  合计 84 byte          54h
data2 ends
data3 segment
 dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
 dw 11542,14430,15257,17800
 ;21个word数据   合计 42 byte 
data3 ends
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;栈
stack segment
 dd 64 dup(0ffffh)
stack ends
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;栈
a segment
 db 160 dup(0)
a ends
b segment
 db 112 dup(0)
b ends
d segment
 db 160 dup(0)
d ends
c1 segment
 db 2001 dup(11h)
c1 ends
;;;li主程序的开始;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
li segment
start:
 mov bx,data1
 mov bx,data2
 mov bx,data3
 mov bx,a
 mov bx,b
 mov bx,c1
 mov bx,d
 mov bx,0    ;;上边这几段可以省略的,这些是为了在程序开始的时候记录存储空间的
                  ;;各个段地址,以便在出现问题的时候进行内存数据查询.
 mov ax,stack
 mov ss,ax
 mov sp,120
;;;;;;;data2---->a seg begin
;ax 传递要转换的数低16位
;dx 传递要转换的数高16位
;ds:si 传递转换后的数据存放首地址
;字符返回直接存储到制定的地址空间,存储方式为第一位指定的了字符的长度,后边为字符,字符最后一位用0结束.
;si 返回输出字符的最后一位的下一位.
;后面还有一段排序用的函数.
;bp 仅仅作为偏移地址计算
 mov ax,a
 mov ds,ax
 mov si,0
 mov di,0
 mov cx,21
data2a:
 push ds          ;;;push ds in 1
 mov bx,data2
 mov ds,bx
 mov ax,ds:[di]
 add di,2
 mov dx,ds:[di]  ;;传递ax,dx数值
 add di,2
 pop ds           ;;;pop ds out 1
 call dtoc
 loop data2a
;;;;;;;data2---->a seg转换排序整理结束;;;;;;;;;;;;;;;;;;;;;;;ok
;;;;;;;;data3---->b seg begin
 mov ax,b
 mov ds,ax
 mov si,0
 mov di,0
 mov cx,21
data3b:
 push ds          ;;;push ds in 2
 mov bx,data3
 mov ds,bx
 mov ax,ds:[di]
 add di,2
 mov dx,0   ;;传递ax,dx:00数值
 pop ds           ;;;;push ds in 2
 call dtoc
 loop data3b
;;;;;;;;data3---->b seg转换排序整理结束; 
;;;;;;;;data2/data3----->c1进行除法运算
;ax 被除数dword L16bit
;dx 被除数dword H16bit
;cs 除数
;返回值ax 商dword L16bit
;返回值dx 商dword H16bit
;返回值cs 余数
 mov cx,21
 mov di,0
 mov si,0
d23c1:
 push cx                     ;push cx1    
 mov bx,data2
 mov ds,bx
 mov ax,ds:[si]
 add si,2
 mov dx,ds:[si]            ;;;传递AX,DX,CX数据进行除法运算
 add si,2
 mov bx,data3
 mov ds,bx
 mov cx,ds:[di]
 call divdw
 mov bx,c1
 mov ds,bx
 mov ds:[di],ax            ;;传递ax数据进行类型变换
 add di,2
 pop cx         ;pop cx1
 loop d23c1
;;;;;;;;data2/data3----->c1进行除法运算结束 ;;;;;;;;;;;;;;;ok
;;;;;;;;c1---->d seg begin
;ax 传递要转换的数低16位
;dx 传递要转换的数高16位
;ds:si 传递转换后的数据存放首地址
 mov cx,0ffffh
 mov bx,d
 mov ds,bx
 mov si,0
 mov di,0
 mov cx,21
ok1:
 push ds     ;push ds 1
 mov bx,c1
 mov ds,bx
 mov ax,ds:[di]
 add di,2
 mov dx,0
 pop ds       ;pop ds 1
 call dtoc
 loop ok1 
;;;;;;;c1---->d seg转换排序整理结束;
;;;;;;;;;;;;; c1 数据整理begin;;;;;;;;;;;;;;;;;;;;;;;;;
 mov ax,c1
 mov ds,ax
 mov si,0
 mov al,20h     ;;输入空格屏幕没有显示
 mov cx,2000
strdatacls: 
 mov ds:[si],al
 inc si
 loop strdatacls
 mov ds:[si],00h
;;;;;;;;;;;;; c1 数据整理end ;;;;;;;;;;;;;;;;;;;;;;;;;;ok
;;;;;;;;;;;;;;;;data1中数据写入c1中;;;;;;;;;;;;;;;;;;;begin
 mov ax,data1
 mov ds,ax
 mov si,0
 mov ax,c1
 mov es,ax
 mov di,0ffb2h       ;;初始位置应该是0ffb0h,这里的0ffb4h多了4字节为了让显示的位置好看些
 mov cx,21           ;初始化
data1toc1: 
 push cx
 mov cx,4
data1toc1in: 
 mov al,ds:[si]
 inc si
 mov es:[di+80],al    ;;这里用的是di+80,由于前边的初始化我们可以这么做,要不读取每段数据的第一值需要
                              ;;再重新编写一段代码然后再进入loop循环.
 inc di
 loop data1toc1in
 add di,76
 pop cx
 loop data1toc1
;;;;;;;;;;;;;;;;data1中数据写入c1中;;;;;;;;;;;;;;;;;;;;;;ok
;;;;;;;;;;;;;;;; a 中数据写入c1 中 ;;;;;;;;;;;;;;;;;;;;;;
 mov ax,a
 mov ds,ax
 mov si,0
 mov ax,c1
 mov es,ax
 mov di,0ffc8h
 mov cx,21           ;初始化
atoc1: 
 push cx
 mov cx,ds:[si]
 mov ch,0
 mov bx,cx
 inc si
atoc1in: 
 mov al,ds:[si]
 inc si
 mov es:[di+80],al
 inc di
 loop atoc1in
 inc si
 sub di,bx
 add di,80
 pop cx
 loop atoc1
 
;;;;;;;;;;;;;;;; a 中数据写入c1 中 ;;;;;;;;;;;;;;;;;;;;;;ok
;;;;;;;;;;;;;;;; b 中数据写入c1 中 ;;;;;;;;;;;;;;;;;;;;;;
 mov ax,b
 mov ds,ax
 mov si,0
 mov ax,c1
 mov es,ax
 mov di,0ffdch
 mov cx,21           ;初始化
btoc1: 
 push cx
 mov cx,ds:[si]
 mov ch,0
 mov bx,cx
 inc si
btoc1in: 
 mov al,ds:[si]
 inc si
 mov es:[di+80],al
 inc di
 loop btoc1in
 inc si
 sub di,bx
 add di,80
 pop cx
 loop btoc1 
;;;;;;;;;;;;;;;; b 中数据写入c1 中 ;;;;;;;;;;;;;;;;;;;;;;ok
;;;;;;;;;;;;;;;; d 中数据写入c1 中 ;;;;;;;;;;;;;;;;;;;;;;
 mov ax,d
 mov ds,ax
 mov si,0
 mov ax,c1
 mov es,ax
 mov di,0fff0h
 mov cx,21           ;初始化
dtoc1: 
 push cx
 mov cx,ds:[si]
 mov ch,0
 mov bx,cx
 inc si
dtoc1in: 
 mov al,ds:[si]
 inc si
 mov es:[di+80],al
 inc di
 loop dtoc1in
 inc si
 sub di,bx
 add di,80
 pop cx
 loop dtoc1 
;;;;;;;;;;;;;;;; b 中数据写入c1 中 ;;;;;;;;;;;;;;;;;;;;;;ok
;;;;;;;;;;;;;;;;;;调用写入显存数据程序;;;;;;;;;;;;;;;;;;;;;;;;;
 mov ax,c1
 mov ds,ax
 mov si,0
 mov dh,5
 mov dl,1
 mov cx,0
 mov cl,2
 call show_str
;;;;;;;;;;;;;;;;;;调用写入显存数据程序;;;;;;;;;;;;;;;;;;;;;;;;;ok

 mov ax,4c00h
 int 21h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;----------------dtoc begin-------------------
;ax 传递要转换的数低16位
;dx 传递要转换的数高16位
;ds:si 传递转换后的数据存放首地址
;字符返回直接存储到指定的地址空间,存储方式为第一位指定的了字符的长度,后边为字符,字符最后一位用0结束.
;si 返回输出字符的最后一位的下一位.
;后面还有一段排序用的函数.
;bp 仅仅作为偏移地址计算
dtoc:
 push cx
 push bx
 push bp
;入栈保护
 mov bp,1 
ndiv:
 mov cx,10
 mov bx,ax
 mov ax,dx
 mov dx,0
 div cx
 push bp   ;bp push 1
 mov bp,ax
 mov ax,bx
 div cx
 mov cx,ax
 mov bl,dl
 mov dx,bp
 pop bp   ;bp pop 1 
 add bl,30h
 mov ds:[si+bp],bl
 inc bp
 add cx,1
 loop ndiv  
 sub bp,1
;----------- ;此时转换完毕但是这是还是倒序,需要重新排列顺序;
 push ax
 push dx
 push cx
 push si
 push bp
 push bx
 mov bx,1
 mov ax,bp
 mov dx,0
 mov cx,2
 call divdw
 mov cx,ax
number: 
 mov al,ds:[si+bx]
 mov ah,ds:[si+bp]
 mov ds:[si+bp],al
 mov ds:[si+bx],ah
 inc bx
 sub bp,1
 jcxz cxz
 loop number
cxz:
 pop bx
 pop bp
 pop si
 pop cx
 pop dx
 pop ax
;----------- ;这上边一小段函数将倒序变成顺序的;-
 mov bx,bp
 mov ds:[si],bl
 add si,bp
 inc si       ;用来在结束添加'00'确定结束地址
 mov al,0
 mov ds:[si],al
 inc si
;出栈保护
 pop bp
 pop bx
 pop cx
 ret
;----------- ;----------------------------divdw  begin-------------------------------
;ax 被除数dword L16bit
;dx 被除数dword H16bit
;cs 除数
;返回值
;ax 商dword L16bit
;dx 商dword H16bit
;cs 余数
divdw:
 push bx
 push si
 push di
;入栈保护
 mov si,ax
 mov ax,dx
 mov dx,0
 div cx
 mov bx,ax  ;ax  dword H16bit商,dx dword H16bit余数 
 mov ax,si
 div cx   ;ax  dword L16bit商,dx dword L16bit余数 
 mov cx,dx
 mov dx,bx
;出栈返回     
 pop di
 pop si
 pop bx
 ret
;----------- ;----------------------------divdw  end------------------------------- 
;----------------dtoc end --------------------
;
;-------------show_str begin----------------
;dh 显示器显示的行数
;dl 显示器显示的列数
;cl 显示器显示的字体颜色
;ds 程序中要显示的数据地址
show_str:
 push bp
 push ss
 push cx
 push ax
 push bx
 push ds
 push es
;上边为入栈保护 ax,es,dx,bp,bx,ds,cx
 mov ax,0b800h
 mov es,ax       ;es:bp 显示器的  段地址:偏移地址 
 mov ax,160
 sub dh,1
 mul dh
 mov bp,ax       ;显示器显示的初始地址定位行
 sub dl,1
 mov ax,2
 mul dl
 add bp,ax       ;显示器显示的初始地址定位: {行*每行列数}+列
 mov bx,0
 mov ah,cl       ;ah 存储数据颜色 cl 使用结束,由ah代替cl,
 mov cx,0
sjp1:
 mov al,ds:[si+bx] ;将数据读出
 mov cl,al
 jcxz okc
 inc bx
 mov es:[bp],al   ;将数据放入显存
 add bp,1
 mov es:[bp],ah
 add bp,1
 jmp short sjp1
;下边为出栈释放
okc:
 add si,bx       ;返回源文件所读数据的下一个数据的指针
 pop es
 pop ds
 pop bx
 pop ax
 pop cx
 pop ss
 pop bp 
 ret
;-------------show_str end----------------
 
li ends
end start
 
 
汇编 | 阅读 936 次
文章评论,共0条
游客请输入验证码