ARM汇编【2】:LOAD 和 STORE

news2024/12/24 21:29:15

     ARM使用load-store指令进行内存访问,这意味着只有LDR和STR指令才能访问内存,虽然在X86上,大多数指令都可以对内存中的数据进行操作,但在ARM上,数据在进行操作之前必须从内存移动到寄存器中。这意味着,在ARM上的特定内存地址增加32位值需要三种指令(加载、增量和存储)才能首先将特定的地址的值加载到寄存器中,在寄存器中递增,然后将其从寄存器存储回内存。

     汇编程序例子:

.data          /* the .data section is dynamically created and its addresses cannot be easily predicted */
var1: .word 3  /* variable 1 in memory */
var2: .word 4  /* variable 2 in memory */

.text          /* start of the text (code) section */ 
.global _start

_start:
    ldr r0, adr_var1  @ load the memory address of var1 via label adr_var1 into R0 
    ldr r1, adr_var2  @ load the memory address of var2 via label adr_var2 into R1 
    ldr r2, [r0]      @ load the value (0x03) at memory address found in R0 to register R2  
    str r2, [r1]      @ store the value found in R2 (0x03) to the memory address found in R1 
    bkpt             

adr_var1: .word var1  /* address to var1 stored here */
adr_var2: .word var2  /* address to var2 stored here */

     在底部,我们有我们的Literal Pool(同一代码段中的一个内存区域,用于存储常量、字符串或偏移量,其他人可以以独立于位置的方式引用),在这里,我们使用标签adr_var1和adr_var2存储var1和var2的内存地址(在顶部的数据段中定义)。第一个LDR将var1的地址加载到寄存器R0中。第二个LDR对var2执行相同的操作,并将其加载到R1。然后,我们将存储在R0中找到的存储器地址处的值加载到R2,并将在R2中找到的值存储到在R1中找到的存储地址。

    当我们将某个东西加载到寄存器中时,括号([])的意思是:在这些括号之间的寄存器中找到的值是我们想要从中加载某个东西的内存地址。

   当我们将东西存储到内存位置时,括号([])的意思是:在这些括号之间的寄存器中找到的值是我们想要存储东西的内存地址。

   现在具体分析下上面ldr 和str 四行汇编代码,在内存中和寄存器中的体现: 

ldr r0, adr_var1

ldr r1, adr_var2
标题
ldr r2, [r0] 

str r2, [r1] 

     我们在前两个LDR操作中指定的标签更改为[pc,#12]。这被称为PC相对寻址。因为我们使用了标签,编译器计算了我们在Literal Pool(PC+12)中指定的值的位置。你可以使用这种精确的方法自己计算位置,也可以像我们以前那样使用标签。唯一的区别是,您不需要使用标签,而是需要计算值在Literal Pool中的确切位置。在这种情况下,它距离有效PC位置有3跳(4+4+4=12)。本章稍后将介绍有关PC相对寻址的更多信息。 

偏移形式:立即值作为偏移    

STR    Ra, [Rb, imm]
LDR    Ra, [Rc, imm]

这里我们使用立即数(整数)作为偏移量。该值从基址寄存器(以下示例中的R1)中添加或减去,以在编译时以已知的偏移量访问数据。

.data
var1: .word 3
var2: .word 4

.text
.global _start

_start:
    ldr r0, adr_var1  @ load the memory address of var1 via label adr_var1 into R0
    ldr r1, adr_var2  @ load the memory address of var2 via label adr_var2 into R1
    ldr r2, [r0]      @ load the value (0x03) at memory address found in R0 to register R2 
    str r2, [r1, #2]  @ address mode: offset. Store the value found in R2 (0x03) to the memory address found in R1 plus 2. Base register (R1) unmodified. 
    str r2, [r1, #4]! @ address mode: pre-indexed. Store the value found in R2 (0x03) to the memory address found in R1 plus 4. Base register (R1) modified: R1 = R1+4 
    ldr r3, [r1], #4  @ address mode: post-indexed. Load the value at memory address found in R1 to register R3. Base register (R1) modified: R1 = R1+4 
    bkpt

adr_var1: .word var1
adr_var2: .word var2

让我们调用这个程序ldr.s,编译它并在GDB中运行它,看看会发生什么。

$ as ldr.s -o ldr.o
$ ld ldr.o -o ldr
$ gdb ldr

在GDB(使用gef)中,我们在_start处设置一个断点并运行程序。

gef> break _start
gef> run
...
gef> nexti 3     /* to run the next 3 instructions */

我的系统上的寄存器现在填充了以下值(请记住,这些地址在您的系统上可能不同):

$r0 : 0x00010098 -> 0x00000003
$r1 : 0x0001009c -> 0x00000004
$r2 : 0x00000003
$r3 : 0x00000000
$r4 : 0x00000000
$r5 : 0x00000000
$r6 : 0x00000000
$r7 : 0x00000000
$r8 : 0x00000000
$r9 : 0x00000000
$r10 : 0x00000000
$r11 : 0x00000000
$r12 : 0x00000000
$sp : 0xbefff7e0 -> 0x00000001
$lr : 0x00000000
$pc : 0x00010080 -> <_start+12> str r2, [r1]
$cpsr : 0x00000010

    将执行的下一条指令是具有偏移地址模式的STR操作。它将存储从R2(0x00000003)到R1中指定的存储器地址的值(0x0001009c)+偏移量(#2)=0x1009e。

gef> nexti
gef> x/w 0x1009e 
0x1009e <var2+2>: 0x3

    下一个STR操作使用预索引地址模式。你可以通过感叹号(!)来识别这种模式。唯一的区别是基址寄存器将被更新为存储R2值的最终存储器地址。这意味着,我们将在R2(0x3)中找到的值存储到R1(0x1009c)中指定的内存地址+偏移量(#4)=0x100A0,并用这个确切的地址更新R1。

gef> nexti
gef> x/w 0x100A0
0x100a0: 0x3
gef> info register r1
r1     0x100a0     65696

   最后一个LDR操作使用后索引地址模式。这意味着基址寄存器(R1)被用作最终地址,然后用R1+4计算的偏移量进行更新。换句话说,它取在R1(而不是R1+4)中找到的值,即0x100A0,并将其加载到R3,然后将R1更新为R1(0x100A0)+偏移量(#4)=0x100a4。

gef> info register r1
r1      0x100a4   65700
gef> info register r3
r3      0x3       3

以下是汇编语句的执行效果:

 str r2, [r1, #2]

str r2, [r1, #4]!

 

 ldr r3, [r1], #4

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/911570.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单理解Socket

TCP/IP 要想理解socket首先得熟悉一下TCP/IP协议族&#xff0c; TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff09;即传输控制协议/网间协议&#xff0c;定义了主机如何连入因特网及数据如何再它们之间传输的标准&#xff0c; 从字面意思来看T…

ESD实时监测报警系统主要包括哪些部分

ESD实时监测报警系统是指用于监测静电放电&#xff08;Electrostatic Discharge, ESD&#xff09;并及时报警的系统。静电放电是指物体由于静电积累引起的瞬时放电现象&#xff0c;可能对电子元器件、电子设备等造成潜在的损坏或干扰。 ESD实时监测报警系统通常包括以下几个主…

岩棉革新——洛科威推出NGF新一代岩棉产品

作为全球领先的岩棉制品生产商&#xff0c;洛科威公司基于在岩棉性能革新领域八十多年的深入研究和生产工艺的不断优化&#xff0c;在中国市场正式推出NGF新一代岩棉制品&#xff0c;并在上海国际绿色建筑建材博览会和2023国际绿色低碳技术展上正式发布。 洛科威NGF产品作为革…

bigemap如何批量添加地图?

bigemap如何批量添加地图&#xff1f; 说明&#xff1a;批量添加可以同时添加多个在线地图&#xff0c;一次性添加完成&#xff08;批量添加无法验证地址是否可以访问&#xff09;&#xff08;批量配置文件可以在官网获取&#xff09; 第一步选择地图点进去点(添加号) 第二步&…

QPushbutton

QPushbutton API使用方式 QPushbutton大部分时候都需要使用它从父类QAbstractbutton中继承过来的那些 API。 API // 构造函数 /* 参数:- icon: 按钮上显示的图标- text: 按钮上显示的标题- parent: 按钮的父对象, 可以不指定 */ QPushButton::QPushButton(const QIcon &i…

Python学习 -- 类的封装

当谈及面向对象编程&#xff08;Object-Oriented Programming&#xff0c;OOP&#xff09;&#xff0c;封装是其中的一个重要概念。封装是指将数据和方法封装在一个单一的实体中&#xff0c;以达到隐藏内部实现细节、提供统一接口、提高代码可维护性等目的。在Python中&#xf…

智慧水务在供水行业的应用场景

什么是“智慧水务” 智慧水务指利用物联网、智能传感、云计算、大数据、人工智能等技术对供水、排水、节水、污水 处理、防洪等水务环节进行智慧化管理。智慧水务通过结合传感器、通信网络、水务信息系统提升水务信息化水平&#xff0c;实现水务管理协同化、水资源利用高效化、…

SFL212B-10-21-15、SFL212B-20-21-40喷嘴挡板伺服阀

SFL212B-05-21-10、SFL212B-10-21-15、SFL212B-20-21-40、SFL212-05-32-10、SFL212-10-32-15、SFL212-20-32-40、SFL212A-05-21-10、SFL212A-10-21-15、SFL212A-20-21-40喷嘴挡板力反馈伺服阀&#xff0c;外置伺服放大器&#xff0c;四通&#xff0c;带阀芯阀套的两级伺服阀&am…

打造基于AI的一站式节能减碳方案,南洋万邦助力工业园区实现“双碳”目标

工业是产生碳排放的主要领域之一。相关数据显示&#xff0c;2022年&#xff0c;中国碳排放量累计110亿吨&#xff0c;其中工业排放量42亿吨&#xff0c;占全国排放量的38.18%。国务院印发的《2030年前碳达峰行动方案》将“工业领域碳达峰行动”列为“碳达峰十大行动”之一&…

MIPI-D/C PHY的PCB布局布线要求

MIPI&#xff08;移动行业处理器接口&#xff09;是专为移动设备&#xff08;如智能手机、平板电脑、笔记本电脑和混合设备&#xff09;设计的行业规范的标准定义。其常见的通用的唯一物理&#xff08;PHY&#xff09;层&#xff0c;即MIPI D-PHY和C-PHY。 MIPI D-PHY&#xf…

春秋云境:CVE-2021-40282(zzcms注入)

一、题目 靶标介绍&#xff1a; 站长招商网内容管理系统简称 ZZCMS&#xff0c;由ZZCMS团队开发&#xff0c;融入数据库优化&#xff0c;内容缓存&#xff0c;AJAX等技术&#xff0c;使网站的安全性 、稳定性 、负载能力得到可靠保障。源码开放&#xff0c;功能模块独立&#…

vue3安装组件

如何创建vue项目链接&#xff1a;http://t.csdn.cn/tX8wY 新建vue项目如何配置&#xff1a;http://t.csdn.cn/YLdTG 我们这里拿vant组件演示 首先安装组件库 # Vue 3 项目&#xff0c;安装最新版 Vant npm i vant 可以在package.json查看 我们找到main.js 按钮举例 写入自…

管理类联考——英语——汇总篇——知识+真题——作文——模板——书信——为自己——询问,邀请,请求,求职

目录 询问信 万能模板 普通模板 邀请信 万能模板 普通模板 请求信 万能模板 普通模板 求职信 万能模板 询问信 万能模板 普通模板 Dear ______, I am __________________(自我介绍). I am writing to see if it is possible for you to provide me with inform…

Nest(3):扫盲篇:TypeScript 类和装饰器

前言 先回顾下前文中介绍了哪些内容&#xff1a; 使用 nestjs/cli 创建和管理 Nest 应用Hello, World 示例代码分析Nest 基本概念&#xff1a;模块&#xff0c;控制器&#xff0c;服务常用的装饰器&#xff1a;Module、Controller、Get、InjectableNest 目录结构分析nest/cli…

撸卡、撸货、采退成功率低是什么原因,以及解决办法

在亚马逊和沃尔玛平台上&#xff0c;无论是进行测评、撸卡还是撸货&#xff0c;首要任务就是确保环境的安全性和稳定性。稳定的环境是进行测评和撸卡的基础&#xff0c;如果无法解决安全性问题&#xff0c;那么就不值得进行这些项目。进行环境技术研发已有六七年的时间&#xf…

GB28181国标平台测试软件NTV-GBC(包含服务器和模拟客户端)

GB28181国标平台测试软件NTV-GBC用于对GB28181国标平台进行测试(测试用例需要服务器软件&#xff0c;服务器软件可以是任何标准的国标平台&#xff0c;我们测试使用的是NTV-GBS&#xff09;&#xff0c;软件实现了设备注册、注销、目录查询&#xff0c;消息订阅、INVITE&#x…

惊艳亮相!天翼物联5G工业物联产品获主流媒体关注

近日&#xff0c;由工业和信息化部与广东省人民政府共同主办的2023年中国数字经济创新发展大会举行。作为赋能汕头玩具创意和纺织服装“两特”产业数字化的重要抓手&#xff0c;天翼物联5G工业物联产品惊艳亮相中国电信主展台&#xff0c;并得到了广东广播电视台等媒体的关注。…

亚马逊买家怎么留评

亚马逊买家可以按照以下步骤在购买后留下产品评价&#xff1a; 1、登录亚马逊账户&#xff1a;首先&#xff0c;在网页浏览器中打开亚马逊网站&#xff0c;登录你的亚马逊账户。 2、找到订单&#xff1a;在页面上找到并点击你购买过的商品的"我的订单"或"订单…

【LeetCode】151. 反转字符串中的单词 - 双指针

目录标题 2023-8-22 09:53:10原始优化 151. 反转字符串中的单词 2023-8-22 09:53:10 也是想到了快慢指针的思想。 原始 class Solution {public String reverseWords(String s) {int length s.length();Integer pre null;Integer last null;StringBuilder stringBuilde…

LeetCode--HOT100题(38)

目录 题目描述&#xff1a;226. 翻转二叉树&#xff08;简单&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;226. 翻转二叉树&#xff08;简单&#xff09; 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 LeetCode做题链…