TI的C28x CPU指令集学习(二)
Direct Addressing Mode(直接寻址模式) :
1. 基本概念
Direct Addressing Mode(直接寻址模式)是一种固定页寄存器 + 偏移量的寻址方式。
在这种模式下,指令并不会直接给出完整的 16 位或 32 位地址,而是由以下两部分组成:
- DP 寄存器 (Data Page Pointer):一个 16 位的数据页指针寄存器,存储基准页地址。
- Offset(偏移量):指令中给出的 6 位或 7 位偏移字段。
最终的有效地址由 DP 与 Offset 拼接得到。
2. 有效地址计算方式
如果 DP 是 16 位,而 Offset 是 6/7 位,那么有效地址为:
Effective Address = (DP << 6 or 7) | Offset
也可以理解为:
有效地址 = 数据页基地址 + 偏移量
例如:
- 假设 DP = 0x2000
- 偏移量 = 0x3A(6 位)
- 那么有效地址 =
0x2000 | 0x3A= 0x203A
3. 使用场景
Direct Addressing Mode 特别适用于访问固定地址的数据结构,例如:
- 片上外设寄存器
比如 UART、SPI、I2C 等硬件寄存器 - 全局变量 / 静态变量
- C/C++ 静态内存区
因为这些数据的起始地址通常是固定的,所以只需要把 DP 寄存器指向对应的页基地址,再通过指令中的 Offset 获取最终地址即可。
4. 优势
- 代码更精简:只需要在指令里存放较短的偏移量,而不是完整的地址。
- 访问速度快:避免频繁加载长地址。
- 适合固定数据结构:例如外设寄存器、常量表、全局变量等。
好的😊,我们结合 Direct Addressing Mode(直接寻址模式) 和 DP寄存器,对这句话逐层分析,帮助你彻底理解它在硬件和编译器层面上的意义。
这句话是:
“这种寻址方式可用于访问固定地址数据结构,例如外围寄存器和 C/C++ 中的全局或静态变量。”
1. 背景:Direct Addressing Mode + DP
在 Direct Addressing Mode 下:
- 指令只给出 页内偏移量 (Offset),而不是完整的 16 位地址。
- 高位页号由 DP(Data Page Pointer)寄存器提供。
- 最终有效地址 = DP高10位 + Offset低6位。
这种寻址方式非常适合访问一块固定地址的内存区域,因为:
- 页号(DP)一般不变
- 只改 Offset → 就能快速访问该页内的不同数据
2. “固定地址数据结构”是什么意思
固定地址数据结构就是那些起始地址不会动态变化的存储区域,包括:
(1) 外围寄存器(Peripheral Registers)
-
MCU / DSP 上的外设寄存器(UART、SPI、I2C、ADC、Timer等)一般放在固定的内存映射地址。
-
例如:
外设 起始地址 大小 UART 0x2000 64B SPI 0x2040 64B I2C 0x2080 64B -
如果我们把
DP=0x2000,那么:- UART_TX 寄存器 →
DP + 0x00 - UART_RX 寄存器 →
DP + 0x04 - UART_SR 状态寄存器 →
DP + 0x08
- UART_TX 寄存器 →
-
只需修改 Offset,不需要每次写完整 16 位地址。
(2) C/C++ 中的全局变量 (Global Variables)
在 C/C++ 编译时,全局变量一般会被放在一个固定的内存段(例如 .data 或 .bss 段)。
这些段的基地址是确定的,编译器可以让 DP 指向全局变量所在的页:
int g_count = 0; // 全局变量
假设编译器把 g_count 放在内存 0x3002:
- 如果
DP = 0x3000 Offset = 0x02- CPU 访问
g_count时,只需要写一个 6 位 Offset,而不用写完整 16 位地址。
(3) 静态变量 (Static Variables)
void foo() {
static int s_data = 5;
}
- 静态变量
s_data也放在固定的.data或.bss段,不会像局部变量那样放在栈上。 - 编译器可以同样使用 DP + Offset 的方式访问。
3. 为什么 Direct Addressing Mode 特别适合这种情况
| 特点 | 普通寻址 | Direct Addressing Mode |
|---|---|---|
| 指令中的地址 | 16 位完整地址 | 只需 6 位 Offset |
| DP寄存器 | 不用 | 保存页基地址 |
| 访问效率 | 慢 | 快 |
| 代码大小 | 大 | 小 |
| 应用场景 | 动态内存、堆栈 | 外设寄存器、全局变量、静态变量 |
由于外设寄存器、全局变量、静态变量起始地址是固定的,DP 只需要配置一次,高效又节省指令空间。
4. 举个例子
假设有一个 UART 外设:
#define UART_DR (*(volatile unsigned char*)0x2002)
#define UART_SR (*(volatile unsigned char*)0x2004)
如果我们设置:
DP = 0x2000
Offset(UART_DR) = 0x02
Offset(UART_SR) = 0x04
那么:
UART_DR→ 有效地址 =DP + 0x02 = 0x2002UART_SR→ 有效地址 =DP + 0x04 = 0x2004- 不需要每次写完整 16 位地址。
5. 总结
这句话的核心意思是:
Direct Addressing Mode 通过 DP寄存器 + Offset 拼接完整地址,
非常适合访问那些起始地址固定的内存区域:
- 外围寄存器(外设控制寄存器)
- 全局变量
- 静态变量
因为:
- 页号固定 → DP 只需初始化一次
- 偏移量小 → 指令只需写 Offset,节省 ROM
- 效率高 → 访问速度快
如果你想,我可以给你画一张图,展示:
- 64KB 内存划分
- 外设寄存器所在的页
- 全局变量所在的页
- DP + Offset 如何快速定位到这些固定地址
我来用中文详细分析 Stack Addressing Mode(堆栈寻址模式) 这段话,结合 C28x DSP 的特性,逐句解释。
1. 基本概念
Stack Addressing Mode(堆栈寻址模式)是一种基于栈指针 SP (Stack Pointer) 的寻址方式,用于访问软件堆栈 (software stack) 上的数据。
SP (Stack Pointer):
是一个 16 位寄存器,用于指向软件栈的当前位置。
2. C28x 软件栈特点
文中提到的 C28x 是 TI C2000 DSP 内核,栈有几个特点:
(1) 软件栈在内存中是连续区域
-
软件栈 (software stack) = 程序专用的一块内存空间。
-
用于保存:
- 函数返回地址
- 局部变量
- 寄存器现场
- 中断上下文
-
这块内存由 SP 寄存器管理。
(2) 栈从低地址向高地址增长
“The software stack grows from low to high memory on the C28x”
不同 CPU 架构,栈的增长方向不一样:
- 大多数 MCU:栈从高地址向低地址增长(ARM、x86 等)。
- C28x DSP:栈从低地址向高地址增长。
比如:
初始 SP = 0x2000
PUSH 一个 2 字节数据 → SP = 0x2002
再 PUSH 一个 2 字节数据 → SP = 0x2004
(3) SP 总是指向“下一个空闲位置”
“the stack pointer always points to the next empty location”
区别于某些 CPU(SP 指向栈顶数据),C28x 的 SP 始终指向栈内下一个可用空位,方便 PUSH/POP 操作。
例如:
-
当前栈数据:
[0x2000] = 0xAAAA [0x2002] = 0xBBBB [0x2004] = (空) -
此时 SP = 0x2004(指向下一个空位置)。
3. 指令中的 Offset 用法
“The instruction supplies a 6-bit offset field that is subtracted from the current stack pointer value for accessing data on the stack”
- 指令会带一个 6 位 Offset,用于访问栈上已有数据。
- CPU 会用:
有效地址 = SP - Offset
而不是 SP + Offset,因为 SP 指向“下一个空位”,想访问栈上的旧数据,必须往回退。
举例
假设:
- SP = 0x2008
- 指令中 Offset = 4
那么访问地址:
有效地址 = SP - 4 = 0x2008 - 0x0004 = 0x2004
4. PUSH / POP 操作
“the stack pointer can be post-incremented or pre-decremented when pushing and popping data from the stack”
(1) PUSH 操作(压栈)
- 把数据存到栈顶
- 先写数据,再 SP 增加
- 叫做 post-increment(后增)
PUSH ACC
假设:
SP = 0x2000
PUSH 2 字节
过程:
[0x2000] = ACC
SP = SP + 2 → 0x2002
(2) POP 操作(出栈)
- 从栈顶读取数据
- 先 SP 减少,再读数据
- 叫做 pre-decrement(先减)
POP ACC
假设:
SP = 0x2004
POP 2 字节
过程:
SP = SP - 2 → 0x2002
ACC = [0x2002]
5. 总结
| 概念 | 说明 |
|---|---|
| SP (Stack Pointer) | 16 位寄存器,指向栈中下一个空位置 |
| 软件栈 | 存储函数返回地址、局部变量、寄存器现场等 |
| 栈增长方向 | C28x 从 低地址 → 高地址 |
| SP 指向 | 下一个空闲位置 |
| Offset 寻址 | 指令提供 6 位 Offset,SP - Offset 访问已有数据 |
| PUSH | 先写数据,SP 后增(post-increment) |
| POP | SP 先减,后读数据(pre-decrement) |
如果你想,我可以给你画一张 C28x 软件栈示意图,标出:
- 栈的增长方向
- SP 的指向
- PUSH / POP 动作
- Offset 访问方式
明白😊,我来详细分析 Register Addressing Mode(寄存器寻址模式) 在 C28x DSP 架构中的含义、特点和应用场景。
这段话是:
“In this mode, another register can be the source or destination operand of an access.
This enables register-to-register operations in the C28x architecture.”
我们一步一步解析。
1. 什么是 Register Addressing Mode
寄存器寻址模式(Register Addressing Mode)是 C28x 指令系统中最直接、最快速的一种寻址方式。
- 指令操作数直接是寄存器,而不是内存地址。
- 参与运算的两个操作数可以都在寄存器里。
- 目标操作数(destination)也可以是寄存器。
2. 指令操作数的来源与去向
(1) Source Operand(源操作数)
- 从一个寄存器中读取数据作为输入。
- 例如:
ADD ACC, AR1
含义:
ACC = ACC + AR1
这里,AR1 作为源操作数。
(2) Destination Operand(目的操作数)
- 运算结果可以直接写回某个寄存器。
- 例如:
MOV AR2, ACC
含义:
AR2 = ACC
这里,AR2 作为目的操作数。
(3) Register-to-Register 操作
这句话:
“This enables register-to-register operations in the C28x architecture.”
意思是:
C28x 架构支持寄存器到寄存器之间的直接操作,无需访问内存。
例如:
MOV AR0, AR1
含义:
AR0 = AR1
- 数据在寄存器间直接传递,速度最快。
- 无需经过数据总线访问内存。
3. 与其他寻址模式的对比
| 寻址模式 | 操作数来源 | 是否需要访问内存 | 速度 | 常用场景 |
|---|---|---|---|---|
| Register Addressing | 直接寄存器 | 否 | 最快 | 寄存器之间的数据计算 |
| Immediate Addressing | 指令中写死的常量 | 否 | 快 | 常量计算 |
| Direct Addressing | DP + Offset 指向内存 | 是 | 中等 | 外设寄存器,全局变量 |
| Indirect Addressing | XARn 指向的内存 | 是 | 较慢 | 数组、表、缓冲区 |
| Stack Addressing | SP + Offset 指向栈 | 是 | 较慢 | 局部变量、函数调用 |
C28x 使用寄存器寻址模式时,完全绕过内存,速度最快,非常适合高频操作。
4. 常用寄存器类型
在 C28x 中,常见的寄存器有:
| 寄存器 | 位宽 | 用途 |
|---|---|---|
| ACC | 32 位 | 累加器,主要用于算术运算 |
| P | 32 位 | 乘法器结果寄存器 |
| AR0~AR7 | 16 位 | 通用寄存器,可用于运算或索引 |
| XAR0~XAR7 | 32 位 | 扩展地址寄存器,用于间接寻址 |
| SP | 16 位 | 栈指针 |
| DP | 16 位 | 数据页指针 |
寄存器寻址模式可以在这些寄存器之间直接操作数据,避免访问内存。
5. 示例
(1) 两寄存器相加
ADD AR0, AR1
含义:
AR0 = AR0 + AR1
(2) 把数据从累加器移到寄存器
MOV AR2, ACC
含义:
AR2 = ACC
(3) 从寄存器拷贝到寄存器
MOV AR3, AR7
含义:
AR3 = AR7
6. 总结
| 特性 | 说明 |
|---|---|
| 操作数位置 | 操作数直接在寄存器中 |
| 源寄存器 | 可直接用作输入 |
| 目的寄存器 | 运算结果可直接写回 |
| 效率 | 最快的寻址方式 |
| 应用 | 高频计算、寄存器间数据传递 |
C28x 使用寄存器寻址模式可以实现高速寄存器到寄存器运算,不需要访问内存,非常适合 DSP 高频运算场景。
如果你想,我可以给你画一张图,展示:
- 两个寄存器之间直接操作数据
- 和访问内存相比,寄存器寻址模式为什么速度更快


浙公网安备 33010602011771号