汇编 第八章 数据处理的两个基本问题

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

本章对前面的所有内容是具有总结性的
计算机是进行数据处理、运算的机器,那么有两个基本的问题就包含在其中:
1.处理的数据在什么地方?
2.要处理的数据有多长?
这两个问题,在机器指令中必须给以明确或隐含的说明,否则计算机就无法工作

8.1 bx、si、di、bp

​ 1.在8086CPU中,只有这4个寄存器(bx、bp、si、di)可以用在“[…]”
​ 中,用来进行内存单元的寻址
​ 2.在“[…]”中,这四个寄存器(bx、bp、si、di)可以单个出现,
​ 或者只能以以下4种组合出现
​ 1.bx和si
​ 2.bx和di
​ 3.bp和si
​ 4.bp和di
​ 3.错误的用法
​ mov ax,[bx+bp]
​ mov ax,[si+di]
​ 4.只要在[…]中使用寄存器bp(帮sp不够用的时候),则指令中没有显性给出段地址,那么
​ 段地址就默认在ss中,比如:
​ mov ax,[bp] ax的值为栈空间中,偏移地址为bp的内存单元
​ mov ax,[bp+常数]
​ mov ax,[bp+si]
​ mov ax,[bp+si+常数]

8.2 机器指令处理的数据所在的位置

​ 1.绝大部分机器指令进行数据处理的指令大致可分为3大类
读取、写入、运算
​ 2.在机器指令这一层,并不关心数据的值是多少,而关心指令执行前一刻
​ 它将要处理的数据所在的位置
​ 3.指令在执行前,所要处理的数据可以在三个地方
CPU内部(寄存器)、内存、端口(后面讲)

在这里插入图片描述

8.3 汇编语言中数据位置的表达

​ 汇编语言中用三个概念来表达数据的位置
​ 1.立即数(idata)immediate data

对于直接包含在机器指令中的数据(执行前在CPU的指令缓冲器中),在汇编语言中称为:立即数(idata),在汇编指令中直接给出。
例:mov ax,1

​ 2.寄存器

指令要处理的数据在寄存器中,在汇编指令中给出相应的寄存器名。例:mov ax,bx

​ 3.段地址(SA)和偏移地址(EA)
​ 1.存放段地址的寄存器可以是默认的
​ 既可以是默认在ds中,也可以是在ss中(使用bp寄存器)
​ 2.存放段地址的寄存器也可以显性的给出
​ mov ax,ds:[bp]
​ mov ax,es:[bx]
​ mov ax,ss:[bx+si]
​ mov ax,cs:[bx+si+8]

8.4 寻址方式

在这里插入图片描述

8.5 指令要处理的数据有多长?

​ 1.8086CPU的指令,可以处理两种尺寸的数据,byte和word
​ 所以在机器指令中要指明,指令进行的是字操作还是字节操作
​ 2.8086CPU确定数据长度的几种方法
​ 1.通过寄存器名指明要处理的数据的尺寸
​ mov al,1 ;指明数据是字节型的
​ mov bx,ds:[0] ;指明数据是字型的
​ 2.在没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度
X在汇编指令中可以为word或byte
​ 1.下面的指令中,用byte ptr指明了指令访问的内存单元是字节型单元
​ mov byte ptr ds:[0],1
​ inc byte ptr [bx]
​ inc byte ptr ds:[0]
​ add byte ptr [bx],2
​ 2.下面的指令中,用word ptr指明了指令访问的内存单元是字型单元
​ mov word ptr ds:[0],1
​ inc word ptr [bx]
​ inc word ptr ds:[0]
​ add word ptr [bx],2

在没有寄存器参与的内存单元访问指令中,用word ptr或者byte ptr,显性地指明所要访问的内存单元的长度,是非常有必须要的。否则,CPU无法得知所要访问的单元是字单元,还是字节单元

假设我们用Debug查看内存的结果如下:
2000:1000 FF FF FF FF FF FF…
那么指令:

mov ax,2000H
mov ds , ax
mov byte ptr [1000H],1

将使内存中的内容变为:
2000: 1000 01 FF FF FF FF FF …

而指令:

mov ax, 2000H
mov ds , ax
mov word ptr [ 1000H],1

将使内存中的内容变为:
2000: 1000 01 00 FF FF FF FF…
这是因为mov byte ptr [1000H],1访问的是地址为ds:1000H的字节单元,修改的是ds:1000H单元的内容;而mov word ptr [1000H],1访问的是地址为ds:1000H的字单元,修改的是 ds:1000H 和 ds:1001H两个单元的内容。

​ 3.其他方法
​ 有些指令默认了访问的是字单元还是字节单元,比如,push [1000H]就 不用指明访问的是字单元还是字节单元,因为push指令只进行字操作
​ sp = sp-2

8.6 寻址方式的综合应用

在这里插入图片描述

以上是该公司1982年的情况,到了1988年 DEC公司的信息有了如下变化。(1) Ken Olsen在富翁榜上的排名已升至38位;
(2)DEC的收入增加了70亿美元;
(3)该公司的著名产品已变为VAX系列计算机。我们提出的任务是,编程修改内存中的过时数据。首先,我们应该分析一下要修改的数据。
要修改内容是:
(1)(DEC公司记录)的(排名字段)(2)(DEC公司记录)的(收入字段)
(3)(DEC公司记录)的(产品字段)的(第一个字符)、(第二个字符)、(第三个字符)从要修改的内容,我们就可以逐步地确定修改的方法。
(1)要访问的数据是DEC公司的记录,所以,首先要确定DEC公司记录的位置:R=seg:60
确定了公司记录的位置后,下面就进一步确定要访问的内容在记录中的位置。(2)确定排名字段在记录中的位置:0CH。
(3)修改R+0CH处的数据。
(4)确定收入字段在记录中的位置:OEH。

(5)修改R+0EH 处的数据。
(6)确定产品字段在记录中的位置:10H。
要修改的产品字段是一个字符串(或一个数组),需要访问字符串中的每一个字符。所以要进一步确定每一个字符在字符串中的位置。
(7)确定第一个字符在产品字段中的位置:P=O。(8)修改R+10H+P处的数据;P=P+1。
(9)修改R+10H+P处的数据;P-P+1。

(10)修改 R+10H+P处的数据。根据上面的分析,程序如下。

mov ax, seg
mov ds, ax
mov bx,60h;确定记录地址,ds:bx
mov word ptr [bx+0ch],38;排名字段改为38
add word ptr [bx+0eh],70;收入字段增加70
mov si,0;用si来定位产品字符串中的字符
mov byte ptr [bx+10h+si],'v'
inc si
mov byte ptr [bx+10h+si],'A'
inc si
mov byte ptr [bx+10h+si],'x'
8.7 div指令

​ 1.div是除法指令(division),使用div作除法的时候,要求
​ 1.除数:8位或16位,在寄存器或内存单元中
​ 2.被除数:(默认)放在 AX 或 DX 和AX 中
​ 3.除数与被除数的相互关系
​ 除数 被除数
​ 8位 16位(AX)
​ 16位 32位(DX+AX)
​ 4.结果存放的位置
​ 运算 8位 16位
​ 商 AL AX
​ 余数 AH DX
​ 2.div指令格式
​ 1.div 寄存器
​ 2.div 内存单元
​ 除数是寄存器或内存单元的内容
​ 3.div指令示例

1.div byte ptr ds:[0]   ;被除数是16位,除数是ds:[0]的内容(8位)
          含义:(al)=(ax)/((ds)*16+0)的商
               (ah)=(ax)/((ds)*16+0)的余数
2.div word ptr es:[0]    ;被除数是32位,除数是es:[0]的内容(16位)
          含义:(ax)=[(dx)*10000H+(ax)]/((es)*16+0)的商
               (dx)=[(dx)*10000H+(ax)]/((es)*16+0)的余数   

​ 4.利用除法指令计算100001/100
​ 1.被除数100001大于65535,要使用dx和ax两个寄存器联合存放
​ 即说要进行的16位的除法
​ 2.除数100小于255,可以在一个8位寄存器中存放,但是,因为被除数是32位,除数应为16位,所以要用16位寄存器来存放除数100
​ 3.现将100001表示成十六进制数:186A1H,即dx中存放1H,ax中存放86A1H

mov dx,1
mov ax,86A1H ;(dx)*10000H+(ax)=100001
mov bx,100
div bx  ;默认除数是16位的
;程序执行后 ax = 03e8h(1000 商),dx = 1(余数)

5.编程,利用除法指令计算1001/100。
首先分析一下,被除数1001可用ax寄存器存放,除数100可用8位寄存器存放,也就是说,要进行8位的除法。程序如下。

mov ax,1001
mov bl,100
div bl

程序执行后,(al)=OAH(即 10),(ah)=1(余数为1)。读者可自行在Debug 中实践。

8.8 伪指令dd
1. dd是用来定义双字型数据的 define double word
    2.示例
    data segment
        db 1    ;字节型数据 一个字节,01H,在data:0处
        dw 1    ;字型数据  一个字,0001H,在data:1处
        dd 1    ;双字型数据 2个字 00000001H,在data:3处
    data ends
    3.已知data段数据,用div计算data中第一个数据除以第二个数据后的结果,商存放在第3个数据的内存单元中
assume cs:code,ds:data
data segment
	dd 100001
	dw 100
	dw 0
data ends
code segment
start:
	mov ax,data
	mov ds,ax
	mov bx,0
	mov ax,[bx]     ;低位存放在ax中
	mov dx,[bx+2]   ;高位存放在dx中
	div word ptr [bx+4]
	mov [bx+6],ax   ;商存放在ax中,把ax中的内容放入内存中
	mov ax,4c00h
	int 21h
code ends
end start
8.9 dup

​ 1.dup是一个操作符,在汇编语言中,同db、dw、dd等一样,也是有编译器识别处理的符号
​ 2.dup和db、dw、dd等数据定义伪指令配合使用的,用来进行数据的重复
​ 3.dup示例
​ 1.db 3 dup(0) ;定义了3个字节,他们的值都是0
​ 2.db 3 dup(0,1,2) ;定义了9个字节,他们是0、1、2、0、1、2、0、1、2
​ 3.db 3 dup(‘abc’,‘ABC’) ;定义了18个字节,相当于db ‘abcABCabcABCabcABC’
​ 4.dup的使用格式
​ db 重复的次数 dup(重复的字节型数据)
​ dw 重复的次数 dup(重复的字型数据)
​ dd 重复的次数 dup(重复的双字型数据)
【实验七】寻址方式在结构化数据访问中的应用

在这里插入图片描述

assume cs:code,ds:data,ss:stack,es:table
stack segment
	dw 8 dup(0)	;空栈时,sp指向16
stack ends
data segment
	db '1975','1976','1977','1978','1979','1980','1981','1982','1983' ;起始地址0,终止地址21*4-1:83	(0-53H)
	db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
	db '1993','1994','1995'
	;表示21年的21个字符串(4byte)
	
	dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514;起始地址21*4:84,终止地址21*4+21*4-1:167 (54H-0A7H)
	dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000 
	;表示21年公司总收入的21个双字型(4byte)数据

	dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226;起止地址21*8:168,终止地址21*8+21*2-1:209 (0A8H-0D1H)
	dw 11542,14430,15257,17800
	;表示21年公司雇员人数的21个字型数据(2byte)
data ends

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

code segment
start:
	mov ax,data
	mov ds,ax
	mov ax,table
    mov es,ax
    mov ax,stack
    mov ss,ax
    mov sp,16
    mov si,0
    mov di,0
    mov bx,0
    mov bp,0 
    mov cx,21
outer:
	push si
    add si,si
    mov ax,ds:[bp]
    mov es:[bx][di],ax
    mov ax,ds:84[bp]
    mov es:[bx][di+5],ax
    pop si
    mov al,168[si]
    mov es:[bx][di+10],al
    inc si
    add di,2
    push si
    add si,si
    mov ax,ds:[bp]
    mov es:[bx][di],ax
    mov ax,ds:84[bp]
    mov es:[bx][di+5],ax
    pop si
    mov al,168[si]
    mov es:[bx][di+10],al
    inc si
    add di,2
    add bx,16
    loop outer
    mov ax,4c00h
    int 21h
code ends
end start

在这里插入图片描述

一直到78E0h:0才是代码段的位置,前面是数据。cx是21

076aH:0 是数据data段ds的位置。0778d:0是table开始es的位置
在这里插入图片描述

最后得到的结果和题目排列要求一样

在这里插入图片描述

验证平均收入数是正确的
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值