题目如下:
题目.png "QUESTION"

给出的程序框架如下:

assume cs:code
data segment
        db '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984','1985'
        db '1986','1987','1988','1989','1990','1991','1992','1993','1994','1995'
 
        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514,345980
        dd 590827,803530,1183000,1843000,2758000,3753000,4649000,5937000
 
        dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
        dw 11542,14430,15257,17800
data ends

table segment
        db 21 dup ('year summ ne ?? ')
table ends

大体思路

我们要合理规划好data段中的数据,并设置好方便的访问手段
下面是对单行数据的操作过程:

首先是对数据段的划分,偏移0即年份,偏移84即收入,偏移168即人数。
然后就是对数据的转存,因为内存中的数据无法直接转存到另一个内存,这里使用通用寄存器ax来充当中介作用。
然后注意除法的使用细则,为了将就后面稍大的数据,这里使用32位除法,使用dx保存高位数据,ax保存低位数据
由于寄存器不够用,所以是先进行了除法操作,这样ax寄存器又可以空闲出来,方便转存人数。
                mov bx, 0       ;年份
                mov si, 84      ;收入
                mov bp, 168     ;人数

                mov ax, word ptr [bx]
                mov es:[bx], ax
                mov ax, word ptr [bx+2]
                mov es:[bx+2], ax       ;设置年份

                mov ax, [si+2]          
                mov es:[bx+7], ax       ;设置收入
                mov dx, ax              ;高位置dx
                mov ax, [si]            ;低位置ax
                mov es:[bx+5], ax

                div word ptr [bp]       ;32位除法

                mov es:[bx+13], ax     ;保存取整结果

                mov ax, word ptr [bp]       
                mov es:[bx+10], ax     ;保存人数到表

根据这个思路,构建出整个程序:

这里,我在debug的时候,出现使用g语句卡死的情况,后面发现是语句逻辑问题,所以呀,要对语句字字斟酌,🤡
assume cs:code ds:data es:table
data segment
        db '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984','1985'
        db '1986','1987','1988','1989','1990','1991','1992','1993','1994','1995'
 
        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514,345980
        dd 590827,803530,1183000,1843000,2758000,3753000,4649000,5937000
 
        dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
        dw 11542,14430,15257,17800
data ends

table segment
        db 21 dup ('year summ ne ?? ')
table ends

code segment
        start:  mov ax, data
                mov ds, ax      ;数据段

                mov ax, table
                mov es, ax      ;目标地址

                mov cx, 21      ;总循环次数
                mov bx, 0
                mov si, 0
                mov di, 0       ;记录数据段偏移量

input:          mov ax, word ptr [di]
                mov es:[bx], ax
                mov ax, word ptr [di+2]
                mov es:[bx+2], ax       ;设置年份

                mov ax, [84+di+2]          
                mov es:[bx+7], ax       ;设置收入
                mov dx, ax              ;高位置dx
                mov ax, [84+di]         ;低位置ax
                mov es:[bx+5], ax

                div word ptr [168+di]           ;32位除法

                mov es:[bx+13], ax              ;保存取整结果

                mov ax, word ptr [168+di]       
                mov es:[bx+10], ax              ;保存人数到表
                
                add di, 4
                add si, 2
                add bx, 16
                loop input

                mov ax, 4c00h
                int 21h

code ends

        end start

QQ截图20230310191904.png

优化程序

  • 在上面的程序中,我们是没有使用栈的,栈一次可以处理俩字节数据,但实际上我们使用栈可以节省出一部分寄存器
  • 然后就是对语句的优化,增加可阅读性

    assume cs:code ds:data es:table ss:stack
    data segment
          db '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984','1985'
          db '1986','1987','1988','1989','1990','1991','1992','1993','1994','1995'
     
          dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514,345980
          dd 590827,803530,1183000,1843000,2758000,3753000,4649000,5937000
     
          dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
          dw 11542,14430,15257,17800
    data ends
    
    table segment
          db 21 dup ('year summ ne ?? ')
    table ends
    
    stack segment stack
          db 16 dup (0)
    stack ends
    
    code segment
          start:  mov ax, data
                  mov ds, ax      ;数据从哪来
    
                  mov ax, table
                  mov es, ax      ;数据到哪去
    
                  mov ax, stack
                  mov ss, ax
                  mov sp, 10h
    
                  mov cx, 21      ;总循环次数
                  mov bx, 0
                  mov si, 0
                  mov di, 0       ;记录数据段偏移量
    
    input:          push [di]
                  pop es:0[bx]
                  push [di+2]
                  pop es:2[bx]            ;设置年份
    
                  mov ax, [21*4+di]
                  push ax
                  pop es:5[bx]
                  mov dx, [21*4+di+2]
                  push dx
                  pop es:7[bx]            ;设置收入
    
                  push [21*4*2+si]       
                  pop es:0ah[bx]                  ;设置人数
    
                  div word ptr [21*4*2+si]        ;32位除法
    
                  mov es:0dh[bx], ax              ;保存取整结果
                  
                  add di, 4
                  add si, 2
                  add bx, 16
                  loop input
    
                  mov ax, 4c00h
                  int 21h
    
    code ends
    
          end start