assume ds:data,ss:stack,cs:code
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个字符串 4*21=84byte [0]-[83]
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型数据 4*21=84byte [84]-[167]
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型数据 2*21=42byte [168]-[209]
;以下是临时空间[210]~[219]
db 10 dup(0)
data ends
stack segment
db 32 dup(0)
stack ends
code segment
start:
;=====initial=====
;ds:[si]=>temp space
;es:[di]=>data
mov ax,data
mov ds,ax
mov es,ax
mov si,210
mov di,0
mov ax,stack
mov ss,ax
mov sp,32
;=====print a line=====
mov cx,21 ;循环次数
mov bp,0 ;计次=>计算di用
pal:
push cx
;=====show col1=====
;di定位至需要取的数据
mov ax,bp
mov bl,4
mul bl
mov di,ax
;转移数据
mov si,210
push es:[di]
pop ds:[si]
push es:[di+2]
pop ds:[si+2]
mov byte ptr ds:[si+4],0
;设置显示行列
mov ax,bp
inc al
add ah,15
mov dh,al
mov dl,ah
mov cl,00000111b
mov si,210
call show_str
;=====show col2=====
mov ax,bp
mov bl,4
mul bl
mov di,ax
add di,84
mov ax,es:[di]
mov dx,es:[di+2]
mov si,210
call dtoc
mov ax,bp
inc al
add ah,25
mov dh,al
mov dl,ah
mov cl,00000111b
mov si,210
call show_str
;=====show col3=====
mov ax,bp
mov bl,2
mul bl
mov di,ax
add di,168
mov ax,es:[di]
mov dx,0
mov si,210
call dtoc
mov ax,bp
inc al
add ah,35
mov dh,al
mov dl,ah
mov cl,00000111b
mov si,210
call show_str
;=====show col4=====
;除数=>cx
mov cx,es:[di]
;di定位至需要取的数据
mov ax,bp
mov bl,4
mul bl
mov di,ax
add di,84
;被除数=>[dx:ax]
mov ax,es:[di]
mov dx,es:[di+2]
call divdw
mov si,210
call dtoc
mov ax,bp
inc al
add ah,45
mov dh,al
mov dl,ah
mov cl,00000111b
mov si,210
call show_str
;=====print a line=====
inc bp
pop cx
dec cx
jcxz ok
jmp pal
;=====程序结束=====
ok:
mov ax,4c00h
int 21h
;=====显示字符串=====
;func: show a string ended with 0, at specified location in spcfd color
;para: dh: 0-24(row number)
; dl: 0-79(column no.)
; cl: 7 654 3 210
; blink rgb(backgroud) highlight rgb(foreground)
; ds:si=>string.head
;retu:null
show_str:
push ax
push bx
push cx
push dx
push es
push si
push di
mov ax,0b800h
mov es,ax
mov di,0
;计算行偏移
mov al,dh
mov bl,160
mul bl
mov bx,ax
;计算列偏移
mov dh,0
add dx,dx
add bx,dx
mov ah,cl ;显示效果不用每次都放ah,开头放一次即可
mov ch,0 ;每次读取1byte 用于检验是否读到'0',所以ch可以始终为0
show_str_s0:
mov al,ds:[si]
mov es:[bx+di],ax
mov cl,al
inc si
add di,2
jcxz show_str_ok
loop show_str_s0
show_str_ok:
pop di
pop si
pop es
pop dx
pop cx
pop bx
pop ax
ret
;=====不会溢出的除法(32/16bit)=====
;func: [dx:ax]/(cx)=[dx:ax]……(cx)
;para: [dx:ax]=[H:L]
; (cx)=divisor
;retu: [dx:ax]=[H:L]
; (cx)=remainder
divdw:
;bx=unknow_bx=ub
;这里不需要push ax cx dx,因为return时acd的值会变 所以也就不用保留输入时acd的值了
push bx
;ax=L
;ss=L ub ip
push ax
;计算H部分
;dx=0 ax=H
mov ax,dx
mov dx,0 ;清零可以用xor dx,dx 指令占用2byte
div cx ;dx=H.rem ax=H.int
;ax与栈顶数据交换
;ax=L
;ss=H.int ub ip
mov bx,ax
pop ax
push bx
;计算L部分
;dx=H.rem ax=L
div cx ;dx=L.rem ax=L.int
;整理数据
mov cx,dx ;cx=L.rem
pop dx ;dx=H.int
;ss=ub ip
;因为ret=pop ip,所以这里没有正确pop ub会导致不能正确pop ip,因而程序很可能出错,例如无法终止
pop bx
ret
;=====数值显示32bit=====
;func: value(32bit)=>string(dec),ended with 0
;para: [dx:ax]=[H:L]
; ds:si=>string.head
;retu: null
dtoc:
;下面要用到的reg先push
push ax
push bx
push cx
push dx
push si
;cx=除数 bx计算次数
mov bx,0
dtoc_s0:
mov cx,10
call divdw
push cx ;余数push
inc bx
mov cx,ax ;判断商是否=0,=0就跳出
or cx,dx
jcxz dtoc_s1
jmp short dtoc_s0
dtoc_s1:
mov cx,bx ;放入计算出的循环次数
dtoc_s2:
pop ax
add al,30h ;数值+30h=数值的ascii码
mov ds:[si],al
inc si
loop dtoc_s2
mov ds:[si],cl ;string末位+0
pop si
pop dx
pop cx
pop bx
pop ax
ret
code ends
end start