## **CPU与内存的数据交换**
要解决的问题: CPU从内存单元中要读取数据
要求 CPU要读取一个内存单元的时候,必须先给出这个内存单元的地址;
原理:在8086PC中,内存地址由段地址和偏移地址组成(段地址:偏移地址)
解决方案:DS和[address]配合
用DS寄存器存放要访问的数据的段地址。指令执行时, 8086CPU自动取ds中的数据为内存单元的段地址。
偏移地址用[...]形式直接给出(这种形式段地址一定是保存在DS中的)
![](https://img.kancloud.cn/e2/49/e24903667f1f8c9145a50153b0215180_568x294.png)
例子1:内存里的数据传入寄存器
```
//将内存10000H(1000:0)中的数据读取到cpu寄存器al中
mov bx,1000H
mov ds,bx
//mov ds 1000H 注意这种方法是错的
mov al, [0]
```
例子2:寄存器的数据传入内存
```
//将cpu寄存器al中的数据写到内存10000H(1000:0)中。在8086PC中,cpu不支持将数据直接送入段寄存器
mov bx,1000H
mov ds,bx
mov [0],al
```
>[danger]套路:数据-》一般寄存器(通用寄存器)-》段寄存器
字的传送:
```
//将1000H段地址数据传给DS寄存器
mov bx,1000H
mov ds,bx
mov ax,[0] //将内存10000H(1000:0)处的字型数据读取到ax中
mov [0] cx //cx中的16位数据送到内存10000H(1000:0)处
```
例子:
注意DS和[...]操作的是字数据啦!在8086一个字是16位的
```
内存 指令
--------
- - mov ax,1000H //ax=1000
10000H - 23 -
- - mov ds,ax //ds=1000
--------
- - mov ax,[0] //ax=1123 注意ds[...]操作的是字数据,8086一个字为16位
10001H - 11 -
- - mov bx,[2] //bx=6622 ds保存的是段地址,[]中指明的是偏移地址,将1000:2的字数据6622赋值到bx
--------
- - mov cx,[1] //cx=2211 将1000:1的字数据2211赋值到bx
10002H - 22 -
- - add bx,[1] //bx=8833 将1000:1的字数据2211与bx的值6622相加并赋值到bx
--------
- - add cx,[2] //cx=8833 将1000:2的字数据6622与cx的值2211相加并赋值到cx
10003H - 66 -
- -
```
![](https://img.kancloud.cn/2c/99/2c9973bdf5aec7728d79f05eef96912d_889x482.png)
![](https://img.kancloud.cn/65/73/6573d1cf937a9def9d31957fc71c2e23_764x637.png)
## **DS与数据段(对内存单元中数据的访问)**
对于8086PC机,可以根据需要将一组内存单元定义为一个段。
物理地址=段地址x16+偏移地址
将一组长度为N (NS64K )、地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。
例:用123D0H,123B9H的空间来存放数据
* 段地址: 123BH 起始偏移地址:0000H长度:10字节
* 段地址: 1230H 起始偏移地址: 00B0H长度: 10字节
* ... ...
上面例子告诉我们 给出的方法很多
>[danger]在实际操作时,将哪段内存当作数据段? 段地址如何定,在编程时右编程人员自行安排。
处理方法:(DS):([address]),即用DS存放数据段的段地址
用相关指令访问数据段中的具体单元,单元地址由\[address\]指出
例子:
累加数据段中的前三个单元中的数据
```
mov ax,123BH //确定段地址
mov ds,ax //将确定的段地址存入DS
mov al,0 //初始化清零
add al,[0] //开始累加
add al,[1] //
add al,[2] //
```
累加数据段中的前三个**字型**单元的数据
```
mov ax,123BH //确定段地址
mov ds,ax //将确定的段地址存入DS
mov ax,0 //初始化清零
add ax,[0] //开始累加
add axl,[2] //
add ax,[4] //
```