已知 data 段:
assume cs:codesg 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个字符串 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型数据 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型数据 data ends table segment db 21 dup ('year summ ne ??') table ends
编程,将 data 段中的数据按如下格式写入到 table 段中,并计算 21 年中的人均收入(取整),结果也按照下面的格式保存在 table 段中。
代码和分析如下:
# 思考两个问题: 1. 要处理的数据在什么地方?(数据源在 data 段中; 数据目的在 table 段中) 2. 要处理的数据有多长? # # 将 data 段中的数据看作多个数组; table 段中的数据看作一个数组,数组的每一个元素是一个结构体 # # 对 data 段中的数据进行**重排**, 成一个结构体的数组, 只需循环 21 次, 每次完成一个数组结构体元素的赋值 # # [bx].idata[di] 用来定位 table 段 ; [bp + si] 用来定位 data 段 # # 1. 初始化操作: # # 1)取得data段和table的段的起始地址,分别用 ds:si 和 es:di 指向 # 2)初始化cx的值为21,也就是循环次数为21 # 3)引入bx,控制si的增量保持为4。原因:雇员和人均收入记录中的每个数据项长度是2,而其它每个数据项的 # 长度均为4,为了能在一个循环中进行操作,必须使得他们的增量保持一致 # 4)入口地址:标号next: # # 2. 循环体 # # 1)移动年份数据 # 2)移动总收入数据 # 3)sub si,bx # 4)移动雇员数据 # 5)进行除法操作求出人均收入,并移动人均收入 # # 3. 参数修改 # # 1)si增加4,用si指向每个数据项 # 2)di增加16,用di指向每行 # 3)bx增加2,与sub si,bx配合控制雇员和人均收入两个数据在data段中的位置 # # 4. 循环控制 # loop next # # 5. 程序返回 # mov ah,4ch # int 21h assume cs:codesg 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个字符串 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型数据 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型数据data ends data ends table segment db 21 dup ('year summ ne ?? ') table ends codesg segment start: mov ax,data mov ds,ax mov ax,table mov es,ax ;将源数据和目的数据的段地址记录在段寄存器中 sub si,si sub di,di ;分别存放两个数据段的偏移地址, 初始值是 0 mov cx,21 sub bx,bx ;这里引入bx是为了很好的控制一次循环过后 si 的增量保持在 4 # 下面移动年份数据, 一次循环需要移动 4 个字节 next: mov ax , ds:[si] mov es:di , ax ;先移动头 2 个字节 mov ax , ds:[si+2] mov es:[di+2] , ax ;再移动后 2 个字节 mov byte ptr es:[di+4] , 20h ;向目的地的年份数据后面放一个空格(大小为一个字节) # 下面移动收入数据, 一次循环需要移动 4 个字节 mov ax , ds:[si+84] mov es:[di+5] , ax ;先移动头 2 个字节 mov ax , ds:[si+86] mov es:[di+7] , ax ;再移动后 2 个字节 mov byte ptr es:[di+9] , 20h ;向目的地的收入数据后面放一个空格(大小为一个字节) # 下面移动雇员数据, 一次循环需要移动 2 个字节 sub si , bx ;bx 用来补齐 mov ax , ds:[si+168] mov es:[di+10] , ax ;先移动头 2 个字节 add si , bx ;还原 si mov byte ptr es:[di+12] , 20h ;向目的地的雇员数据后面放一个空格(大小为一个字节) # 计算平均收入数据 mov dx , ds:[si+86] ; 移动被除数高 16 bit mov ax , ds:[si+84] ; 移动被除数低 16 bit div word ptr es:[di+10] ; 进行除法操作求出人均收入 mov es:[di+13],ax ; ax默认存储商, bx默认存储余数 mov byte ptr es:[di+15],20h add si , 4 add di , 16 ; si-> 0 4 8 12 add bx , 2 ; 如果不加 2 的话, 会遗漏数据--> ; bx-> 0 2 4 6 8 10 12 loop next ; 3 7 9 13 28 38 130 mov ah , 4ch int 21h codesg ends end start