《汇编语言》第 8章 -数据处理的两个基本问题 检测点,实验7,总结

第8章 数据处理的两个基本问题

(1)要处理的数据在什么地方?
(2)要处理的数据有多长?

定义的描述性符号:reg(register)和sreg(segment register)
reg包括:ax,bx,cx,dx,al,bl,cl,dl,ah,bh,ch,dh,sp,bp,si,di
sreg包括:ds,ss,cs,es。
1.关于bx,si,di和bp
(1)8086中只有这4个寄存器可以在“[…]”中来进行内存单元的寻址。
如;mov ax,[cx]是不对的。
(2)在[…]中,这4个寄存器可以单个出现,或只能以4种组合出现:bi和si、bx和di、bp和si、bp和di。
如:mov ax,[bx+bp]是不对的。
(3)如同’mov ax,[bx]‘,默认的段地址在ds中一样,
mov ax,[bp],默认的段地址在ss中。
2.机器指令处理的数据在什么地方
在机器指令这一层来讲,并不关心数据的值是多少,而关心指令执行前一刻(值得深思),它将要处理的数据所在的位置。指令在执行前,所要处理的数据可以在3个地方:CPU内部(各种寄存器等)、内存、端口。
3.数据表达的位置
3种方式(立即数,寄存器,段地址:偏移地址)
4.寻址方式(主要是内存)
[idata],[bx],[bx+idata],[bx+si],[bx+si+idta]等(di,bp类似)
5.指令要处理的数据有多长
8086可以处理两种尺寸的数据,byte和word。所以要指明指令进行的是字节操作还是字操作。
所以在没有寄存器存在的情况下,用操作符X ptr指明内存单元的长度。
如:mov word ptr ds:[0],1
mov byte ptr ds:[0],1
注:栈操作只作字操作。
6.div指令
div是除法指令,使用div做除法的时候应注意以下问题。
(1)除数:有8位和16位的,应该在reg或者内存单元中保存;
(2)被除数:默认放在AX或(DX和AX中)。若除数为8位,则被除数为16位,默认在AX中;若除数为16位,则被除数为32位,默认在DX和AX中,高16位放DX,低16位放AX;即:除数小于255,用8位保存;大于255小于65535,用16位保存;被除数看除数。
(3)结果:若除数为8位,则al存放除法操作的商,ah存放除法操作的余数;
若除数为16位,则ax中存放除法操作的商,dx中存放除法操作的余数;
格式:div reg
div [bx]
7.伪指令dd
与dw,db一样·,dd用来定义双字数据,即32位数据。
8.操作符‘dup’
操作符dup和db,dw,dd等配合使用,用来进行数据的重复。
例如:db 3 dup(0)
相当于:db 0,0,0
例如:db 3 dup(0,1,2)
相当于:db 0,1,2,0,1,2,0,1,2

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

这个实验迄今确为最难的一道,但它综合了我们前面的所学,很有必要从头到尾自己做一遍。以下为我的答案:

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数据
				;;10进制双字数据转为16进制为:10h,16h,17eh,54ch,956h,1f40h,
				3e80h,5fa6h,0c391h,17cc7h,22481h,3038ah,5477ch,903ebh,0c42cah
				120d18h,1c1f38h,2a1958h,394428h,46f028h,5a9768h
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数据
				;;10进制字型数据转为16进为:3h,7h,9h,0dh,1ch,26h,82h,0dch,1dch,
				30ah,3e9h,5a2h,8d2h,0ae9h,0fc5h,1603h,2022h,2d16h,385eh,
				3b99h,4588h
					
				;;人均(商)的16进制表示:5h,3h,2ah,68h,55h,0d2h,7bh,6fh,41bh,
				7dh,61h,61h,57h,7bh,92h,8eh,8fh,0efh,104h,130h,14dh
	"""人均这里的16进制表示可能有点错误,数太多了,懒得一一转换了😀"""
data ends

table segment
db 21 dup ('year summ ne ?? ')
table ends

stack segment
db 10h dup (0)	;定义栈段用以保存cx的值
stack ends

code segment
start:
mov ax,data
mov ds,ax		;使ds指向data段
mov ax,table
mov es,ax		;使es指向table段
mov ax,stack
mov ss,ax
mov sp,10h		;使ss:sp指向栈段,此时栈空


mov bx,0		;[bx]控制data段的行
mov bp,0		;[bp]控制table段的行
mov cx,21		;设置外层循环次数

s1:
push cx			;保存cx的值
mov cx,4		;设置内层循环次数
mov si,0		;[si]寻址时,控制data段和table段的列
s2:
mov al,ds:[bx].[si]
mov es:[bp].[si],al
				;将年份从data段传送到table段第0-3列
mov al,ds:[bx].84[si]
mov es:[bp].5[si],al
				;将收入从data段传送到table段第5-8列
inc si			;使si递增,控制列指向下一个单元
loop s2

pop cx			;使外层循环次数出栈
add bx,4		;使data段行数递增
add bp,10h		;使table段行数递增
loop s1

mov bx,0		;data段的行置0
mov cx,21		;设置外层循环次数
mov bp,0		;table段的行置0
s3:
push cx			;使外层循环入栈保存
mov cx,2		;设置内层循环次数
mov si,0		;设置列为0
s4:
mov al,ds:[bx].168[si]
mov es:[bp].0ah[si],al
				;;将雇员数从data段传送到table段的第0a-0b段
inc si			;控制列数递增
loop s4

mov dx,es:[bp].7
mov ax,es:[bp].5
				;被除数32位,高位放入dx,低位放入ax
div word ptr es:[bp].0ah
				;除数在table段的0a(雇员数)
mov es:[bp].0dh,ax
				;把商传入0d列

pop cx
add bx,2		;控制data段的行
add bp,10h		;控制table段的行
loop s3

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

在这里插入图片描述在这里插入图片描述
其中0-3字节为年份,ASCII码有显示;5-8字节为总收入;0a-0b字节为雇员;0d-0e字节为人均;

总结: 本实验费了蛮大劲的,前后大概花了将近2个半小时的时间才搞定。不过这道题确实是对我们前面所学有很大的综合,对我们的能力是很大的锻炼;最好是自己从头到尾,从写到debug一步步来完成。
说说我的思路吧:程序要求把data段中的内容按照table段的格式写入。我们先分析table段,发现table段可以看作是21行16列的一个二维数组,想到用[bp]控制它的行,[si]控制它的列,然后用[bp].idata的方式来行内定位。再看data段,它有年份,总收入,雇员数3个。。域吧,可以把它们都看作是21行的数组,但是它们的列数不一;再看这3个域在table段中的位置,其中年份,总收入是占4个字节;雇员数及人均是占2个字节;想到可以把年份及总收入放在一个循环内传送(因为它们的行列数一致,可以同时寻址。),再把雇员数和人均放到另一个循环内来传送(一开始我是想把它们放到同一个循环内的,但是寻址寄存器不太够用,只能分开) 用[bx]控制行,用[si]控制列,再用[idata]定位数组的首地址(相隔84个字节)最后要解决的是人均,它是总收入和雇员数的商,只需做一下除法,用循环来放入固定的位置即可。(具体细节见上代码;)


唉,失恋了,心情不太好。不过当然不是我,是?北这家伙,?!他跟我抱怨,我能怎么办啊,他骂我,我骂他。没得办法。不知道这家伙汇编学到哪了,估计没看。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值