tsembrace 发表于 2011-8-18 11:25:18

课程设计一

断断续续做完,各位如果有时间的话,帮忙看下,提提建议。

assume cs:codesg

stack segment
dw 0,0,0,0,0,0,0,0
stack ends

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个年份的字符串

dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
    ;以上为21年公司收入数据

dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635
dw 8226,11542,14430,15257,17800
    ;以上为21年公司员工人数

dw 21 dup (0)   ;预设21个人均年创收数存储区
data ends


table segment
db 21 dup (0,0,0,0,0,0,0,0)   ;预设年份字符存储区,每个占8字节
db 21 dup (0,0,0,0,0,0,0,0)   ;预设年收入字符存储区,每个占8字节
db 21 dup (0,0,0,0,0,0,0,0)   ;预设员工数量字符存储区,每个占8字节
db 21 dup (0,0,0,0,0,0,0,0)   ;预设人均年创收字符存储区,每个占8字节
table ends
    ;预设转为字符的数据存储区

codesg segment
start:
;step1求出人均年创收存入data预设存储区------------------start
          mov ax,data
          mov ds,ax
          mov bx,0
          mov si,84            ;被除数指针
          mov di,168         ;除数指针
          mov bp,210         ;结果指针
          mov cx,21
s11:
          mov ax,ds:    ;被除数低16位
          mov dx,ds:;被除数高16位
          div word ptr ds:;除数,结果在ax中
          mov ds:,ax      ;结果存入指定区域
          add si,4
          add di,2
          add bp,2
          loop s11
;step1--------------------------------------------------ends

;step2将data段数据转成字符型存入table区----------------------------------------start
;step2.1将data段中年份数据存入table区-----------------start
          mov ax,table
          mov es,ax
          mov bx,0
          mov bp,0
          mov si,0
          mov di,0
          mov cx,21
s211:
          mov dx,ds:
          mov es:,dx
          mov dx,ds:
          mov es:,dx
          mov word ptr es:,0
          mov word ptr es:,0
          add si,4
          add di,8
          loop s211
;step2.1----------------------------------------------ends

;step2.2将data段中收入数据转成字符然后存入table区-----------------start
          mov si,84   ;原数据存储区基址,指针
          mov bp,168   ;目标存储区基址
          mov cx,21

s221:   
          push cx       ;保护循环数
          mov di,0      ;目标存储区指针
          mov bx,0      ;计位器
          mov ax,ds:
          mov dx,ds:
s222:
          inc bx
          call divdw    ;商在dx-ax中,余数在cx中
          push cx       ;余数入栈
          mov cx,ax
          jcxz ok221    ;若ax为0,则跳转继续判断dx是否为0
          jmp short s222 ;ax不为0,即商不为0,继续求余
ok221:
          mov cx,dx
          jcxz ok222    ;若dx为0,则整个商为0,跳转至取出源数据各位转成字符
          jmp short s222 ;dx不为0,即商不为0,继续求余

ok222:   
          mov cx,bx   ;计位器数值作循环次数
s223:
          pop ax
          add al,30h
          mov es:,al
          inc di
          loop s223
          add bp,8      ;目标区基址+8指向下一字符串首地址
          add si,4      ;源数据区指针指向下一数据
          pop cx
          loop s221
;step2.2----------------------------------------------------------ends

;step2.3将data段中员工数量数据转成字符然后存入table区-----------------start
          mov si,168   ;原数据存储区基址,指针
          mov bp,336   ;目标存储区基址
          mov cx,21

s231:   
          push cx       ;保护循环数
          mov di,0      ;目标存储区指针
          mov bx,0      ;计位器
          mov ax,ds:
s232:
          inc bx
          call divw    ;商在ax中,余数在cx中
          push cx       ;余数入栈
          mov cx,ax
          jcxz ok231    ;若ax为0,则整个商为0,跳转至取出源数据各位转成字符
          jmp short s232 ;ax不为0,即商不为0,继续求余
ok231:
          mov cx,bx   ;计位器数值作循环次数
s233:
          pop ax
          add al,30h
          mov es:,al
          inc di
          loop s233
          add bp,8      ;目标区基址+8指向下一字符串首地址
          add si,2      ;源数据区指针指向下一数据
          pop cx
          loop s231
;step2.3--------------------------------------------------------------ends

;step2.4将data段中人均年创收数据转成字符然后存入table区---------------start
          mov si,210   ;原数据存储区基址,指针
          mov bp,504   ;目标存储区基址
          mov cx,21

s241:   
          push cx       ;保护循环数
          mov di,0      ;目标存储区指针
          mov bx,0      ;计位器
          mov ax,ds:
s242:
          inc bx
          call divw    ;商在ax中,余数在cx中
          push cx       ;余数入栈
          mov cx,ax
          jcxz ok241    ;若ax为0,则整个商为0,跳转至取出源数据各位转成字符
          jmp short s242 ;ax不为0,即商不为0,继续求余
ok241:
          mov cx,bx   ;计位器数值作循环次数
s243:
          pop ax
          add al,30h
          mov es:,al
          inc di
          loop s243
          add bp,8      ;目标区基址+8指向下一字符串首地址
          add si,2      ;源数据区指针指向下一数据
          pop cx
          loop s241
;step2.4--------------------------------------------------------------ends
;step2-------------------------------------------------------------------------ends

;step3将table区字符按格式显示在屏幕上----------------------------start
          mov ax,table
          mov ds,ax
          mov bx,0
          mov si,0
          mov dl,3
          mov dh,3
          mov al,2
          mov cx,4
s31:
          push cx      ;保护外循环次数
          mov cx,21
s32:
          call showdata
          mov si,0
          mov di,0      ;指针置0返回
          add bx,8       ;指向同区下一串字符
          inc dl          ;指向显示的下一行
          loop s32
          mov dl,3      ;设置下一区显示的起始行
          add dh,8      ;设置下一区显示的起始列

          pop cx
          loop s31
;step3-----------------------------------------------------------ends   


      mov ax,4c00H
      int 21h

;----------子程序1-------------start
;name:divdw.
;function:dword型数据除以10求余运算.
;input:商高16位dx,商低16位ax,除数=10.
;return:结果为dword型数据,高16位dx,低16位ax,余数cx.

divdw:
          push bx       ;保护
          push ax
          mov ax,dx
          mov dx,0
          mov bx,10
          div bx
          mov cx,ax   ;暂存商高16位保存进cx
          pop ax
          push cx       ;商高16位入栈
          div bx      ;商为ax,即最终商的低16位
          mov cx,dx   ;余数赋给cx
          pop dx      ;取出商高16位
          pop bx      ;恢复现场
          ret
;----------子程序1-------------ends

;----------子程序2-------------start
;name:divw.
;function:word型数据除以10求余运算.
;input:商ax,除数=10.
;return:结果为word型数据ax,余数cx.
divw:
          push bx
          push dx       ;保护
          push ax
          mov al,ah
          mov ah,0
          mov dx,10
          div dl
          mov bl,al   ;保存商高8位进bl
          mov bh,ah   ;保存本次余数进bh
          pop ax
          mov ah,bh
          div dl      ;商为al,即最终商的低8位
          mov cx,0
          mov cl,ah   ;余数赋给cx
          mov ah,bl   ;取出商高8位
          pop dx
          pop bx      ;恢复现场

      ret
;----------子程序2-------------ends

;----------子程序3-------------start
;----------子程序3-------------start
;name:showdata
;function:将指定内存区8位字符串显示在屏幕指定位置
;input:(ds:bx+si)=字符串首地址,(es:bp+di)=显示区首地址;(dl)=起始显示行序号,(dh)=起始显示列序号,(al)=字符属性
;return:无

showdata:
          push cx      ;保护现场
          push dx      ;保护行列
          push ax      ;保护字符属性
          mov ax,0b800h
          mov es,ax
          mov bp,0
          mov di,0
          mov al,160
          mul dl
          add bp,ax
          add dh,dh
          mov ah,0
          mov al,dh
          add bp,ax   ;确定显示区基址
          pop ax      ;取出字符属性
          mov cx,8
sf31:
          mov ah,ds:
          mov es:,ah   ;写入字符值
          inc di
          mov es:,al   ;写入字符属性
          inc si
          inc di
          loop sf31
          pop dx          ;取出初始行列
          pop cx          ;恢复现场      
          ret
;----------子程序3-------------ends
;----------子程序3-------------ends
          codesg ends
          end start            

几个注意点和感受:
1、调用divdw子程序时候,判定商为0,须高低位同时为0;
2、数据段如何预设才最合理,最省事?
3、寄存器的使用,感觉不够用,push来pop去很饶人。。
4、显示子程序提供的是只显示一串8位字符的功能;调用很方便,但在主程序中的循环和进入下循环预设条件上有些头大。




页: [1]
查看完整版本: 课程设计一