课程设计1
本帖最后由 雪球丶 于 2020-3-17 23:56 编辑assume cs:code,ss:stack
data segment
;data
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年的字符串
;data + 54H (84)
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;21个年份公司的总收入
;data + A8H(168)
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;21个年份的雇员数
data ends
table segment
; 年份 收入 雇员 人均收入
db 21 dup ('year summ ne ?? ')
table ends
;创建一个数据段,用来存放格式化之后的数据,用空格填充
;每行 年份起始索引0,收入起始索引20,雇员数起始索引40,人均收入起始索引60
format segment
db 1680 dup (' ')
db 0
format ends
stack segment
db 128 dup(0)
stack ends
;将12666以十进制的形式在屏幕的8行3列用绿色显示出来
code segment
start:
mov ax,stack
mov ss,ax
mov sp,128
mov ax,data
mov ds,ax ;初始化数据段
mov ax,table
mov es,ax ;es指向table段地址
;es指向table段地址
call dneat ;整理数据
;将数据中的数字转换为ascii
mov ax,table
mov es,ax ;table段
mov ax,format
mov ds,ax ;format段
mov bx,0 ;table行索引
mov si,0 ;format行索引
mov cx,21
ts:
;拷贝年份数据-字符串(四字节)
mov ax,es:
mov ds:,ax
mov ax,es:
mov ds:,ax
;将收入转换为ascii的数字(四字节)
mov ax,es: ;收入低16位
mov dx,es: ;收入高16位
push bx
push cx
push si
add si,20 ;写到format段每行的第20列处
;函数 dtoc
;将word(16位)型数据转变位标识十进制数的字符串,字符串以0结尾,存放在ds处
;输入参数:
; (ax) = 32位数字的第16位
; (dx) = 32位数字的高16位
; ds:si指向字符串首地址
;返回值: 无
call dtoc
;最后一位多多加了一个0,把0去掉,改为空格
mov al,20H
mov ds:,al
pop si
pop cx
pop bx
;将雇员数改为ascii的数字(2字节)
mov ax,es:
mov dx,0000h
push bx
push cx
push si
add si,40 ;写到format段每行的第40列处
call dtoc
;最后一位多多加了一个0,把0去掉,改为空格
mov al,20H
mov ds:,al
pop si
pop cx
pop bx
;将平均工资改为ascii的数字(2字节)
mov ax,es:
mov dx,0000h
push bx
push cx
push si
add si,60 ;写到format段每行的第60列处
call dtoc
;最后一位多多加了一个0,把0去掉,改为空格
mov al,20H
mov ds:,al
pop si
pop cx
pop bx
add si,80
add bx,16
loop ts
;将format段的第22行第一个数据(21x80 + 1= 1681)改为0,作为输出结束标识
mov ax,0
mov ds:,ax
;显示
mov dh,1 ;第1行
mov dl,0 ;第0列
mov cl,2 ;颜色
mov ax,format
mov ds,ax
mov si,0
call show_str
mov ax,4C00H
int 21H
;将word(16位)型数据转变位标识十进制数的字符串,字符串以0结尾,存放在ds处
;输入参数:
; (ax)=word型数据
; ds:si指向字符串首地址
;返回值: 无
;32位除法所需的寄存器:DX被除数的高16位,AX被除数的低16位,reg,除数(这里是cx)结果:AX商,DX余数
dtoc: ;mov dx,0000H
mov di,si
mov bx,0 ;字符长度计数
;输入参数:
; (ax)=dword型数据的低16位
; (dx)=dowrd型数据的高16位
; (cx)=除数
;返回值:
; (dx)=结果的高16位,(ax)=结果的低16位
; (cx)=余数
s0: mov cx,0AH
push bx ;divdw函数内部会改变bx的值,把bx暂存起来
push si
call divdw
pop si
pop bx
push cx ;数据入栈,因为算出来的顺序是反的,所以用栈来倒一下
inc bx
;检查商是否为0,为0则计算结束,跳出循环
push ax ;ax寄存器的值后面还有用,先保存起来
or ax,dx
mov cx,ax
pop ax
jcxz s1
inc di
mov cx,2
loop s0
s1:
mov di,si
mov cx,bx
ens:
pop ax
add ax,30H ;转换为ASCII
mov ds:,al
inc di
loop ens
mov cl,0 ;末尾写入0
mov ds:,cl
ret
show_str:
mov ax,0b800H ;显存地址
mov es,ax
;计算像素点索引 = rowx160 + colx2
add dl,dl
mov al,dh
mov bl,160
mul bl ;计算出来的行号存储在ax中
mov dh,0
add ax,dx
mov di,ax ;像素写索引
mov dh,cl ;先用dl记录下颜色值,后面直接用dx寄存器写显存;CX寄存器在循环中会被用到,释放cl
ws: ;写显存
mov dl,ds:
mov es:,dx
inc si
add di,2
;查看下一位是否为0
mov cx,0
mov cl,ds:
jcxz wd ;若下一位为0,则跳转到wd处
mov cx,2 ;给CX赋值,如果程序走到这里说明下一位不为0就让其不断循环继续往下写
loop ws
wd: ret
divdw:
mov si,ax ;低16位暂存在si中
;计算高16位,将16位计算转化为32位计算
mov ax,dx
mov dx,0
div cx
mov bx,ax ;H/N存放在BX中
;计算低16位
mov ax,si
div cx
mov cx,dx
mov dx,bx
ret
dneat:
mov bx,0 ;bx作为data段四字节数据的索引 (每次增加4)
mov si,0 ;si作为data段2字节数据的索引 (每次增加2)
mov bp,0 ;bp作为table段的索引 (table每次增加16)
mov cx,21
dn_s:
;拷贝
;table中每年的数据相隔F个字节
;table中同一年数据头索引 year(0)-summ(5)-ne(A)-??(D)
; 长度(byte) 4 4 2 2
mov ax,ds: ;拷贝年份字符串 4 byte 每次2byte
mov es:,ax
mov ax,ds:
mov es:,ax
mov ax,ds: ;拷贝收入字符串 dd=4byte 每次2byte
mov es:,ax
mov ax,ds:
mov es:,ax
mov ax,ds:
mov es:,ax ;拷贝雇员字符串 dw=2byte
;除法计算会改变bx的值,先将bx入栈
push bx
;计算平均收入
;load收入(4字节)
mov ax,ds:
mov dx,ds:
;load人数(2字节)
mov bx,ds:
div bx
;bx出栈
pop bx
;保存计算结果(取整)(2字节)
mov es:,AX
add bx,4H
add si,2H
add bp,10H
loop dn_s
ret
code ends
end start
DOS的汇编debug真的太不友好了,调试了三个多小时.....还发现前面几个测试点的程序里面的bug{:5_104:}
页:
[1]