這道題其實就是把前面的幾次練習串在一起就可以。難點在於第二列,要先實現32位除以16位的divdw子程序。
不失一般性,這裏還是實現了最後3年的結果。
; analysis for 3 years for efficiency and it is easy to extend to 21 years.
assume cs:codesg
stack segment
db 32 dup (0)
stack ends
year segment
db '1993','1994','1995'
year ends
salary segment
dd 3753000,4649000,5937000;394428h,46f028h,5a9768h
salary ends
;employee num
enum segment
dw 14430,15257,17800;385eh,3b99h,4588
enum ends
table segment
db 3 dup ('year sala en as ')
table ends
buf segment
db 200 dup (0)
buf ends
codesg segment
start:
;stack init
mov ax,stack
mov ss,ax
mov sp,32
;loop init
mov si,0 ; year size and salary size =4
mov bp,0 ; enum size =2
mov cx,3
mov ax,table
mov es,ax ; es put table
mov di,0
loop_entry:
push cx
;copy year
mov ax,year
mov ds,ax
mov cx,4
mov bx,si
loop_year:
mov ah,[bx]
mov es:[di],ah
inc di
inc bx
loop loop_year
;copy space
mov byte ptr es:[di],0
;copy salary
inc di
mov ax,salary
mov ds,ax
mov cx,4
mov bx,si
;prepare for calc average salary
push [bx+2]
push [bx]
loop_salary:
mov ah,[bx]
mov es:[di],ah
inc di
inc bx
loop loop_salary
;copy space
mov byte ptr es:[di],0
;copy employee num
inc di
mov ax,enum
mov ds,ax
mov cx,2
mov bx,bp
;prepare for calc average sala
push [bx]
loop_enum:
mov ah,[bx]
mov es:[di],ah
inc di
inc bx
loop loop_enum
;copy space
mov byte ptr es:[di],0
;calc avarage salay
pop bx;
pop ax;
pop dx;
div bx
;averary salary
inc di
mov es:[di],ax
inc di
inc di
;copy space
mov byte ptr es:[di],0
inc di
add si,4
add bp,2
pop cx
loop loop_entry
;print the table to screen
;init ds=table
mov ax,table
mov ds,ax
;print year ds[si]
mov cx,3
mov si,0
;init print registers
mov dh,1 ; line start from 1
mov dl,1 ; column start from 1
mov bl,7 ; color=white/black
L119:
call show_str
;update registes
inc dh
add si,16 ; point to next line
loop L119
;print salary
;loop init
mov cx,3
mov di,5 ;salary offset=5 in each table entry
;loop print high and low 16bits
;init string dest
mov ax,ds
mov es,ax
mov ax,buf
mov ds,ax
mov si,0
mov bh,1 ;print line init
L145:
mov dx,es:[di+2]
mov ax,es:[di]
call itoa
;init print registers
mov dh,bh ; line start from 1
mov dl,6 ; column start from 5
mov bl,7 ; color=white/black
call show_str
;update registes
inc bh
add di,16 ; point to next line
loop L145
;print employee num
;loop init
mov cx,3
mov di,10 ;salary offset=10 in each table entry
;loop print high and low 16bits
;init string dest
mov ax,table
mov es,ax
mov ax,buf
mov ds,ax
mov si,0
mov bh,1 ;print line init
L177:
mov dx,0
mov ax,es:[di]
call itoa
;init print registers
mov dh,bh ; line start from 1
mov dl,14 ; column start from 14
mov bl,7 ; color=white/black
call show_str
;update registes
inc bh
add di,16 ; point to next line
loop L177
;print average salary
;loop init
mov cx,3
mov di,13 ;salary offset=10 in each table entry
;loop print high and low 16bits
;init string dest
mov ax,table
mov es,ax
mov ax,buf
mov ds,ax
mov si,0
mov bh,1 ;print line init
L208:
mov dx,0
mov ax,es:[di]
call itoa
;init print registers
mov dh,bh ; line start from 1
mov dl,20 ; column start from 14
mov bl,7 ; color=white/black
call show_str
;update registes
inc bh
add di,16 ; point to next line
loop L208
mov ax,4c00H
int 21H
;convert int to string
;dx:ax int
;ds:si string begin add
;bp:strlen
itoa:
;save
push bx
push cx
push dx
push di
mov bp,0
l1:
mov cx,10
call divdw
inc bp
push cx
sub dx,0
jnz l1
mov cx,ax
jcxz itoa_ok
jmp short l1
itoa_ok:
mov cx,bp ;strlen
;begin pop into ds:si
mov di,si
l2:
pop ax
add ax,30h
mov [di],al
inc di
loop l2
mov al,0
mov [di],al ;last 0 added
pop di
pop dx
pop cx
pop bx
ret
;show string
;dh:line(0-24) dl:column(0,79),bl:color ds:si string start addr
;es:bx->0b800:offset
show_str:
;save registers
push si
push cx
push ax
push es
push bx
push dx
push bx ;save color
;init es
mov ax,0b800h
mov es,ax
;calc display memory offset according to line and columm
mov al,dh
mov cl,160
mul cl; 160 bytes per line
mov dh,0
add ax,dx ;offset = 160*line + 2*column
add ax,dx
mov bx,ax
pop ax ;restore color
mov ah,al
l:
;string end?
mov cl,[si]
mov ch,0
jcxz ok
;begin write
mov al,cl
mov es:[bx],al
;write color
mov es:[bx+1],ah
;update indexs
inc bx
inc bx
inc si
jmp short l
ok:
;recover registers
pop dx
pop bx
pop es
pop ax
pop cx
pop si
ret
;被除數 dx:ax 除數 cx 商 dx:ax 餘數 cx
divdw:
;save
push bx
push si
;calc dx/cx
;save ax->bx
mov bx,ax
mov ax,dx
mov dx,0
div cx
;save 商->si
mov si,ax
;calc (餘數+低16位)除法
mov ax,bx
div cx
;
mov cx,dx
mov dx,si
pop si
pop bx
ret
codesg ends
end start