01_CPU中的寄存器访问(读写)内存

一、各类存储器芯片

在这里插入图片描述
这些存储器在物理上是独立的硬件,但有以下2点相同

  • 都和CPU的总线相连
  • CPU对它们进行读写都通过控制总线发出内存读写命令。
    在这里插入图片描述
    CPU将各类存储器看做一个由若干存储单元组成的逻辑存储器,各类存储器在这个逻辑存储器上占有一个地址段。这个逻辑存储器就是内存地址空间

想起来一个一个例子,对于X86的PC机来说,开机时, CS=0xFFFF; IP=0x0000;因此BIOS程序的地址为0xFFFF0(ROM BIOS映射区,内存RAM的地址,为了运行的快)。不是X86的PC机器,PC指针指向ROM的BIOS程序地址 0xF0000~0xFFFFF(这个地址是ROM的地址)。硬件执行BIOS。由此可见,ROM与RAM共同组成了一个逻辑存储器(内存地址),看起来是相连的地址。

二、寄存器

8086CPU所有寄存器都是16位寄存器

2.1、DX

段寄存器,内存单元的地址要放到dx中。
详解:8086CPU中的内存地址有段地址和偏移地址组成。
场景:CPU要访问(读写)一个内存地址的数据时

mov bx,1000H
mov dx,bx
mov al,[0]

内存地址=段地址:偏移地址
[0]说明操作对象是一个内存单元,偏移地址是0

2.2、CS

段寄存器,CPU要读取指令的代码段地址。
场景:CPU要读取执行代码(指令)的内存地址=CS:IP

2.3、SS

段寄存器,栈顶的段地址存在CS中,偏移地址放在SP中。
场景:SS:SP存储栈顶的地址。

三、8086CPU

  • 16位数据总线
  • 20位地址总线
  • 单位存储地址1byte
  • 寻址范围,地址有多大: 2的20次方byte,2的10次方M,1KB

四、mov指令

mov指令的作用是完成数据的传送。
寄存器,段寄存器,内存单元,数据。
8086CPU不支持数据直接送入段寄存器。

五、字

8086CPU是16位数据总线,寄存器也是16位。那么寄存器与内存间的数据一个传2字节数据,即一个字的数据。
针对8086CPU:1字=2字节
那么用mov传送内存中的数据给寄存器的时候,一次就传一个字(2字节)而不是1个字节。
在这里插入图片描述

在这里插入代码片
mov ax,10000H
mov ds,ax
mov ax,[0]

100000H地址存储的值是23,这是2字节8位二进制数,但是ax寄存器是存16位二进制数,因此ax的值是10000H和10001H组成的。

六、段

一组内存地址定义为段。段中的地址都可以用 段地址:偏移地址表示。
这个可以引申出2个概念和2个问题

6.1、数据段

把一组地址连续的内存单元专门存储数据,定义为数据段。
CPU访问数据段:mov 内存地址 定义DS,偏移[ ]

6.2、栈段

把一组连续的内存单元当作栈空间来用,定义为栈段。
CPU进行栈操作 SS:SP

6.3、代码段

一个段存放代码,定义为代码段。
CPU执行代码,CS:IP

问题、内存中数据和程序(指令)有区别吗?如何确定内存中哪些是数据,哪些是程序?

1)数据和程序有区别吗?
答:在磁盘和内存中(这是条件),数据和程序是没有区别的,都是二进制信息。
2)如何确定内存中的信息哪些是数据,哪些是程序?
答:要想确定内存中的信息是到底是数据还是信息,主要取决于在工作时访问这些信息的寄存器类别;
首先我们得知道,可以访问这些信息的寄存器有哪些,比如说:
CS(CodeString)是指令段地址,当CS:IP访问内存中的信息时,这些信息就是要执行的指令程序
DS(DataString)是数据段地址,当DS:IP访问内存中的信息时,这些就是数据
SS(StackString)指向的是栈顶段地址,学过数据结构的朋友应该知道栈其实是数据存储的一种特殊方式,也就是说被SS访问的信息也是被当作数据来看待的。
所以说只有当二进制信息被CS:IP访问时,才是可执行的指令 或 程序;其他的情况都被当作是数据。
在这里插入图片描述

PC指针指向20000H后,指向20003H,执行指令,不会指向数据20001H和20002H

七、栈

这里可以引申为几个问题

7.1、为什么需要栈?

CPU提供的栈机制,这里的栈指的是一种处理问题的机制,数据结构中栈也是一种数据结构。主要临时数据的存储、函数调用和返回。例如在调用函数时,cpu进去函数内部去执行代码,函数执行完了,需要返回调用函数的位置执行下一行代码,这个地址就存储到栈中。这里底层的实现就是栈用来暂存以后要恢复的寄存器中的内容。

7.2、CPU如何知道一段空间被当成栈使用?

根据段寄存器SS和寄存器SP中存储的地址。

7.3、CPU如何知道哪个内存单元是栈顶?

栈顶地址存储在SS:SP中。
这里需要注意的说:栈的增长是从高地址到低地址,因此栈增长偏移地址反而减小。8086CPU,一次入栈偏移地址减小2,因为寄存器存储16位二进制即2内存单元。

7.4、栈存储临时数据,那么代码中的常量、全局变量、局部变量、方法参数存储到哪里?

在微控制器上读取和修改PWM2_CCER1寄存器通常涉及到特定的硬件操作和软件编程。这里以STM32系列为例,因为它们广泛用于各种嵌入式应用,并有详细的文档支持。 1. **读取PWM2_CCER1寄存器**: - 首先,你需要确定该寄存器的确切地址。例如,在STM32F103,CCER1位于GPIOE的端口映射区,地址可能是`*GPIOE_BASE + GPIOE_PUPDR_OFFSET + PWM2_CCER1_BITOFFSET`,其`GPIOE_BASE`是GPIOE的基地址,`PUPDR_OFFSET`是控制寄存器的偏移量,`PWM2_CCER1_BITOFFSET`是CCER1位的具体位地址。 - 使用适当的访问模式(如R/W、只读等),通过CPU的I/O映射功能将该地址转换成内存地址,然后从内存读取数据。 - 在C语言,这可能看起来像这样: ```c uint16_t ccer1 = *(uint16_t *)(GPIOE_BASE + GPIOE_PUPDR_OFFSET + PWM2_CCER1_BITOFFSET); ``` 2. **修改PWM2_CCER1寄存器**: - 同样地,你需要确保权限允许你写入该地址。然后,更新变量值并写回内存: ```c ccer1 |= (uint16_t) 新的值; // 如果你想设置某个位为1 ccer1 &= ~(uint16_t) 新的值; // 如果你想清除某个位为0 *(__IO uint16_t *)(GPIOE_BASE + GPIOE_PUPDR_OFFSET + PWM2_CCER1_BITOFFSET) = ccer1; ``` `__IO`前缀表示这是一个可读写内存区域。 请注意,实际操作可能会因芯片型号和库函数的不同而有所变化。如果你使用的是Keil MDK或STM32CubeIDE这样的集成开发环境,会有一套预设的API可以简化这些过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值