计算机学院实验报告课程汇编语言实验名称实验7 寻址方式在结构化数据访问中的应用专业计算机科学与技术2018年 12 月 24 日一、实验目的1.定位内存单元的寻址方式汇总2.寻址方式的综合应用3.转移指令的分类和原理4.熟悉在显存中编程的方法二、实验内容及要求( 一) 寻址方式的汇总及综合应用1.定位内存单元的寻址方式有几种,并举例说明。
2.寻址方式在结构化数据访问中的应用。
Power idea 公司从 1975 年成立一直到 1995 年的基本情况如下。
年份收入 ( 千美元 )雇员人均收入 ( 千美元 ) 1975163?1976227? 19773829? 1978135613? 1979239028? 1980800038? 1995593700017800?下面的程序中,已经定义好了这些数据:assume cs:codesgdata segmentdb '1975','1976','1977','1978','1979','1980','1981','1982','1983'db '1984','1985','1986','1987','1988','1989','1990','1991','1992'db '1993','1994','1995';年份dd16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514dd345980,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,8226dw 11542,14430,15257,17800;公司雇员人数data endstable segmentdb 21 dup('year summ ne ??')table ends编程,将 data 段中的数据按如下格式写入到人均收入 ( 取整 ) ,结果也按照下面的格式保存在table table段中,并计算21 年中的人均收入,结果也按照下面格式保存在table段中。
1 年地址占 1 行,0 1 2 3 4 5 6 7 8 9 A BC DE F每行的起始地址table:0‘1975’163? table:10H‘1976’227? table:20H‘1977’3829? table:30H‘1978’135613? table:40H‘1979’239028? table:50H‘1980’800038?Mtable:140H‘1995’593700017800?提示 : 可将 data 段中的数据看成是多个数组,而将 table 中的数据看成是一个结构型数据的数组,每个结构型数据中包含多个数据项,可用bx 定位每个结构型数据,用 idata 定位数据项,用 si 定位数组项中每个元素,对于 table 中的数据的访问可采用 [bx].idata和[bx].idata[si]的寻址方式。
注意,这个程序是目前为止最复杂的程序,它机会用到了我们以前学过的所有知识和编程技巧。
所以,这个程序是对我们从前学习的最好的实践总结。
三、实验解答过程及结果( 一) 寻址方式的汇总及综合应用1.定位内存单元的寻址方式有 5 种, 如下:(1)[idata]例: mov ax,[5] (ax)=((ds)*16+5)(2)[bx]例: mov ax,[bx] (ax)=((ds)*16+(bx))(3)[bx+idata]例: mov ax,[bx+5] (ax)=((ds)*16+(bx)+5)(4)[bx+si]或[bx+di]例: mov ax,[bx+si] (ax)=((ds)*16+(bx)+(si))(5)[bx+si+idata]或[bx+di+idata]例: mov ax,[bx+si+5] (ax)=((ds)*16+(bx)+(si)+5)2.寻址方式在结构化数据访问中的应用(1) 给出该设计过程或算法该题目地址的变化是有规律的,我们可以知道,程序运行完的table 段一共有21行,分别存放 21 年的数据,每行有 16 个字节,正好放满所有内容。
所以采用loop 循环 21 次,每次都在 table 段的对应行存放”年份( 4 字节) +空格 + 收入( 4 字节) +空格 +雇员数( 2 字节) +空格 +人均收入( 2 字节) +空格”形式的数据。
这里的数据我放在 es:[si+idata] 里, si 最初为 0,每次循环 +16 (即一行)。
而从 data 段的数据可以看出,第一块年数据地址之间相隔4,第二块收入数据地址之间相隔也是4,第三块雇员数据地址之间相隔2。
第一块数据和第二块数据地址之间相隔4*21=84(因为一个年数据占了4个字节),第二块数据和第三块数据地址之间也是相隔8 4(收入是 dword 数据)。
年数据用 ds:[bx]定位,收入数据用ds:[bx+84] 定位,bx 最初为0,每次循环bx+4(即跳到下个相应数据)。
雇员数用 ds:[di+168] 定位, di 最初为 0,每次循环 di+2 。
代码如下:assume cs:code,ds:data,ss:stackdata segmentdb '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,197514dd 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,8226dw 11542,14430,15257,17800;以上是表示21年公司雇员人数的21个word型数据data endstable segmentdb 21 dup ('year summ ne ?? ')table endsstack segment stackdb 128 dup(0)stack endscode segmentstart: mov ax,stackmov ss,axmov sp,128mov ax,datamov ds,ax ;设置数据从哪儿来mov ax,tablemov es,ax ;设置数据到哪儿去mov si,0 ;ds:[si] si=0 年份开始的偏移地址mov di,84 ;ds:[di] di=84 公司总收入开始的偏移地址mov bx,168 ;ds:[bx] bx=168 公司雇员人数开始的偏移地址mov bp,0 ;es:[bp] bp=0 数据存到table中的开始的偏移地址mov cx,21 ;循环21次inputTable: push ds:[si] ;把年份放到table的 year中用栈转移更简单pop es:[bp]push ds:[si+2]pop es:[bp+2]mov ax,ds:[di] ;把公司总收入放到table的 summ中因需算人均收入,故不使用栈mov dx,ds:[di+2] ;dd型占2个字,即4个字节mov es:[bp+5],ax ;bp+5 对应 sumov es:[bp+7],dx ;bp+7 对应 mmpush ds:[bx] ;把雇员人数放到table的 ne中pop es:[bp+0AH]div word ptr ds:[bx]mov es:[bp+0DH],ax ;把人均收入放到talbe的 ??中;0123456789ABCDE; db 21 dup ('year summ ne ?? ')add si,4 ;年份占4个字节add di,4 ;总收入占4个字节add bx,2 ;雇员人数占2个字节add bp,16 ;放入table中每一年换一行loop inputTablemov ax,4c00Hint 21Hcode endsend start(3)Table段中原始数据与最终结果比对。
前后对比如图:四、实验总结通过这次实验,我学会了寻址方式的多种形式以及他们的综合应用,还有转移指令的原理和各种用法。
在实验的过程中,我学会了编写一些复杂的程序,学会了判断程序的运行结果,懂得了更多的汇编知识,在汇编语言的学习上又有了新的进步。