1. 从“搬箱子”开始:理解ARM汇编数据搬运的底层逻辑
如果你刚开始接触ARM汇编,看到LDR、STR、LDM、STM这一堆指令,是不是感觉头都大了?别担心,这太正常了。我刚开始学的时候,也在这几个指令上绕了很久的弯路,特别是它们之间那些微妙的、反直觉的差异。今天,我就用最“小白”的方式,把我踩过的坑和总结的经验分享给你,保证你看完就能分清谁是谁,并且知道在什么场合该用谁。
你可以把CPU里的寄存器和内存的关系,想象成你家里的工作台和大仓库。寄存器(比如R0, R1, R2)就是你手边的工作台,空间很小但拿东西放东西特别快;内存就是你家后面的大仓库,空间巨大,但每次存取东西都得跑一趟,速度慢。我们写程序,本质上就是不断地在“工作台”(寄存器)和“仓库”(内存)之间搬运数据。
LDR和STR,就是一次只搬一个箱子的指令。你想从仓库里拿一个零件(数据)到工作台上处理,就用LDR;处理完了,要把成品放回仓库,就用STR。简单直接,是编程中最基础、最常用的操作。
而LDM和STM,则是开着小叉车,一次搬一整摞箱子的指令。当你需要把工作台上好几个工具(多个寄存器)一次性收拾起来存进仓库,或者从仓库里一次性把一套工具全摆上工作台时,就用它们。这通常发生在函数调用、中断处理或者需要高效批量操作数据的场景里。
最让人困惑的点来了:为什么“一次搬一个”和“一次搬一堆”的指令,写法上好像把“谁搬谁”的顺序给反过来了呢?别急,我们后面会掰开揉碎了讲。你只需要先记住,这不是设计缺陷,而是ARM指令集为了区分这两种截然不同的操作模式而特意设定的语法。理解了这一点,你就成功了一半。
2. 单件搬运大师:LDR与STR的深度解析与应用
2.1 LDR:从内存“加载”到寄存器
LDR指令,全称是 LoaD Register。它的核心动作是:从内存中读取一个值,放到寄存器里。记住这个方向:内存 -> 寄存器。
我们来看一个最基础的例子:
LDR R1, [R2]
这条指令怎么理解?咱们拆开看:
LDR:指令本身,意思是“加载”。R1:目标,也就是“搬到哪儿去”。它是一个寄存器。[R2]:来源,也就是“从哪儿搬”。[ ]这个括号在汇编里非常重要,它表示“取这个寄存器里存放的地址所对应的内存位置的值”。所以[R2]不是说操作R2这个寄存器本身,而是把R2的值当作一个门牌号,去这个门牌号对应的房间里把东西拿出来。
所以,LDR R1, [R2] 的完整操作是:CPU先去查看R2寄存器里存的是一个什么数字(比如0x20001000),然后它跑到内存中地址为0x20001000的地方,把那里存放的4个字节(32位系统)的数据读出来,最后把这个数据塞到R1寄存器里。
我刚开始总记混,后来用一个笨办法:看英文。LD是Load,加载,那肯定是把东西“装进来”。装到哪儿?装到紧跟指令后面的那个“容器”里。所以LDR后面第一个位置,就是目的地——寄存器。
2.2 STR:从寄存器“存储”到内存
STR指令,全称是 STore Register。它的动作和LDR正好相反:把寄存器里的值,存到内存里去。方向是:寄存器 -> 内存。
看这个例子,和上面那个是绝配:
STR R1, [R2]
STR:指令,意思是“存储”。R1:来源,也就是“搬什么东西”。它是数据的源头。[R2]:目标,也就是“搬到哪儿去”。同样,[R2]表示R2里存的那个地址所指向的内存位置。
所以,STR R1, [R2] 的操作是:CPU把R1寄存器里的数据拿出来,然后找到R2寄存器里存放的地址(比如0x20


935

被折叠的 条评论
为什么被折叠?



