《汇编语言》- 读书笔记 - 第8章-实验 7 寻址方式在结构化数据访问中的应用
实验 7 寻址方式在结构化数据访问中的应用
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
end
看这意思,公司所有收入都给雇员平分了呗?666
ds
存 data 的段地址。
bx
作为年份
、收入
共用的偏移量,每次需递增 4 字节。因为它两都占32位
idata
作为 data 段中各数据项:年份、收、雇员数、人均收(列)的偏移量,直接写死,见代码。
[si]
作为雇员人数偏移量,每次需递增 2 字节
es
存 table 的段地址。
[di]
作为 table
行的偏移量。定位表中的第N行。每次需递增 16 字节。
idata
表格中的列偏移也直接写死。
书中说可用 [bx].idata
和[bx].idata[si]
寻址方式。但是我看着别扭没用。
解
完整代码
assume cs:code, ds:data, es:table
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 个字符串
; db 字节。每个字符占1字节(8位)。每个年份占4个字符,共 4 字节(32位)。
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 型数据
; dd 双字。每个收入占 4 字节(32位)。
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
code segment
start:
mov ax, data ; 设置 data 段地址,DS 指向 data
mov ds, ax
mov ax, table ; 设置 data 段地址,ES 指向 table
mov es, ax
; 初始化偏移量
mov bx, 0 ; 年份(db*2)、收入(dd*1),每次需递增 4 字节,共用偏移量
mov si, 0 ; 雇员人数偏移量,每次需递增 2 字节
mov di, 0 ; table 行偏移量,每次需递增 16 字节
mov cx, 21 ; 循环 21 次
s:
mov ax, data
; 复制年份(每个年份 = 4字节) 【data 里年份的偏移量 0】
mov ax,[bx+0] ; 将 ds:[bx+0] 的值装进 ax
mov es:[di+0], ax ; ax 写入 table 第 di 行,偏移量 0
mov ax,[bx+2]
mov es:[di+2], ax
mov al, ' '
mov es:[di+4], al ; 将空格写入第4列
; 复制收入(每个收入 = bx = 4字节) 【data 到收入之间的偏移量 84】
mov ax,[bx+84]
mov es:[di+5], ax
mov ax,[bx+86]
mov es:[di+7], ax
mov al, ' '
mov es:[di+9], al ; 将空格写入第9列
; 复制雇员数(每个雇员数 = si = 2字节)【data到雇员数之间的偏移量 168】
mov ax, [si+168]
mov es:[di+10], ax
mov al, ' '
mov es:[di+12], al ; 将空格写入第12列
; 计算人均收入(2字节)
mov ax,[bx+84] ; 读取低 16 位存入 ax 中
mov dx,[bx+86] ; 读取高 16 位存入 dx 中
div word ptr [si+168]
mov es:[di+13], ax
mov al, ' '
mov es:[di+15], al ; 将空格写入第15列
; 本轮循环结束,更新偏移量
add bx, 4 ; 年份、收入每个 4 字节
add si, 2 ; 雇员人数每个 2 字节
add di, 16 ; table 每行 16 字节
loop s
mov ax, 4c00H ; 退出程序
int 21H
code ends
end start
查看结果
g 077A: 6F
执行到int 21H
这句。也就是执行完整个程序。但是先别退出。077A: 6F
是怎么找出来的?
2.1.077A
是上面先用u
查看了一次找到的table
段位置 。
2.2.6F
是多次用u cs:偏移
试出来的。d 077A:0 14F
查看table
所在这段内存。结果如上图。