历史上的今天
返回首页

历史上的今天

今天是:2025年03月30日(星期日)

正在发生

2020年03月30日 | 什么是ARM中的SP(堆栈)和LR?

2020-03-30 来源:eefocus

问题描述

我一遍又一遍地阅读定义,我还没有得到什么是ARM中的SP和LR?我明白PC(它显示下一个指令的地址),SP和LR可能是相似的,但我只是不明白它是什么。你可以帮我吗?

编辑:如果你可以用例子说明一下,那会很棒。

编辑:终于弄清楚LR是什么,还没有得到什么SP。


link register。

SP是堆栈指针。堆栈通常用于在函数调用中保存”automatic”变量和上下文/参数。从概念上讲,您可以将”stack”视为您”pile”您的数据的地方。您将”stacking”保留在一个数据之上,堆栈指针告诉您”high”的数据是”stack”。您可以从”stack”的”top”中删除数据并缩短。


从ARM架构参考:

SP, the Stack Pointer

Register R13 is used as a pointer to the active stack.

In Thumb code, most instructions cannot access SP. The only instructions that can access SP are those designed to use SP as a stack pointer. The use of SP for any purpose other than as a stack pointer is deprecated. Note Using SP for any purpose other than as a stack pointer is likely to break the requirements of operating systems, debuggers, and other software systems, causing them to malfunction.

LR, the Link Register

Register R14 is used to store the return address from a subroutine. At other times, LR can be used for other purposes.

When a BL or BLX instruction performs a subroutine call, LR is set to the subroutine return address. To perform a subroutine return, copy LR back to the program counter. This is typically done in one of two ways, after entering the subroutine with a BL or BLX instruction:

• Return with a BX LR instruction.

• On subroutine entry, store LR to the stack with an instruction of the form: PUSH {,LR} and use a matching instruction to return: POP {,PC} …

This link gives an example of a trivial subroutine.

Here is an example of how registers are saved on the stack prior to a call and then popped back to restore their content.


http://github.com/lsasim我创建了一个教学处理器,并有一个汇编语言教程。在那里我会经历关于堆栈的讨论。它不是一个手臂处理器,但故事是一样的,它应该直接转换到你想要在手臂或大多数其他处理器上理解。


例如,您的程序中需要20个变量,但只有16个寄存器减去至少三个(sp,lr,pc),这些是特殊用途。你将不得不将一些变量保留在ram中。让我们说r5拥有一个你经常使用的变量,你不想保持在ram中,但是有一段代码,你真的需要另一个注册表来做某事,r5没有被使用,你可以保存r5堆栈以最小的努力,而您重用r5的其他东西,然后,很容易,恢复它。

传统(不一定都回到起初)手臂语法:


...

stmdb r13!,{r5}

...temporarily use r5 for something else...

ldmia r13!,{r15}

...


stm是存储多个,一次可以保存多个寄存器,直到所有这些都在一个指令中。


db表示之前递减,这是从高地址到较低地址的向下移动堆栈。


您可以使用r13或sp来指示堆栈指针。该特定指令不限于堆栈操作,可用于其他操作。


的!意味着在完成后用新地址更新r13寄存器,这里再次使用stm可以用于non-stack操作,因此您可能不想更改基地址寄存器,离开!在这种情况下。


然后在括号{}中列出要保存的寄存器,以逗号分隔。


ldmia是相反的,ldm表示加载多个。 ia表示递增,其余与stm相同


所以如果你的堆栈指针在0x20008000,当你打到stmdb指令看到,因为列表中有一个32位寄存器,它将在它使用它之前减少r13中的值,所以0x20007FFC然后它在存储器中写入r5到0x20007FFC,并保存值0x137FFC在r13。后来,假设你没有错误,当你得到ldmia指令r13有0x20007FFC在其中有一个单一的注册表在列表r5。所以它在0x20007FFC读取内存将该值放在r5中,ia表示增量后,0x20007FFC将一个寄存器大小增加到0x20008000,而!意味着将该号码写入r13以完成指令。


你为什么要使用堆栈而不是固定的内存位置?那么上面的美妙之处在于,当您运行该代码或0x20002000或其他任何代码仍然可以运行时,r13可以是0x20007654,如果您在循环中使用该代码,或者在循环中使用该代码,或者对于每个级别您递交的递归保存r5的新副本,您可能有30个保存的副本,具体取决于您在该循环中的位置。并且当它展开时,将所有副本放回所需的位置。单个固定内存位置不起作用。这将直接转换为C代码作为示例:


void myfun ( void )

{

   int somedata;

}


在这样的C程序中,变量somedata存在于堆栈中,如果您递归调用myfun,则根据递归的深度,您将有多个副本的somedata值。此外,由于该变量仅在函数内部使用,并且不需要其他位置,那么您可能不想在程序的生命周期内为该变量刻录一定量的系统内存,只需要在该函数中使用这些字节,并释放该内存不在那个功能。这就是堆栈的用途。


在堆栈中找不到全局变量

回去…

说你想实现和调用这个函数,你会在调用myfun函数时有一些代码/函数。 myfun函数希望使用r5和r6,当它正在操作的东西,但它不想垃圾的任何人称它是使用r5和r6这样的持续时间的 myfun()你想要保存在堆栈上的这些寄存器。同样,如果您查看分支链接指令(b1)和链接寄存器lr(r14),则只有一个链接寄存器,如果从函数调用函数,则需要在每次调用时保存链接寄存器,否则您无法返回。


...

bl myfun

    <--- the return from my fun returns here

...

 

 

myfun:

stmdb sp!,{r5,r6,lr}

sub sp,#4 <--- make room for the somedata variable

...

some code here that uses r5 and r6

bl more_fun <-- this modifies lr, if we didnt save lr we wouldnt be able to return from myfun

   <---- more_fun() returns here

...

add sp,#4 <-- take back the stack memory we allocated for the somedata variable

ldmia sp!,{r5,r6,lr}

mov pc,lr <---- return to whomever called myfun.


所以希望你可以看到堆栈的使用和链接寄存器。其他处理器以不同的方式做同样的事情。例如有些将把返回值放在堆栈上,当你执行返回函数时,它通过从栈中拉一个值来知道在哪里返回。编译器C /C++等通常会有一个”calling convention”或应用程序接口(ABI和EABI是ARM定义的名称)。如果每个函数遵循调用约定,则将参数传递给在正确的寄存器或堆栈中被调用的函数。并且每个函数遵循规则,关于什么寄存器不必保留其内容和什么寄存器来保存内容,那么你可以使用函数调用函数调用函数,并执行递归和各种事情,只要堆栈不会太深,以至于它运行到用于全局变量和堆的内存中,所以您可以调用函数并从整个日期返回。 myfun的上述实现与编译器生成的内容非常相似。


ARM现在有很多核心和一些指令集,cortex-m系列的工作原理有所不同,只要没有一堆模式和不同的堆栈指针。并且在拇指模式下执行拇指指令时,您可以使用推送和弹出指令,这些指令不会让您自由使用任何类似stm的寄存器,它只使用r13(sp),而且您无法仅将所有寄存器保存在其特定子集中。流行的手臂组装人员允许您使用


push {r5,r6}

...

pop {r5,r6}


手臂代码以及拇指代码。对于arm代码,它编码适当的stmdb和ldmia。 (在缩略图模式下,您也不必选择使用db的时间和位置,之前递减,ia,后增加)。


不,您绝对不必使用相同的寄存器,您不必配对相同数量的寄存器。


push {r5,r6,r7}

...

pop {r2,r3}

...

pop {r1}


假设在这些指令之间没有其他堆栈指针修改,如果你记得sp将被递减12个字节的推送,我们说从0x1000到0x0FF4,r5将被写入0xFF4,r6到0xFF8和r7到0xFFC堆栈指针将变为0x0FF4。第一个pop将取值为0x0FF4,并将其放在r2中,然后将值置于0x0FF8,并将其置于r3中,堆栈指针将获取值0x0FFC。稍后最后一个pop,sp为0x0FFC,读取的值为r1,然后堆栈指针的值为0x1000,在那里开始。


ARM ARM,ARM架构参考手册(infocenter.arm.com,参考手册,找到适用于ARMv5并下载的手册,这是ARM ARM与ARM和Thumb指令的传统ARM),包含ldm和stm ARM的伪代码关于这些如何使用的完整图片。同样,整本书都是关于手臂和如何编程的。在程序员模型章节前面将介绍所有模式下的所有寄存器等。


如果您正在编程ARM处理器,您应该首先确定(芯片厂商应该告诉您,ARM不会使芯片使芯片厂商的芯片成为芯片厂商的核心)。然后去arm站,找到那个家族的ARM ARM,找到特定内核的TRM(技术参考手册),包括修正版本(如果供应商提供的)(r2p0表示版本2.0(二点零,2p0)),甚至如果存在较新的转速,请使用与设计中使用的供应商所使用的手册。不是每个核心都支持每个指令或模式,TRM告诉您ARM ARM支持的模式和指令,总结了核心所处的整个处理器系列的功能。请注意,ARM7TDMI不是ARMv7,而是ARMv7 ARM9不是ARMv9。 


ARMvNUMBER是家族名称ARM7,ARM11没有v是核心名称。较新的内核具有像Cortex和mpcore这样的名称,而不是ARMNUMBER的东西,这减少了混乱。当然,他们不得不通过制造一个非常不同的系列的ARMv7-m(cortex-MNUMBER)和ARMv7-a(Cortex-ANUMBER)来增加混乱,一个用于重负载,台式机,笔记本电脑等,另一个是微控制器,时钟并在咖啡壶和类似的东西上闪烁的灯光。谷歌beagleboard(Cortex-A)和stm32值行发现板(Cortex-M)得到感觉的差异。或者甚至使用多于千兆赫兹的多核的open-rd.org板,或者来自nvidia的更新的tegra 2,相同的交易超级定标器,多核,多吉赫兹。 cortex-m几乎没有制动100MHz的屏障,并且以千字节测量的内存,尽管如果你想要一个cortex-a的地方,它可能会运行一个电池几个月。


对于很长的帖子很抱歉,希望它是有用的。

What are SP (stack) and LR in ARM?


注:本文内容整合自google/baidu/bing辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:gxnotes#qq.com(#替换为@)。

推荐阅读

史海拾趣

Dexter Research Center Inc公司的发展小趣事

Dexter Research Center Inc.(以下简称Dexter)最初是由一群热衷于电子科技研究的科学家和工程师组成的实验室。他们热衷于探索新的传感器技术,并在实验室环境下取得了多项技术突破。然而,技术的真正价值在于其商业化应用。Dexter意识到这一点,决定将研究成果转化为实际产品,推向市场。经过数年的努力,Dexter成功开发出了一系列高性能、高精度的传感器产品,并受到了市场的热烈欢迎。

蓝箭(BLUE ROCKET)公司的发展小趣事

为了提高产品质量和客户满意度,蓝箭电子从1997年开始通过ISO9001质量管理体系认证。随后,公司还通过了ISO14001环境管理体系认证、ISO/TS16949汽车行业质量管理体系标准认证以及OHSAS18001认证。这些认证不仅提升了公司的管理水平,也增强了客户对公司的信任。

Collins Electronics Corp公司的发展小趣事

Collins Electronics Corp的创始人在电子领域拥有深厚的背景和丰富的经验。在公司创立初期,他们发现市场上的电子设备在性能和稳定性上存在巨大的提升空间。于是,他们决定创立一家公司,专注于研发和生产高品质的电子设备。经过多次试验和改进,Collins Electronics Corp推出了他们的首款产品,一款高性能的信号放大器。这款产品凭借其卓越的性能和稳定性,在市场上获得了极大的成功,也为公司的后续发展奠定了坚实的基础。

Echelon_Corporation公司的发展小趣事

进入21世纪后,Echelon继续拓展其业务范围,于2003年推出了网络能源服务系统(NES)。该系统是一个开放式的电表基础设施,旨在提高能源使用效率和管理水平。NES系统很快在全球范围内得到了广泛应用,特别是在意大利的智慧型电表基础建设中,Echelon的技术得到了大量使用,连接了数以千万计的电表。随着NES系统的成功推广,Echelon在能源管理领域的地位得到了进一步提升。

Cramer公司的发展小趣事

在早期的发展阶段,Cramer公司推出了一款革命性的智能手机。这款手机采用了最新的芯片技术和高分辨率显示屏,为用户提供了出色的使用体验。为了满足市场需求,Cramer公司加大了研发投入,不断优化产品性能。最终,这款手机在市场上取得了巨大的成功,为Cramer公司带来了可观的收益,并奠定了其在电子行业中的地位。

Catalyst公司的发展小趣事

Catalyst公司深知品质是企业生存和发展的根本。因此,公司始终将品质管理放在首位,从原材料采购到生产加工、产品检验等各个环节都进行严格把控。公司还建立了完善的售后服务体系,确保客户在使用过程中能够得到及时、专业的技术支持。这些举措不仅提升了Catalyst产品的品质水平,也赢得了客户的信任和好评。

问答坊 | AI 解惑

职业生涯规划书籍-选对池塘钓大鱼

毕业后在同一单位的不同部门之间摸爬滚打多年,至今一事无成。 逐渐意识到个人的成就是建立在清晰的个人规划上。 向大家推荐本老书,希望能对大家有所启发。 [ 本帖最后由 dingchuan 于 2009-3-16 12:41 编辑 ]…

查看全部问答>

ATmega16

ATmega16_cn 正文版数据手册  想要的就别客气 高手路过 免费下载…

查看全部问答>

大开眼界——国产球

国产球机三大生产基地是:京津,江浙,广东,豫鲁地区。 国内球机经过15-20年的发展(球机在国内大约时间是1993-96年起步),现早已成熟。经过白热化的发展,除了国内几个可数品牌球价格不动摇。其他小厂球机价格在市场竞争中,不得已价格比以前低 ...…

查看全部问答>

一种简单实用方便的集成块去焊方法

下面这一段是我在网上看到的“ 在我们这次电子设计比赛中,我队友发现了一种取多角元件(直插式)的方法,我小试一下,真的很好用,且简单。 小弟们不敢独享,道出来分享一下:当你发现集成块第东西需要取下来时,你会用什么方法呢? ————— ...…

查看全部问答>

2440的NAND FLASH有坏块怎样解决?

如题,请问有没有办法避免在文件系统下载进了K9F1208之后出现坏块?这样系统就被搞死了....…

查看全部问答>

【求助】串口数据发送不完整问题

平台:s3c2440 + wince5 按标准的流驱动模型,编写了一个UART的测试驱动Dll,开发板UART与PC串口相连 //因无法上网只能写个大概了,程序大致如下 #define UART_BASE 0xB1004000 #define INT_BASE  0xB0A00000 #define IOP_BASE & ...…

查看全部问答>

推荐几本计算机组成原理的书

各位大侠给小弟提供提供意见吧…

查看全部问答>

C语言和汇编之间的函数参数传递

本帖最后由 dontium 于 2015-1-23 13:33 编辑 数组如何传递? 比如int  vadd(int n,int a[],int b[]) a+=b,a & b 均有n个元素 n传输到寄存器A里面了 那么栈中的a,b呢? 是地址吗? 如何获取地址以及数组元素? 请大虾指点 谢 ...…

查看全部问答>

msp430 uart

请问一下哪位大哥有关于MSP430F149的串口发送字符串的程序啊,带参数的,谢谢!472283165@qq.com…

查看全部问答>