实验七 寻址方式在结构化数据访问中的应用

目录

一.实验内容:

二.实验过程(实验设计思路,源码及注释)

三.Debug调试及实验结果分析

四.总结与体会


一.实验内容:

问题:

Power idea公司的基本情况如下:

      见书中数据列表:

下面格式已经定义好了这些数据:

assume cs:code 

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

code segment

start:

       ???????

       mov ax,4c00H

       int 21H

code ends

end start

实验要求:将data段中的数据,按照书中的格式写入到table段中,并计算21年中的人均收入(取整),结果也按照下面的格式保存在table段中。

二.实验过程(实验设计思路,源码及注释)

程序分析:

先观察data段,21个年份一共占21*4=84byte,21个公司收入一共占21*4=84byte(因为dword占4byte),21个公司雇员人数占21*2=42byte。再观察table段,dup表示复制,复制了21次'your sum ne ?? ',因为这个字符串占16个字节,这样我们就可以用date段中的21个年份替换table段中的year(例如,1975 -> year),同样我们可以用data段中的21个公司总收入替换table段中的summ,data段中的雇员人数替换table段中的ne,将data段人均收入的结果用??来替换,这样就完成了table段数据的替换。

考虑到仅仅是将data段中的数据复制到table段中,而不是修改内容并覆盖,这样我们的话,我们可以通过地址传递的方式完成数据的复制操作。那么应该如何具体操作呢?

我们可以具体分析一下复制的一个规律,如下图:

cbbbeea9fe9d47c7a098731123b831c2.jpeg

我们可以进行模拟,第一次data:[0] --> table:[0],第二次data:[1] --> table:[1],……

data:[4] --> table:[5],四个一循环,这样我们可以用[bx+si]存放data的偏移地址,但由于ds已经用来存储data的段地址了,所以我们只能用ss或者es来存储table的段地址(基地址),这里我们用ss段地址(如果用ss作为table的段地址,bp的段地址默认在ss中。可以不用写段名doge)。这里再解释一下为什么不给sp赋初值,因为我们只用到了栈段,用不到push和pop操作,所以不需要给sp赋值。

    那么我们怎么计算人均收入呢?人均收入 = 公司总收入 / 雇员人数,由于公司总收入为dword型数据(占32bit)需要ax和dx两个联合存放,而雇员人数为word型数据(占16bit)

下面是最终的源码:

assume cs:codesg,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'

    dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514

    dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

    dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226

    dw 11452,14430,15257,17800

data ends

table segment

    db 21 dup ('year summ ne ?? ')

table ends

codesg segment

start:  mov ax,data

        mov ds,ax ;这两行是将data段的地址通过ax寄存器送到ds寄存器中

        mov ax,table

        mov ss,ax ;这里也可以用es寄存器

        mov bx,0

        mov si,0

        mov bp,0 ;初始化bx,si,bp

        mov cx,21 ;cx寄存器存储循环次数21次

s0:mov ax,[bx+si]

;s0写入年份

   mov [bp+0],ax;相当于data:[bx+si] --> table:[bp+0]

   add si,2 ;因为ax寄存器是16位(2byte)寄存器,所以移动2个字节(如,‘19’)

   mov ax,[bx+si]

   mov [bp+2],ax

   add si,2

   add bp,10h ;10h表示10进制数16

   loop s0



   mov cx,21

   mov bp,0

   mov si,0 ;由于cx,bp,si的值已经变换,需要重新赋值

s1:mov ax,[bx+si+84] ;跳过年份所占的84byte

;s1写入公司总收入

   mov [bp+5],ax;相当于data:[bx+si+84] --> table:[bp+5]

   add si,2

   mov ax,[bx+si+84]

   mov [bp+7],ax

   add si,2

   add bp,10h

   loop s1



   mov cx,21

   mov bp,0

   mov si,0 ;重新初始化

s2:mov ax,[bx+si+168]

;s2写入公司雇员人数

   mov [bp+10],ax

   add si,2

   add bp,10h

   loop s2



   mov cx,21

   mov bp,0 ;后面不用si不需要对si重新赋值

s3:mov ax,[bp+5];ax存低16位总收入数据

;s3计算人均收入并写入

   mov dx,[bp+7] ; dx存高16位总收入数据

   div word ptr [bp+10] ;商存在ax中,余数存在dx中

   mov [bp+13],ax ;相当于ax --> table:[bp+13]

   add bp,10h

   loop s3



    mov ax,4c00h

    int 21h

codesg ends

end start

三.Debug调试及实验结果分析

先用debug分析一下在最初data段的存储情况,如下图:

467b3a685fdd49be83dda28a2d84e55b.jpeg

我们可以观察:

红色圈:在075A:0100 ~ 075A:0153存储的是21个年份数据共占84byte

蓝色圈:在075A:0154 ~ 075A:01A7存储的是21个收入数据共占84byte

紫色圈:在075A:01A8 ~ 075A:01D1存储的是21个雇员数据共占42byte

在075A:01E0后面存的是table段中的数据“year sum ne ??”……

再用debug分析一下执行最终代码后table段中的数据,如下图:

039ea58d19004edeb98d5da8a4681be7.jpeg

成功将data段中的数据写入到table段中!!!

四.总结与体会

1.本实验考查知识较多,涉及除法指令、dup复制、基址间接寻址等操作全面考查了实验者的综合实践能力。

2.当一个ds寄存器不够用时,可以选择es寄存器或者ss寄存器来进行存储。

3.当我们仅对代码进行复制操作(并不改代码)时,我们可以仅修改地址来实现复制操作。

4.可以结合图表进行分析,对数据进行模拟总结其规律。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无限酸奶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值