第十章课程设计1____源码————————
本帖最后由 decoder 于 2014-5-24 19:55 编辑assume 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'
dd 16,22,382,1356,2390,8000,16000,24486,50065,97478,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1422,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
data ends
buff_mem segment
db 1280 dup(0) ;48个字节储存一行数据,共使用1008个字节为了内存对齐申请1280字节内存空间
buff_mem ends
;es:21年循环变量 3f0h3f0h
;es:年数据最低位 3f2h3f2h
;es:年数据次低位 3f3h3f3h
;es:年数据次高位 3f4h3f4h
;es:年数据最高位 3f5h3f5h
;es:除数 3f6h 3f6h
;es:四位十六进制数除法的低位商 3f8h 3f8h
;es:四位十六进制除法的 余数 3fah 3fah
;es: ds:中bx的值 3fch 3fch
;es:保存bp的值 3f8h3feh
;es:保存di的值 0400h
;ds:保存字符处理循环中的临时cx变量
;ds:保存显示函数中的di
code segment
start: call get_data
call process_data ;0014
call display_data
mov ax,4c00h
int 21h
get_data: mov ax,data
mov ds,ax
ret
process_data: ;ip=0014
;初始化
mov ax,buff_mem ;es指向buff_memes=0b5e
mov es,ax
mov bx,0
mov si,84 ;数据偏移到收入地址
mov bp,0
mov di,48 ;行递增数据,初始化为距左边4字节
mov cx,21
_loop_21_: push cx ;保存21年的循环
mov es:,di ;保存21年循环中di的当前值
mov es:,bp
call covent_year ;年份 ip=0086
call covent_summ ;资产 ip=00a3
call covent_ne ;人数 ip=00e0
call covent_pcdi ;人均收入
pop cx
dec cx
jcxz _l_21_out
add bp,4
add di,2ch
add word ptr es:,4 ;bx镜像递增
mov bx,es:
jmp _loop_21_
_l_21_out:ret
display_data:
mov ax,0b80ah
mov es,ax
mov ax,buff_mem
mov ds,ax
mov bx,0
mov si,0
mov bp,0
mov di,20h
mov cx,21
b:push cx
push di ;用来定位要显示字符的位置
push bx ;用来定位要载入字符的位置
mov ds:,di ;定位年列的位置
mov cx,4
get_year: push cx ;年份字符串的循环处理
mov cx,ds: ;取得年份字符的
mov es:,cx
pop cx
add bx,2
add di,2
loop get_year
add di,16
mov cx,8
mov ax,0
add word ptr ds:,16 ;定位资产列的位置
mov di,ds:
_get_summ: push cx ;资产字符串的循环处理
mov cx,ds:
jcxz _summ_eq0 ;判断字符是否为空,在48字节的段中去掉空格存入显存
mov es:,cx
add di,2
_summ_eq0: add ax,2
add bx,2
pop cx
loop _get_summ
add di,16
mov cx,8
sub di,ax
add di,16
add word ptr ds:,20;定位人员列的位置
mov di,ds:
get_ne: push cx
mov cx,ds: ;取得人员的字符
jcxz _cx_ne_eq_0;判断字符是否为空,在48字节的段中去掉空格存入显存
mov es:,cx
add di,2
_cx_ne_eq_0: add ax,2
add bx,2
pop cx
loop get_ne
add di,16
mov cx,4
sub di,ax
add di,32
add word ptr ds:,16;定位人均收入列的位置
mov di,ds:
get_sr: push cx
mov cx,ds: ;取得人均收入位置的字符
jcxz _cx_sr_eq_0 ;判断字符是否为空,在48字节的段中去掉空格存入显存
mov es:,cx
add di,2
_cx_sr_eq_0:add ax,2
add bx,2
pop cx
loop get_sr
add di,16
pop bx
pop di
add di,0a0h
add bx,48
pop cx
dec cx
jcxz dp_out
jmp b ;此处原本用loop循环,但循环溢出,只能使用jmp段内转移
dp_out: ret
covent_year: push bx ;ip=0086 年份字符串处理
push si
push bp
push di
mov cx,4
_loop_str: mov al,byte ptr ds:;年的单位字节数据
mov byte ptr es:,al
mov byte ptr es:,07h
inc bx
add bp,2
loop _loop_str
pop di
pop bp
pop si
pop bx
ret
covent_summ: push bx ;ip=00a3资产字符串处理
push si
push bp
push di
mov ax,word ptr ds:
mov dx,word ptr ds:
mov word ptr es:,10
_div_loop: call divdw ;cx为余数,ax为商
mov word ptr es:,cx ;余数用来做显示位
add word ptr es:,30h;转换成字符
mov ax,word ptr es: ;字符放入ax
mov ah,07h ;把ah变成颜色位
mov word ptr es:,ax ;保存入显示缓冲中
mov ax,word ptr es: ;低位商
mov cx,ax
jcxz _div_out ;只要低位商为零就跳出
sub bp,2 ;从后往前放资产值
jmp _div_loop
_div_out: pop di
pop bp
pop si
pop bx
ret
covent_ne: push bx ;ip=00e0 人员字符串处理
push si
push bp
push di
push word ptr es:
mov cx,es: ;被保存的bx的值??????
mov ax,cx
jcxz _init_data ;检测第一次循环bx是否为零,若为零则跳过-2步骤
mov dx,0
mov cx,2
div cx ;4/2,8/2,12/2,16/2....
mov bx,ax ;2,4,6,8....
_init_data: mov ax,ds: ;ax的值是ne部分
mov dx,0 ;因为都是求余数,并且人数不会超过32位
_divw_loop: call divdw
mov word ptr es:,cx ;余数用来做显示位
add word ptr es:,30h;转换成字符
mov ax,word ptr es: ;放入ax
mov ah,07h ;把ah变成颜色位
mov word ptr es:,ax ;保存入显示缓冲中32-8-20
mov ax,word ptr es: ;低位商
mov dx,0
mov cx,ax
jcxz _divw_out ;只要低位商为零就跳出
sub bp,2 ;从右到左(从小到大)写数据
jmp _divw_loop
_divw_out: pop word ptr es:
pop di
pop bp
pop si
pop bx
ret
covent_pcdi: ;ip=013b人均收入字符串处理
push bx ;ip=00e0 人员字符串处理
push si
push bp
push di
push word ptr es:
mov ax,word ptr ds: ;把资产低位当作被除数
mov dx,word ptr ds: ;把资产高位当作被除数
push ax ;此处注意保存ax和dx的值
push dx
mov cx,es: ;被保存的bx的值??????
mov ax,cx
jcxz _init_ne_data ;检测第一次循环bx是否为零,若为零则跳过-2步骤
mov dx,0
mov cx,2
div cx ;4/2,8/2,12/2,16/2....
mov bx,ax ;2,4,6,8....
_init_ne_data: pop dx ;还原dx和ax的值
pop ax
mov cx,ds:
mov word ptr es:,cx ;把人数当作除数
call divdw
mov word ptr es:,ax ;商用来做人均收入的被除数
mov word ptr es:,10 ;循环中的除数,意思是缩小十倍
mov dx,0
pcdi_: call divdw
mov word ptr es:,cx ;余数用来做显示位
add word ptr es:,30h;转换成字符
mov ax,word ptr es: ;字符放入ax
mov ah,07h ;把ah变成颜色位
mov word ptr es:,ax;保存入显示缓冲中
mov ax,word ptr es: ;低位商
mov cx,ax
jcxz pcdi_out ;只要低位商为零就跳出
sub bp,2 ;从后往前放资产值
jmp pcdi_
pcdi_out: pop word ptr es:
pop di
pop bp
pop si
pop bx
ret
divdw:
push ax ip= 0175h
mov ax,dx
mov dx,0
div word ptr es: ;ax=ax/【x】 高位商dx=ax/cx高位余如果高位为零,则全为零
mov bx,ax ;bx=ax 如果高位被除为零则取ES:的值为商
pop ax ;ax=低位被除数 dx=在进行高位除法时作为高位被除数,低位时为余数(隐含高位被除数)
div word ptr es: ;dx:ax= 14240/ cx= 0f
mov es:,ax ;保存低位除法的商
mov cx,dx;将余数保存在cx
mov dx,bx;将商保存在dx(高位商)
ret
code ends
end start
碉堡了。。。。。 楼主可有divdw 的解释?那里我不理解。 高16位 低16位怎么算出原数的商和余数。有推导么?
而且还是16进制的。搞不懂。跪求啊!!! 传说。 发表于 2014-5-25 01:34
楼主可有divdw 的解释?那里我不理解。 高16位 低16位怎么算出原数的商和余数。有推导么?
而且还是16进制 ...
书里后面有公式证明 在附注5 15岁的小朋友 发表于 2014-5-25 09:41 static/image/common/back.gif
书里后面有公式证明 在附注5
此楼正解 哎,没啥话可说非得要我补齐十个字啊?又不是灌水
页:
[1]