assume cs:code,ds:data,ss:stack
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982'
dd 16,22,382,1356,2390,8000,16000,5937000
dw 3,7,9,13,28,38,130,17800
dw 8 dup(0)
data ends
stack segment
db 32 dup(0)
stack ends
code segment
_start:
mov ax, data
mov ds, ax
mov ax,stack
mov ss,ax
mov sp,32
mov ax, 0b800h
mov es, ax ; ES指向显示缓冲区
mov bx, 0 ; 数据索引(年份数组)
mov bp, 0 ; 显示缓冲区位置(屏幕左上角)
mov dx, 8 ; 循环计数:8个年份
;显示db数据(年份)
year_loop:
mov cx, 4 ; 每个年份4个字符
mov si, 0 ; 字符在年份内的偏移
char_loop:
mov al, ds:[bx+si] ; 读取年份字符
mov es:[bp], al ; 显示字符
mov byte ptr es:[bp+1], 07H ; 属性:黑底白字
add bp, 2 ; 下一个显示位置
inc si
loop char_loop
; 显示8个空格分隔
mov cx, 8
space_loop:
mov byte ptr es:[bp], 20H ; 空格字符
mov byte ptr es:[bp+1], 07H ; 属性
add bp, 2
loop space_loop
; 准备下一次循环
add bx, 4 ; 下一个年份(4字节)
add bp, 136 ; 下一行,计算:160 – (4+8)*2=160-24=136
dec dx
jnz year_loop ; 继续处理下一个年份
;显示dd数据(收入)
mov si,32 ;si指向第一个dd数值的位置
mov bp,24 ;显示位置,年份+空格(4+8)*2=24
dd1:
mov di,0 ;用于计算余数个数
mov ax, ds:[si] ; 被除数低16位
mov dx, ds:[si+2] ; 被除数高16位
mov cx, 000ah ; 除数
dd0:
call show_numToStr
add bx,'0' ;把数值转化为ASCII码值
push bx ;把余数压入栈
inc di ;统计压入栈的个数
add dx,ax
cmp dx,0
jnz dd0
mov cx,di
show_dd:
pop ax
mov es:[bp],al
mov byte ptr es:[bp+1],07H
add bp,2
loop show_dd
mov cx,10
sub cx,di
show_dd_space:
mov byte ptr es:[bp],20H ; 空格字符
mov byte ptr es:[bp+1],07H
add bp,2
loop show_dd_space
add si,4 ;si指向下一个dd数值
add bp, 140 ; 下一行,计算:160 -10*2=140
cmp si,64
jnz dd1
;显示dw数据(雇员数)
mov si,64 ;si指向第一个dw数值的位置
mov bp,44 ;年份+空格(4+8)*2+10*2=44
dw1:
mov di,0 ;用于计算余数个数
mov ax, ds:[si] ; 被除数低16位
mov dx, ds:[si+2] ; 被除数高16位
mov cx, 000ah ; 除数
dw0:
call show_numToStr
add bx,'0' ;把余数的值转化为ASCII码值
push bx ;把余数压入栈
inc di ;统计压入栈的个数
add dx,ax
cmp dx,0
jnz dw0
mov cx,di
show_dw:
pop ax
mov es:[bp],al
mov byte ptr es:[bp+1],07H
add bp,2
loop show_dw
mov cx,10
sub cx,di
show_dw_space:
mov byte ptr es:[bp],20H ; 空格字符
mov byte ptr es:[bp+1],07H
add bp,2
loop show_dw_space
add si,4 ;si指向下一个dw数值
add bp, 140 ; 下一行,计算:160 -10*2=140
cmp si,64
jnz dw1
;显示平均数
mov si,32 ;si指向第一个dd数值的位置
mov word ptr ds:[80],64 ;指向第一个dw数值的位置
mov bp,64 ;年份+空格(4+8)*2+10*2+10*2=64
avg1:
mov ax,ds:[80]
mov cx, ax ; 除数
mov ax, ds:[si] ; 被除数低16位
mov dx, ds:[si+2] ; 被除数高16位
call show_numToStr ;此时dx:ax即为平均数
mov di,0 ;用于计算余数个数
avg0:
mov cx,0ah ;把除数设为10
call show_numToStr
add bx,'0' ;把数值转化为ASCII码值
push bx ;把余数压入栈
inc di ;统计压入栈的个数
add dx,ax
cmp dx,0
jnz avg0
mov cx,di
show_avg:
pop ax
mov es:[bp],al
mov byte ptr es:[bp+1],07H
add bp,2
loop show_avg
mov cx,10
sub cx,di
show_avg_space:
mov byte ptr es:[bp],20H ; 空格字符
mov byte ptr es:[bp+1],07H
add bp,2
loop show_avg_space
add si,4 ;si指向下一个dd数值
mov ax,ds:[80]
add ax,2
mov ds:[80],ax ;ds:[80]的值+2
add bp, 140 ; 下一行,计算:160 -10*2=140
cmp si,64 ;si=64时,表示数据全部读完
jnz avg1
mov ax, 4c00h
int 21h
;以下是防溢出的除法运算子程序
show_numToStr:
push di
push si
;公式:X/N = int(H/N) × 65536 + [rem(H/N) × 65536 + L] / N
;X = 被除数 (32位: DX:AX)
;N = 除数 (16位: CX),
;H = X的高16位 (DX),
;L = X的低16位 (AX)
;int():描述性运算符,取商,比如,int(38/10)=3
;rem():描述性运算符,取余数,比如,rem(38/10)=8
; 第一步:计算 int(H/N),注意不需要显式乘以65536
mov si, ax ; 保存低16位
mov ax, dx ; AX = H (高16位)
mov dx, 0 ; DX = 0,形成32位被除数 0:H
div cx ; AX = 商,DX = 余数
; 第二步:保存 int(H/N) × 65536 的高16位
mov di, ax ; di = int(H/N),这已经是结果的高16位
; 第三步:计算 [rem(H/N) × 65536 + L] / N
mov ax, si ; 恢复低16位 L
; DX 已经是 rem(H/N),与AX形成新的32位被除数 DX:AX
div cx ; AX = 商的低16位,DX = 余数
; 第四步:组合最终结果
; DX = 商的高16位,AX = 商的低16位,bx = 余数
mov bx,dx
mov dx,di
pop si
pop di
ret
code ends
end _start
assume cs:code,ds:data,ss:stack
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982'
dd 16,22,382,1356,2390,8000,16000,5937000
dw 3,7,9,13,28,38,130,17800
dw 8 dup(0)
data ends
stack segment
db 32 dup(0)
stack ends
code segment
_start:
mov ax, data
mov ds, ax
mov ax,stack
mov ss,ax
mov sp,32
mov ax, 0b800h
mov es, ax ; ES指向显示缓冲区
mov bx, 0 ; 数据索引(年份数组)
mov bp, 0 ; 显示缓冲区位置(屏幕左上角)
mov dx, 8 ; 循环计数:8个年份
;显示db数据(年份)
year_loop:
mov cx, 4 ; 每个年份4个字符
mov si, 0 ; 字符在年份内的偏移
char_loop:
mov al, ds:[bx+si] ; 读取年份字符
mov es:[bp], al ; 显示字符
mov byte ptr es:[bp+1], 07H ; 属性:黑底白字
add bp, 2 ; 下一个显示位置
inc si
loop char_loop
; 显示8个空格分隔
mov cx, 8
space_loop:
mov byte ptr es:[bp], 20H ; 空格字符
mov byte ptr es:[bp+1], 07H ; 属性
add bp, 2
loop space_loop
; 准备下一次循环
add bx, 4 ; 下一个年份(4字节)
add bp, 136 ; 下一行,计算:160 - (4+8)*2=160-24=136
dec dx
jnz year_loop ; 继续处理下一个年份
;显示dd数据(收入)
mov si,32 ;si指向第一个dd数值的位置
mov bp,24 ;显示位置,年份+空格(4+8)*2=24
dd1:
mov di,0 ;用于计算余数个数
mov ax, ds:[si] ; 被除数低16位
mov dx, ds:[si+2] ; 被除数高16位
mov cx, 000ah ; 除数
dd0:
call show_numToStr
add bx,'0' ;把数值转化为ASCII码值
push bx ;把余数压入栈
inc di ;统计压入栈的个数
add dx,ax
cmp dx,0
jnz dd0
mov cx,di
show_dd:
pop ax
mov es:[bp],al
mov byte ptr es:[bp+1],07H
add bp,2
loop show_dd
mov cx,10
sub cx,di
show_dd_space:
mov byte ptr es:[bp],20H ; 空格字符
mov byte ptr es:[bp+1],07H
add bp,2
loop show_dd_space
add si,4 ;si指向下一个dd数值
add bp, 140 ; 下一行,计算:160 -10*2=140
cmp si,64
jnz dd1
;显示dw数据(雇员数)
mov si,64 ;si指向第一个dw数值的位置
mov bp,44 ;年份+空格(4+8)*2+10*2=44
dw1:
mov di,0 ;用于计算余数个数
mov ax, ds:[si] ; 被除数低16位
mov dx, ds:[si+2] ; 被除数高16位
mov cx, 000ah ; 除数
dw0:
call show_numToStr
add bx,'0' ;把余数的值转化为ASCII码值
push bx ;把余数压入栈
inc di ;统计压入栈的个数
add dx,ax
cmp dx,0
jnz dw0
mov cx,di
show_dw:
pop ax
mov es:[bp],al
mov byte ptr es:[bp+1],07H
add bp,2
loop show_dw
mov cx,10
sub cx,di
show_dw_space:
mov byte ptr es:[bp],20H ; 空格字符
mov byte ptr es:[bp+1],07H
add bp,2
loop show_dw_space
add si,4 ;si指向下一个dw数值
add bp, 140 ; 下一行,计算:160 -10*2=140
cmp si,64
jnz dw1
;显示平均数
mov si,32 ;si指向第一个dd数值的位置
mov word ptr ds:[80],64 ;指向第一个dw数值的位置
mov bp,64 ;年份+空格(4+8)*2+10*2+10*2=64
avg1:
mov ax,ds:[80]
mov cx, ax ; 除数
mov ax, ds:[si] ; 被除数低16位
mov dx, ds:[si+2] ; 被除数高16位
call show_numToStr ;此时dx:ax即为平均数
mov di,0 ;用于计算余数个数
avg0:
mov cx,0ah ;把除数设为10
call show_numToStr
add bx,'0' ;把数值转化为ASCII码值
push bx ;把余数压入栈
inc di ;统计压入栈的个数
add dx,ax
cmp dx,0
jnz avg0
mov cx,di
show_avg:
pop ax
mov es:[bp],al
mov byte ptr es:[bp+1],07H
add bp,2
loop show_avg
mov cx,10
sub cx,di
show_avg_space:
mov byte ptr es:[bp],20H ; 空格字符
mov byte ptr es:[bp+1],07H
add bp,2
loop show_avg_space
add si,4 ;si指向下一个dd数值
mov ax,ds:[80]
add ax,2
mov ds:[80],ax ;ds:[80]的值+2
add bp, 140 ; 下一行,计算:160 -10*2=140
cmp si,64 ;si=64时,表示数据全部读完
jnz avg1
mov ax, 4c00h
int 21h
;以下是防溢出的除法运算子程序
show_numToStr:
push di
push si
;公式:X/N = int(H/N) × 65536 + [rem(H/N) × 65536 + L] / N
;X = 被除数 (32位: DX:AX)
;N = 除数 (16位: CX),
;H = X的高16位 (DX),
;L = X的低16位 (AX)
;int():描述性运算符,取商,比如,int(38/10)=3
;rem():描述性运算符,取余数,比如,rem(38/10)=8
; 第一步:计算 int(H/N),注意不需要显式乘以65536
mov si, ax ; 保存低16位
mov ax, dx ; AX = H (高16位)
mov dx, 0 ; DX = 0,形成32位被除数 0:H
div cx ; AX = 商,DX = 余数
; 第二步:保存 int(H/N) × 65536 的高16位
mov di, ax ; di = int(H/N),这已经是结果的高16位
; 第三步:计算 [rem(H/N) × 65536 + L] / N
mov ax, si ; 恢复低16位 L
; DX 已经是 rem(H/N),与AX形成新的32位被除数 DX:AX
div cx ; AX = 商的低16位,DX = 余数
; 第四步:组合最终结果
; DX = 商的高16位,AX = 商的低16位,bx = 余数
mov bx,dx
mov dx,di
pop si
pop di
ret
code ends
end _start

















暂无评论内容