汇编语言实验七

时间:2022-04-13 01:10:34

已知 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