7.20 王爽汇编语言(十七)
实验 7 寻址方式在结构化数据访问中的应用
做这道题之前先复习一下有几个寄存器可以使用:
ax:
通常用来临时保存段地址或其他数据
cx:
通常用来保存循环次数
dx:
在 div 除法指令中应用的时候,用来存放 32 被除数的高 16 位
bx、si、di、bp:
4个寄存器通常用来进行内存单元的寻址,存放偏移地址;其中它们可以组合应用;
ss:
通常用来存放栈顶段地址;
sp:
通常用来存放栈顶偏移地址;
ds:
通常用来存放数据的段地址;
es:
和 ds 寄存器功能相近,即用来存放数据的段地址;
ip:
用来存放代码段的偏移地址;
另外还要复习一下内存单元寻址的几种书写方式:书中寻址方式小结在:P164
另外题中还用到了 div 除法指令,并且被除数是 32 位,所以也复习一下:
# 参考 P169
除数:有 8 位和 16 位两种,在一个 reg 或内存单元中
被除数:默认存放在 AX 或 (DX 和 AX)中,如果除数为 16 位,被除数则为 32 位,在DX
和 AX 中存放,DX 存放高 16 位,AX 存放低 16 位;
结果:如果除数为 16 位,则 AX 存放除法操作的商,DX 存放除法操作的余数;
第一版自己写的程序如下(明天优化)
assume cs: codesg, ds: data, ss: stacksg
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
stacksg segment
; 以下 dup 指令等价于:dw 0, 0, 0, 0, 0, 0, 0, 0
dw 8 dup (0)
stacksg ends
codesg segment
start:
mov ax, data
mov ds, ax
mov bx, 0
mov si, 0
mov ax, table
mov es, ax
mov bp, 0
mov di, 0
mov cx, 21
; 将年份移动到 table 段中
s0:
push cx
mov cx, 2
s00:
mov ax, [bx][si]
mov es:[bp][di], ax
add si, 2
add di, 2
loop s00
add di, 12
pop cx
loop s0
; 接下来将每年的收入移动到 table 段中
mov bx, 84
mov si, 0
mov bp, 0
mov di, 5
mov cx, 21
s1:
mov ax, [bx + si]
mov es:[bp + di], ax
mov ax, [bx + si + 2]
mov es:[bp + di + 2], ax
add bx, 4
add bp, 16
loop s1
; 接下来将雇员数移动到 table 段中,也是类似的做法
mov bx, 168
mov bp, 0
mov di, 10
mov cx, 21
s2:
mov ax, [bx]
mov es:[bp + 10], ax
add bp, 16
add bx, 2
loop s2
; 接下来计算每年的人均收入,然后将人均收入移动到 table 段中,会用到 div 除法指令
; 人均收入 = 一年总收入 / 雇员数(我们这里只取商作为人均收入,余数不要)
mov bp, 0
mov si, 10 ; 用于定位收入偏移地址(即被除数)
mov di, 5 ; 用于定位雇员偏移地址(即除数)
mov cx, 21
s3:
mov ax, es:[bp + di] ; 获取收入的低 16 位保存到 AX 寄存器
mov dx, es:[bp + di + 2] ; 获取收入的高 16 位保存到 DX 寄存器
div word ptr es:[bp + si] ; 将 dx:ax 中的 32 位被除数除以 es:[bp + si] 字单元中的数据
mov es:[bp + si + 3], ax ; 将商保存到人均收入的位置
add bp, 16
loop s3
mov ax, 4c00h
int 21h
codesg ends
end start
总结
不知不觉,已经把 13 个寄存器都用了一遍~ 技能这种东西,熟练只是时间问题罢了~ 还没做完,明天再做;
# 2022.4.25
# 今天把初步第一版程序写出来了,不过得优化