2.CPU体系架构-寄存器
CPU通用寄存器是CPU体系结构的重要组成部分,在指令执行过程中发挥着关键作用。以下是几种常见处理器通用寄存器的主要特点:
8086处理器
- 通用数据寄存器:AX、BX、CX、DX(16位),可分解为AH/AL等高位低位寄存器。
- 通用地址指针寄存器:SP、BP、SI、DI(16位)。
- 段寄存器:CS、DS、SS、ES(20位)用于存储寻址。
- 标志寄存器FLAGS(16位)。
- 指令指针寄存器IP(16位)。
ARM7处理器- 数据寄存器:r0~r15(32位),程序状态寄存器CPSR(16位)。
- 寄生功能:堆栈指针寄存器r13作为SP;链接寄存器r14作为LR;程序计数员r15作为PC。
MIPS32处理器- 通用寄宿 register 0~31(32位)。
- 特殊用途:
- $29模拟SP功能。
- $30模拟帧指针FP功能。
- $31模拟返回地址RA功能。
堆栈指针与返回地址- X86使用SP作为堆栈指针;ARM使用r13;MIPS使用$29;返回地址分别通过LR/LA指令管理。
其他特点- MIPS还引入了帧指针FP用于复杂调用机制。
- 程序计数员PC在RISC架构中通常隐藏不对外可见。
- 全局指针GP在MIPS中用于静态数据加载地址管理。
总结:不同处理器的通用寄宿 register设计各有特点,主要围绕数据存储与访问机制展开。理解这些机制对学习汇编语言和优化程序性能至关重要。
在现代计算机体系架构中,CPU通用寄存器扮演着不可或缺的角色。这些寄存器在进行算术逻辑运算时最为直接和频繁地使用。针对采用RISC架构的中央处理器(CPU),其算术逻辑运算功能仅限于对内存中的通用寄存器数据进行操作。我们的目标并非旨在详尽阐述各类CPU架构及其寄存器配置的具体细节,而是对那些在不同处理器架构中常被混淆使用的常见寄录进行归纳与整理。以下将以8086处理器为例展开详细说明;随后介绍ARM7内核的设计方案;最后则聚焦于MIPS32内核的具体实现模式等三个典型案例来进行深入分析与对比研究
8086处理器通用寄存器
对于学习X86系列处理器的基础知识而言
通用的数据寄存器包括AX、BX、CX和DX四个类型。
每个16位的通用数据寄存器都包含两个8位部分。
每个16位的通用数据寄存器可以划分为高低两个8位部分来使用。
例如AX通常被分割为AH(高)和AL(低)两个8位部分来处理数据。
SP、BP、SI、DI这四个通用地址指针寄存器仅能以16位偏移地址值的形式进行存储,并且主要用于存储该存储器段内的16位偏移地址值。
SP、BP、SI、DI这四个通用地址指针寄存器仅能以16位偏移地址值的形式进行存储,并且主要用于存储该存储器段内的16位偏移地址值。
与通用地址指针寄存器对应的是8086系统中的4个16位段寄存器。这四个段寄存器分别称为基址 registers CS、DS、SS 和 ES。它们与四个地址指针 registers 共同作用下生成20位的完整内存地址。这个完整的20位地址被用来进行存储器的地址计算。
然后就是标志寄存器FLAGS,也是16位。相当于ARM7中的程序状态寄存器cpsr。
最后阶段是由16位指令指针寄存器IP负责管理,并存储当前即将执行的指令对应的16位偏移地址。这类似于RISC处理器内部所使用的程序计数器PC寄存器。

ARM7处理器通用寄存器
该处理器采用的是基于ARMv4架构的设计模式,并且是相当多学习者的第一款处理器选择。
在后续介绍的通用寄存器上没有局限性,在这些架构中它们都具有相似的功能和作用。
为了便于理解这些概念,在这里我们以一个典型的RM7处理器为例进行讲解。
ARM7中的通用寄存器主要包含有数据存储单元和状态指示单元。因为ARM核心设计支持多种运行模式,在本系统中我们采用了主流的通用用户模式。在通用用户配置下共有编号从r0到r15的数据存储单元以及一个状态指示单元 cpsr。这些存储模块均为32位深度设计。
在16个数据寄存器中,末尾三个寄存器(即r13、r14、r15)各自具有特定功能。值得注意的是,在某些情况下,即使这些寄存器通常被用于特定操作(如r15用于程序计数),但事实上,在某些程序设计中它们也可以作为通用寄存器使用。
*r13负责SP寄存器(SP),用于存储堆栈顶端地址。
*r14负责LR寄存器(LR),用于保存被调用子程序的返回地址。
*r15控制程序流程的PC寄存器。
改写说明

MIPS32处理器通用寄存器
以下是按照要求进行的文本改写

以下是对几种特定功能的X86与ARM处理器寄存器进行对比分析。
- $29用于作为堆栈指针寄存器(sp),负责存储堆栈顶端的位置。
- 该存储单元与x86架构中的SP指令相同,在ARM架构中对应r13(sp)。
- $30用于表示帧起始位置。
- $31是返回地址寄存器(ra),类似于ARM中的LR指令,负责存储调用子程序返回时所需的位置信息。
除了上述之外,在处理子程序调用时,MIPS对寄存器的应用进行了细致的规定。举例而言,在传递返回值的过程中,默认采用的是寄存器2和3,而用于传递参数的部分,则主要依赖于寄存器组4至7。由此可见,在深入理解MIPS的工作机制时,还需结合软件编译的相关知识进行学习
下面,我们就X86,ARM,MIPS中几个常用的,特殊的寄存器做一个详尽的说明。
堆栈指针寄存器sp
可以看到,在X86、ARM和MIPS架构中都设置了堆栈指针寄存器。其中X86架构通过通用地址指针寄存器中的SP字段来实现堆栈操作;而ARM架构则将第14个通用寄存器r13指定为pile(堆栈操作)相关的存储空间;MIPS架构则采用第30个通用寄存器$29来完成相关操作。需要注意的是,在这些体系中虽然它们的功能相似但具体实现细节存在细微差别:例如在某些体系中可能会使用专门的pile registers来提高效率或简化设计逻辑等细节问题。
X86架构中的堆栈指针寄存器(SPU)具有特殊功能特性,在设计上专为存储结构进行操作,并提供pop与push指令以完成相应的存储/恢复操作(即入栈与出栈)。相比之下,在ARM与MIPS架构中,默认配置下的堆栈指针寄存器属于通用数据寄存器范畴,在功能定位上与其它通用数据寄存器无明显差异。值得注意的是,在这些架构下执行存储/恢复操作(即入栈与出栈)并不像在X86系统中那样提供特定指令支持;相反地,则依赖于普遍性的算术运算指令(如add与sub)来完成相应的存储/恢复动作。
在特定的应用场景中,ARM寄存器r13(sp)可以被当作通用寄存器来使用。
另外,在计算机软件领域中存在一个基础概念——"堆栈"。作为中央处理器(CPU)的核心组件,在程序执行过程中发挥着关键作用。虽然这个比喻可能让人会心一笑(实际上CPU不具备这种特殊功能),但为了便于理解我们仍然采用了这一表述方式。为了实现对程序运行所需的临时数据进行有效管理与保存,因此设计了堆栈指针寄存器这一重要机制。该寄存器的主要功能是记录当前处理的数据存储地址;其中心作用在于为后续操作提供可靠的存储位置参考点。在某些特定情况下(如无函数调用、无局部存储需求等),堆栈指针寄存器其实无需发挥作用;这也是为什么在RISC架构中即使没有特别的函数调用机制,在某些情况下RISC处理器的sp寄存器仍然可以承担通用的数据操作功能。
哪些程序不需要采用堆栈这种数据结构来进行数据保存?这个问题涉及到一个核心概念:跟踪调用链(call stack)。解决这些问题的经典方法是在堆栈中记录活动过程(processes),例如C语言就采用了这一方法。某些编程语言如Mesa和Cedar通过将过程记录以链表形式分配在内存堆中实现了同样的效果。
在某些功能较为特殊或结构较为简单的芯片上,虽然可能具备堆栈概念。例如,在汇编语言中规定,采用了深度仅为2的堆栈机制来进行分支跳转操作。因此,在这种架构下运行时所允许的嵌套式分支跳转次数被限制在最多2次。值得注意的是,在这种情况下所说的堆栈与我们通常意义上的数据存储机制存在显著差异。
如果你希望深入掌握堆栈及其指针sp之间的关系,请建议通过C语言函数调用来进行实践操作。在后续的内容中会有详细的操作步骤说明。
链接寄存器lr/返回地址寄存器ra
ARM架构中的链接寄存器lr与MIPS架构中的返回地址寄存器ra在功能上具有等价性。两者均被视为一种通用目的寄存器,在程序执行过程中被定义为负责存储程序中断时所需的返回地址。这些中断操作特指那些需要执行返回处理的指令集操作码(如MIPS体系中的jal、bal指令)。实际上并不等同于函数调用过程中的转移操作。
X86架构并未配备专门用于存储跳转指令返回地址的寄存器。相反,在执行跳跃操作时,默认情况下会利用堆栈来完成这一功能。具体来说,在执行call指令进行跳跃时(对应于RISC架构中的return操作),程序会将当前线程的状态信息和程序计数器值等关键数据自动推入堆栈中完成保存工作(而RISC架构则通常会直接将return地址存储在专门的寄存器中)。当程序需要从子程序或函数中退出时(对应于RISC架构中的return操作),执行ret指令后会将程序计数器值从堆栈顶位置读取并将其设置为当前机器代码段的位置(对应的RISC架构则通常会使用jr $ra这条指令来完成同样的操作,并无需依赖特定的return指令实现这一功能)。
帧指针寄存器fp
在MIPS架构中,帧寄存器fp是一个特别设计的寄存器。该寄存器负责管理C语言函数调用时的行为。其主要作用是为了支持计算机程序中的堆栈操作,并与SP(stack pointer register)相同。
在MIPS体系架构中,默认情况下存在一个特殊的通用寄存器$8,通常被称作帧指针(frame pointer, fp)。这一特定的命名方式并非仅限于MIPS架构,在x86处理器如X86以及 arm架构如arm处理器等体系中均未采用类似的命名策略。然而这并不意味着它们在x86体系与arm架构体系中完全缺乏功能。实际上,在x86体系结构中,默认使用的机制是通过通用地址寄存器中的BP寄存器来模拟帧指针的功能。这一设置有助于实现对内存保护区域的有效管理以及对堆栈操作的支持。至于arm架构是否也采用了类似的机制来处理内存保护与堆栈操作等问题,则是一个值得探讨的话题了。
那么,请问帧指针寄存器的作用是什么?关于fp/sp(MIPS体系)以及ebp/esp(X86体系)的相关知识,请参考C语言-栈的相关章节。涉及堆栈帧构造、活动记录维护以及调用惯例的具体实现等核心概念。建议深入理解相关内容的读者,请参考《程序员自我修养:链接、装载与库》一书中第10.2节——栈和调用惯例部分。
程序计数寄存器
X86与ARM架构均具备程序寄存器系统。其中,在X86体系中,其核心的通用控制单元(CPU)配置了一个指令指针寄存器ip来管理指令流地址;而ARM架构则采用了通用处理单元(SPU)结构,并在其控制器中设置了通用目的 register r15作为主要的数据通路控制 register。值得注意的是,在MIPS架构中并不存在独立的程序寄存器系统。
程序寄存器PC(Program Counter)的作用是指示当前程序执行的位置。具体而言,则是指当前指令的下一条指令的地址,并告知CPU需要前往何处获取下一条指令。那么MIPS为何不配备程序寄存器呢?事实上,在设计之初并未将PC纳入体系结构中。这种设计选择背后的原因在于:为了提高流水线效率,MIPS系统舍去了传统的程序计数寄存器PC功能;此外,在流水线架构上还留下了加载延迟管道和跳转延迟管道等遗留问题。
全局指针寄存器
全局指针寄存器gp是MIPS架构中的一个通用寄存器$28,在其他架构如X86和ARM处理器中并未引入此类设计。与这些架构相比(gp)同样不具备此类功能的寄存器。
该寄存器的主要作用体现在两个方面:
其一主要用于追踪当前程序运行中的指令流起始位置;
其二则有助于优化指令执行流程并提高处理器的整体性能。
- 在PIC中,gp用来指向GOT(Global Offset Table)。注意,这里的PIC是指的Linux中共享库的PIC,而在很多BSP的boot loader中PIC只是简单的代码和地址无关,并不涉及到共享库,所以BSP中的gp的用法并不属于此类。
- 在嵌入式开发中,gp用来指向链接时决定的静态数据的地址。这样,对在gp所指地址正负各32K范围内数据的load和store(其实就是ld和sw指令),就可使用gp作为基址寄存器。在romInit()函数向C函数romStart()函数跳转以及usrStart()函数最开始都有gp的初始化。代码如下所示。
la gp, _gp # set global ptr from compiler
AI助手
那么,请问_gp具体指的是什么呢?通过反汇编查看bootrom的符号表可知,在链接过程中确定的一个静态数据存储位置,在我们的代码中大致位于内存地址0x801656a0处。
学习心得
处理器通用寄存器的设计显著影响了整个逻辑处理流程(包括具体的入栈和出栈操作、数据Load和store过程)以及算术运算的具体实现步骤。这些流程的确立也直接决定了汇编语言的组织方式也随之确定下来。这也意味着编译器必须具备将更高层次的语言(例如C语言)转化为完全符合处理器架构需求的高效汇编代码的能力。以下内容选自《ARM嵌入式系统开发-软件设计与优化》深入阐述了RISC与CISC在编译器与处理器之间的关系。
RISC的设计重点在于简化由硬件执行指令的复杂性,并非为了降低其难度。原因在于软件系统相较于硬件装置更能提供灵活的操作与更为智能的功能。相比之下,在这种设计理念下所开发出的编译器需要具备更高的处理能力;而传统上采用复杂指令集架构(CISER)设计的计算机则侧重于提升硬件层面指令操作的有效性与功能性,
从而导致其变得更加难以理解和维护。
我们可以用下面的图来概括和理解上面这段话的意思。

CPU结构体系进化主要包括两个关键方面:首先是芯片硬件设计方面的复杂性;其次是编译器优化工作的深化。值得注意的是,在某些语境中,“RISC”这一术语被戏称为“Relegate the Impossible Tasks to the Compiler”,即认为"将无法完成的任务交由编译器处理"。这种表述也恰当地体现了上图所要传达的核心观点
掌握寄存器与指令集之间的关系是一个重要课题。然而,在寄存器与指令集之间存在一个被常忽视的关键环节——寻址方式。我们需要深入探讨寻址方式,并将其作为后续研究的基础之一进行系统阐述。
