寻址方式在结构化数据访问中的应用
题目如下:
给出的程序框架如下:
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
优化程序
- 在上面的程序中,我们是没有使用栈的,栈一次可以处理俩字节数据,但实际上我们使用栈可以节省出一部分寄存器
然后就是对语句的优化,增加可阅读性
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