|
几天以来因为有课有工作不能完全静下心来做这个设计,断断续续的调试,今天早上终于把它搞定啦!挺高兴的,hoho~~
调试汇编程序很磨练人的耐性,急功近利或急于求成是学不到东西的,在调试过程中要摆好心态,抓住每一次碰到问题解决问题的机会,不轻易放弃。另外,调试汇编程序必须及其细心,着眼到每一条指令上,因为每一条指令都可能使你的程序崩溃。
我想应该不只是调程序吧!只有用心调了才能真正学到东西,才能真正感受到调程序时的乐趣。这样的道理跟生活中也相通,再多华丽的文字也无法描述生活的美,只有我们用心生活,学着尝试在生活中做个有心人,怀着一颗对生活敏感的心去感受生活中的点滴——每一缕思绪、每一份感情、每一次心灵触动……你会发现生活给了我们太多太多……
“生活不是有钱人的,也不是有权人的,生活是有心人的!”喜欢这句话。
其实,技术是生活中的一道调味剂,也是感受生活的一种途径。看到我标题(长×宽×高)下面的签名了没?嘿嘿~“我爱技术,我更爱生活。。。”
这次调试程序过程中有几点比较大的感触:
1、写程序之前最好先布好设计框架,设计出流程图。小的程序还好,直接在脑子里面构思,大一点的程序就麻烦了,思路一乱起来,程序就跟着乱了,那样调试的时候就得吃苦头了。
2、写程序过程时,应把一些功能指令,汇到一个子函数中,等要用到该功能时,再让子函数调用,尽量简化主函数,这样会使条理更清晰,这点跟C语言有点相识。
3、写子程序时,之前用过的寄存器如果子函数中要用到,要记得将其压入堆栈,以免数据丢失。
4、在使用push和pop指令时,注意顺序,并且之前压入多少数据,一般后面就要弹出多少数据,以免出现栈乱。
不说太多了,下面把我的程序和运行结果贴出来,供志同道合之士交流。
代码:
assume cs:code,ds:data,ss:stack,es:table
data 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年的21个字符串
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;以上是表示21年公司总收入的21个dword型数据
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word型数据
data ends
table segment
db 'year earn emp ave '
db 21 dup(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
table ends
stack segment
db 256 dup(0)
stack ends
code segment
start:
mov ax,data;数据段
mov es,ax
mov bx,0
mov bp,0
mov ax,stack;栈段
mov ss,ax
mov sp,0
mov ax,table;表格数据段
mov ds,ax
mov si,0
mov cx,21
copydata:;将所有数据复制到表格数据段中
push cx
;复制年份到表格数据段中
mov ax,es:[bx]
mov ds:01ah[si],ax
mov ax,es:[bx+2]
mov ds:01ah[si+2],ax
;复制收入到表格数据段中
mov ax,es:054h[bx]
mov ds:01ah[si+6],ax
mov ax,es:054h[bx+2]
mov ds:01ah[si+8],ax
;复制雇员数到表格数据段中
mov ax,es:0a8h[bp]
mov ds:01ah[si+0fh],ax
;计算出人均收入并存入表格数据段中
mov ax,es:054h[bx]
mov dx,es:056h[bx]
mov cx,es:0a8h[bp]
call divdw
mov ds:01ah[si+016h],ax
mov ds:01ah[si+018h],dl
;为下一次循环做准备
add bx,4
add bp,2
add si,01ah
pop cx
loop copydata
;以下将表格中的数据转换成字符串形式,并将所有的数据显示出来
mov ax,0b800h;使es:bx指向显示缓冲区
mov es,ax
mov bx,0
mov si,0
mov dh,0;初始化,第0行
mov dl,0;初始化,第0列
mov cx,22;表格数据共22行,循环22次
;以下将表格标题数据显示出来
mov cl,07h;字符颜色属性(黑底白字)
mov ah,cl;将字符的颜色属性存入ax的高八位
mov cx,26;表格标题数据类型为字符串,25个字符
table_title:
mov al,ds:[si];将字符的ASCII码存入ax的低八位
mov es:[bx],ax;将字符及其属性载入显存空间
inc si
add bx,2
loop table_title
mov bx,0a0h;显示缓冲区第1行
mov cx,21
showtable:
push cx
;以下将年份数据显示出来
mov cl,07h;字符颜色属性
mov ah,cl;将字符的颜色属性存入ax的高八位
mov cx,4;年份数据类型为字符串,4个字符
year:
mov al,ds:[si];将字符的ASCII码存入ax的低八位
mov es:[bx],ax;将字符及其属性载入显存空间
inc si
add bx,2
loop year
add si,2
add bx,4
;以下将收入数据转换成十进制并显示出来
mov ax,ds:[si]
mov dx,ds:[si+2]
call dtoc
call show_str
add si,9
add bx,18
;以下将雇员数据转换成十进制并显示出来
mov ax,ds:[si]
mov dx,ds:[si+2]
;mov bx,10
call dtoc
call show_str
add si,7
add bx,14
;以下将人均收入数据转换成十进制并显示出来
mov ax,ds:[si]
mov dl,ds:[si+2]
mov dh,0
call dtoc
call show_str
;inc dh;显示完一行换行
;mov dl,0;列不变
add si,4
add bx,6
add bx,06eh;显示缓冲区每行可以显示80个字符,共160个字节,
;已显示25个字符,剩55个字符,即110(06eh)个字节
pop cx
loop showtable
mov ax,4c00h
int 21h
;函数名:dtoc
;功能:将dword型数据转变为十进制数的字符串
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; ds:si指向字符串首地址
;返回:无
dtoc:
push bx
push cx
push dx
push si
push di
mov bx,10
mov di,0h;空操作符,用作字符串结束标志
push di
s1:
mov cx,bx
call divdw
add cx,030h
push cx;将取得的余数压入堆栈
mov bx,10
push ax
add ax,dx
mov cx,ax;将取得的商赋值给cx,用来判断取得的商是否为0
pop ax
inc cx;此处使cx加1是因为执行loop之前要先使cx减1
loop s1
s0:
pop bx
mov cx,bx
jcxz stop
inc cx;此处使cx加1是因为执行loop之前要先使cx减1
mov bh,0
mov ds:[si],bl
inc si
loop s0
stop:
mov bh,0
mov ds:[si],bl
pop di
pop si
pop dx
pop cx
pop bx
ret
;函数名:divdw
;功能:进行不会溢出的除法运算,被除数为dword型,除数为word型,结果为dword型
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位
; (ax)=结果的低16位
; (cx)=余数
divdw:
push bx
push ax;压入被除数低八位
mov ax,dx
mov dx,0
div cx
mov bx,ax
pop ax;弹回被除数低八位
div cx
mov cx,dx
mov dx,bx
pop bx
ret
;函数名:show_str
;功能:在指定的位置,用指定的颜色,显示一个25字节的字符串
;参数:(cl)=颜色,ds:si指向字符串的首地址
;返回:无
show_str:
;将主程序用到的寄存器入栈
push ax
push bx
push cx
push dx
push si
s:
mov ah,07h
mov al,ds:[si];将字符的ASCII码存入ax的低八位
;以下判断al是否为0,为0则结束读取字符串
mov cl,al
mov ch,cl
jcxz ok
mov word ptr es:[bx],ax;将字符及其属性载入显存空间
inc si
add bx,2
loop s
ok:;将主程序用到的寄存器出栈
;pop cx;此处由于在“jcxz ok”之前进行了一次push cx,而后并无pop cx,在此将cx弹出堆栈
pop si
pop dx
pop cx
pop bx
pop ax
ret
code ends
end start
运行结果: