《汇编语言》王爽 课程设计1

时间:2021-07-09 01:13:59

写在前面的话:最近在学习汇编,前面的几个小程序都是写在纸上孤芳自赏了一下,没有在电脑上跑,第一个课程设计才尝试在电脑运行。本来觉得调一个晚上肯定成功,果然是高估我的水平了。真后悔不是从小程序跑起,问题的难度以指数形式累加啊~debug又不像在vs/eclipse底下那么方便,前前后后弄了好几天,终于弄好了。

这是我人生第一篇技术博客,恩。。。真心算不上技术,不过如果有借鉴价值的话,尽管拿过去用~

题目:《汇编语言》第三版 作者:王爽 P211 课程设计1

程序设计思路:

将data中某行数据以16进制放入table中,再将table中的16进制转换为ASCII码放入content中,最后在屏幕上显示content中的内容。以此循环21次,将所有数据显示一遍。

伪代码:

for(int i=0;i<21;i++)

1.将第i行数据的年份,收入,人数,平均工资放入table中

2.将table中的数据转化为可显示的ASCII码放入content中

3.在屏幕第j行显示content里的值

4.j++

说明:

用于循环的i放在CX中

表示显示的第j行放在DH中


于是为此我设计了3个函数对应解决for循环中1 2 3中的问题

1.函数名wtable(意思为write table)

功能:将第i行数据的年份,收入,人数,平均工资放入table中

    输入:DS:[SI]指向要开始的年份,DS:[BX]指向人数,ES:[DI]指向要写入数据的地址,即table的首地址

    返回:无


2.函数名:scontent

功能:将table中的数据转化为可显示的ASCII码放入content中

  输入:ES:[DI]指向要转换的ASCII码的字符串首地址,即table的首地址;DS:[SI]指向目标数据段的首地址,即content的首地址

  返回:无

 这个函数要配合从ccontent函数使用)


3.函数名:ccontent

功能:将16进制数转换为10进制数的ASCII码,如0fh->31 35(十进制数10,可显示的ASCII码为31h(对应1),35h(对应5))

输入:AX为16进制数的低4位,DX为16进制数的高4位,DS:[SI]指向要写入ASCII码的地址,即content

返回:无


4.函数名:show_str

  功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串

输入:(DH)=行号(0-24),(DL)=列号(0-79)

                  (CL)=颜色,DS:SI指向字符串的首地址

    返回:无

   

5.函数名:divdw

功能:进行不会产生一处的除法运算,被除数为dword型,除数为word型,结果为dword型

输入:(AX)=dword型数据低16位

    (DX)=dword型数据高16位

    (CX)=除数

返回:(AX)=结果低16位

    (DX)=结果高16位

    (CX)=余数


代码如下:

assume cs:code,ss:stack
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1900','1991','1992'
db '1993','1994','1995'


dd 16,22,382,1356,4390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000


dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
data ends


table segment
db 'year summ ne ?? '
table ends


content segment
db 40 dup(' ')
content ends


stack segment
db 64 dup(0)
stack ends


code segment
start:mov ax,stack
mov ss,ax
mov sp,64
mov cx,21

mov dh,4
mov si,0
mov bx,0
s: push si
push cx

mov ax,data
mov ds,ax

mov ax,table
mov es,ax
mov di,0

call wtable;write table

mov di,0

mov ax,content
mov ds,ax
mov si,0

call scontent ;table->content

mov dl,2
mov cl,2
mov si,0
call show_str;show string
inc dh

pop cx
pop si
add si,4
add bx,2
loop s

mov ax,4c00h
int 21h

wtable:push ax
push ds
push si
push es
push di
push dx
push cx

mov ax,ds:[si]
mov es:[di],ax
mov ax,ds:[si+2]
mov es:[di+2],ax

mov ax,ds:[si+84]
mov es:[di+5],ax ;high
mov dx,ds:[si+84+2]
mov es:[di+7],dx

mov cx,ds:[bx+84+84]
mov es:[di+10],cx

call divdw
mov es:[di+13],ax

pop cx
pop dx
pop di
pop es
pop si
pop ds
pop ax

ret

scontent:push bx
push ax
push es
push di
push dx
push cx
push ds
push si

mov ax,es:[di]
mov ds:[si],ax
mov ax,es:[di+2]
mov ds:[si+2],ax

add si,10

mov bx,0
mov ax,es:[di+5];low
mov dx,es:[di+7];high
call ccontent

mov bx,0
mov ax,es:[di+10]
mov dx,0
add si,10
call ccontent

mov bx,0
mov ax,es:[di+13]
mov dx,0
add si,10
call ccontent

pop si
pop ds
pop cx
pop dx
pop di
pop es
pop ax
pop bx
ret


ccontent:push cx
push bx
push ax
push ds
push si

c: mov cx,0ah
call divdw
add cx,30h
push cx
inc bx
mov cx,ax
jcxz re
jmp c

re:mov cx,bx
r:pop bx
mov ds:[si],bl
inc si
loop r

pop si
pop ds
pop ax
pop bx
pop cx
ret

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:push ax
push es
push di
push dx
push si
push cx


mov ax,0b800h
mov es,ax
mov al,160
mul dh
mov dh,0
add dx,dx;double dl
add ax,dx
mov di,ax
s2:push cx
mov al,ds:[si]
mov ah,cl;green
mov es:[di],ax
inc si
add di,2
mov ch,0
mov cl,ds:[si]
jcxz s3
pop cx
jmp s2

s3:pop cx

pop cx
pop si
pop dx
pop di
pop es
pop ax
ret

code ends
end start

code ends
end start


运行结果:

《汇编语言》王爽 课程设计1

该程序需要改进的地方:

1.细心的你也许已经发现了在数据段1979年的收入2390被我“不小心”敲成了4390。其实我故意改变了这个数据,使得平均收入为3位10进制数。事实上这是我的这个程序的第一个不足之处。我所设计的用于显示在屏幕上的content是一个初始值为长40的空格组成的数据段,每次都将table中的数据改变为可显示的字符(数值+30h,eg:1->31h)存入content,再调用show_str函数。但每次循环并不初始化,即上次的数据留在content中,必须后面的数据长度大于等于之前的数据才能全部遮盖住之前的数据,才能正常显示。说的可能不太清楚,拿1978和1978年的数据来举例:

题目希望得到的结果:

1978      1356      13        104

1970      2390      28        85

但按照我写的程序的结果:

1978      1356      13        104

1970      2390      28        854

即854中的4是104中未被遮盖住的4,并非结果计算的错误。


2.栈空间设计为64个字节,事实上有点大了,大约大了16个字节,有一定的空间浪费。