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

有一年多没有在CSDN上发博文了。人的工作重心总是有转移的,庆幸一直在做着有意义的事。
  今天的内容,是为汇编语言课程更新一个实验项目。
  
  本方案修改自王爽编《汇编语言》第4版P172“实验7寻址方式在结构化数据访问中的应用”

【数据描述】

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

年份总收入(万元)雇员(人)人均收入(万元)
2004227?
20053829?
2006135613?
2007239028?
2008800038?
……
2023593700017800?

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

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个循环。观察到循环中寻址方式一致,将循环适当合并,是可能且会获得效率上提升的。
  用这个结构试着通思路,再改进出更高效率的解决方案,值得同学们一试。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迂者-贺利坚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值