汇编语言:寻址方式在结构化数据访问中的应用——计算人均收入

有一年多没有在CSDN上发博文了。人的工作重心总是有转移的,庆幸一直在做着有意义的事。

今天的内容,是为汇编语言课程更新一个实验项目。

本方案修改自王爽编《汇编语言》第4版P172"实验7寻址方式在结构化数据访问中的应用"

【数据描述】

烟园科技公司从2004年成立一直到2023年的基本情况如下。

年份 总收入(万元) 雇员(人) 人均收入(万元)
2004 22 7 ?
2005 382 9 ?
2006 1356 13 ?
2007 2390 28 ?
2008 8000 38 ?
......
2023 5937000 17800 ?

下面的程序中,已经定义好了这些数据:

assume cs:codesg
data segment
    db '2004','2005','2006','2007','2008','2009','2010','2011','2012','2013'
    db '2014','2015','2016','2017','2018','2019','2020','2021','2022','2023'
    ;以上是表示20年的20个字符串
    dd 22,382,1356,2390,8000,16000,24486,50065,97479,140417
    dd 197514,345980,590827,803530,1183000,1843000
    dd 2759000,3753000,4649000,5937000
    ;以上是表示20年公司总收入的20个dword型数据
    dw 7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
    dw 11542,14430,15257,17800
    ;以上是表示20年公司雇员人数的20个word型数据
data ends
table segment
    db 20 dup('year summ ne ??')
table ends`

【任务】

请编程序,将data段中的数据按如下格式整理到table段中,并计算20年中的人均收入(取整),记录到table段的相应位置上。

在table段中,一年的数据占16个字节,各字节分配如下表所示。

说明:与教材中提供的方案相比,每一部分的偏移地址为偶数,是更有效率的解决方案,而预留"保留"空间,既能让每一条记录所点空间保持16的倍数上(这是一个很好的特征),也为系统未来扩充等提供方便。

【提示】

①要做的工作主要是将data段中的数据复制到table段中,类似将数据做一个"扭转";

②可将data段中的数据看成是多个数组,用DS指标该数据段,而将table中的数据看成是一个结构型数据的数组,每个结构型数据中包含多个数据项,用ES指示该数据段;

③寻址方式建议:可用bx定位每个结构型数据,用idata定位数据项,用si定位数组项中的每个元素,对于table中的数据的访问可采用[bx].idata和[bx].idata[si]的寻址方式;

④程序结构方面:可以将程序分为四块,分别用四个循环处理------复制年份、复制总收入、复制雇员数、计算人均收入,当然,这四个循环可以合并以提高效率。

【参考解答】

assume cs:codesg, ds:data
data segment
    db '2004','2005','2006','2007','2008','2009','2010','2011','2012','2013'
    db '2014','2015','2016','2017','2018','2019','2020','2021','2022','2023'
    ;以上是表示20年的20个字符串
    dd 22,382,1356,2390,8000,16000,24486,50065,97479,140417
    dd 197514,345980,590827,803530,1183000,1843000
    dd 2759000,3753000,4649000,5937000
    ;以上是表示20年公司总收入的20个dword型数据
    dw 7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
    dw 11542,14430,15257,17800
    ;以上是表示20年公司雇员人数的20个word型数据
data ends

table segment
    db 20 dup('YearSummNeAv????')
table ends

;定义代码段
codesg segment
start: 
    mov ax, data
    mov ds, ax

    mov ax, table
    mov es, ax

    ;复制年份
    mov cx, 20
    mov si, 0   ;data段的数据项
    mov bx, 0   ;table段年份的起始偏移地址
s1:
    mov ax, [si]      ;取data段中年份的前两字节
    mov es:[bx], ax   ;向table中复制年份的前两字节
    mov ax,[si+2]     ;取data段中年份的后两字节
    mov es:[bx+2], ax ;向table中复制年份的后两字节
    add si, 4         ;指向data段的下一个数据项
    add bx, 16        ;指向table中下一年的位置
    loop s1

    ;复制总收入
    mov cx, 20
    mov si, 0   ;data段的数据项
    mov bx, 4   ;table段总收入的起始偏移地址
s2:
    mov ax, [si+80]      ;取data段中总收入的前两字节
    mov es:[bx], ax      ;向table中复制总收入的前两字节
    mov ax,[si+82]       ;取data段中总收入的后两字节
    mov es:[bx+2], ax    ;向table中复制总收入的后两字节
    add si, 4            ;指向data段的下一个数据项
    add bx, 16           ;指向table中下一年的位置
    loop s2

    ;复制雇员人数
    mov cx, 20
    mov si, 0   ;data段的数据项
    mov bx, 8   ;table段雇员人数的起始偏移地址
s3:
    mov ax, [si+160]     ;取data段中雇员人数
    mov es:[bx], ax      ;向table中复制雇员人数的前两字节
    add si, 2            ;指向data段的下一个数据项
    add bx, 16           ;指向table中下一年的位置
    loop s3

    ;计算人均收入
    mov cx, 20
    mov bx, 0   ;table段雇起始偏移地址
s4:
    mov ax, es:[bx+4]      ;取总收入低16位
    mov dx, es:[bx+6]      ;取总收入高16位
    div word ptr es:[bx+8] ;除以雇员数,完成除法,商存放在AX中
    mov es:[bx+10], ax     ;存储人均收入
    add bx, 16             ;指向table中下一年的位置
    loop s4

    mov ax,4c00h
    int 21h
codesg ends
end start

下面是程序运行后看到的一部分数据:

【进一步改进】

参考解答中使用了并行的4个循环。观察到循环中寻址方式一致,将循环适当合并,是可能且会获得效率上提升的。

用这个结构试着通思路,再改进出更高效率的解决方案,值得同学们一试。

相关推荐
尘浮生1 分钟前
Java项目实战II基于微信小程序的校运会管理系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
MessiGo2 分钟前
Python 爬虫 (1)基础 | 基础操作
开发语言·python
Tech Synapse7 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
乌啼霜满天24916 分钟前
JDBC编程---Java
java·开发语言·sql
色空大师28 分钟前
23种设计模式
java·开发语言·设计模式
Bruce小鬼41 分钟前
QT文件基本操作
开发语言·qt
2202_754421541 小时前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
我只会发热1 小时前
Java SE 与 Java EE:基础与进阶的探索之旅
java·开发语言·java-ee
懷淰メ1 小时前
PyQt飞机大战游戏(附下载地址)
开发语言·python·qt·游戏·pyqt·游戏开发·pyqt5
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j