assume cs:code,ds:data,es:table,ss:stack
data segment
;bx = 0
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个字符串,4*21=84
;bx+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年的总收入的dword型数据,dx高位,ax低位, 4*21=84
; bp+84+84 = bp+168
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635
dw 8226,11542,14430,15257,17800
;以上表示公司员工人数word 共21组数据 2*21=42
data ends
table segment
db 21 dup ('year x y z ',0)
; 0 8 19 28
table ends
stack segment
db 64 dup (0)
stack ends
code segment
start:
;设置栈顶,
mov ax,stack
mov ss,ax
mov sp,64
;设置es指向原始数据data bx为db偏移,bx+84为dd偏移,bp为dw偏移
mov ax,data
mov es,ax
mov bx,0
mov bp,168
;设置ds:si指向字符串table数据的首地址
mov ax,table
mov ds,ax
mov si,0
mov cx,21 ;循环次数
loop_s:
;复制年份数据到ds:si中,ds:0
mov ax,es:[bx]
mov [si],ax
mov ax,es:[bx+2]
mov [si+2],ax ;加2是因为ax是16位,16/8=2
;复制总收入数据,转换成字符串
mov ax,es:[bx+84]
mov dx,es:[bx+86]
push si
add si,8
call dtoc
pop si ;将ds:si重新指向每一行的行首
;复制员工数据,转换成字符串
mov ax,es:[bp]
mov dx,0 ;因为员工数小于16位,所以高16位置0
push si
add si,19
call dtoc
pop si
;计算平均数,结果在ax中
mov ax,es:[bx+84]
mov dx,es:[bx+86]
div word ptr es:[bp]
mov dx,0 ;因为平均数小于16位,所以高16位置0
push si
add si,28
call dtoc
pop si
;计算行数,一共循环21次,每次都会加4,加2,加32 ,
mov ax,bx
push bx
push cx
mov bl,4
div bl ;所以除以每一次加的数得到行数,
mov dh,al ;结果在al中,传送到dh中
add dh,1 ;行数加1,因为会向上移一行
mov dl,5 ;在第几列开始
mov cl,2
call show_str
pop cx
pop bx
;pop cx 多出栈一个cx,程序进入死循环
add bp,2
add bx,4
add si,32
loop loop_s
mov ax,4c00h
int 21h
;\+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
;|名称:dtoc |
;|功能:将dword型数据转变为表示十进制的字符,字符串以0为结尾符.|
;|参数:(ax)=dword型数据的低16位 (dx)=dword型数据的高16位 |
;| ds:si指向字符串首地址 |
;|返回:无 |
;/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\
dtoc:
;入栈-----------------------
push bx
push cx
push di
push ax
push dx
push si
;---------------------------
mov di,0
dtoc_div:
mov cx,10
call divdw
add cx,30h
push cx
inc di
mov cx,dx
add cx,ax
jcxz dtoc_div_end
jmp short dtoc_div
dtoc_div_end:
mov cx,di
dtoc_mov:
pop ax
;mov [si],ax 此处传送两个字的进入一个字符中,所以出错
mov [si],al
inc si
loop dtoc_mov
;出栈-----------------------
pop si
pop dx
pop ax
pop di
pop cx
pop bx
;---------------------------
ret
;\+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
;|名称:divdw |
;|功能:解决除法运算时,可能出现的数据溢出问题 |
;|参数:被除数:ax+dx 32位组合 除数:cx |
;|返回:商:ax+dx 余数:cx |
;|X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N |
;|X被除数,N除数,int取整,rem取余,H高16位,L低16位,*65536存在dx中 |
;/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\
divdw:
jcxz div_ok ;如果cx是0则跳到div_ok处
;入栈-----------------------
push bx
;---------------------------
push ax ;把低位暂存在栈中
mov ax,dx
mov dx,0
div cx ;商ax=int(H/N)*65536 余dx=rem(H/N)*65536
mov bx,ax ;把高位的商暂存在reg中
pop ax
div cx ;[rem(H/N)*65536+L]/N
;商ax 余dx
mov cx,dx ;将结果余数放入cx中
mov dx,bx ;把暂存在reg中的商放入高位 int(H/N)*65536
;出栈-----------------------
pop bx
;---------------------------
div_ok:
ret
;\+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
;|名称:show_str |
;|功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串. |
;|参数:(dh)=行号(取值范围0~24),(dl)=列号(取值范围0~79), |
;| (cl)=颜色,ds:si指向字符串首地址 |
;|返回:无 |
;/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\
show_str:
;入栈-----------------------
push ax
push es
push bx
push si
;---------------------------
;设置显示缓冲区
mov ax,0B800h
mov es,ax
;8位乘法,al与另一个reg相乘,结果在ax中
mov al,160 ;行的倍数,
mul dh
mov bx,ax
mov al,2 ;列的倍数
mul dl
add bx,ax ;用bx做偏移地址
mov ah,cl ;颜色存放在ah,字符存放在al
mov ch,0
show_xh:
mov cl,[si]
jcxz show_xh_ok ;如果cx是0则跳到show_xh_ok处
mov al,cl ;cx非0,al=cl=[si]
mov word ptr es:[bx],ax ;此时,高位ah=颜色,低位al=字符
inc si
add bx,2
;loop show_xh
jmp short show_xh
show_xh_ok:
;出栈-----------------------
pop si
pop bx
pop es
pop ax
;---------------------------
;释放show_str子程序
ret
code ends
end start
汇编课程设计一(记录)
于 2023-05-06 15:18:00 首次发布