網(wǎng)站首頁 編程語言 正文
LDR指令和LDR偽指令詳解
ARM32位指令的構(gòu)成
ARM是RISC結(jié)構(gòu),數(shù)據(jù)從內(nèi)存到CPU之間的移動(dòng)只能通過LDR/STR指令來完成。 32bit = 指令碼 + 數(shù)據(jù)。所以32bit的一條指令不可能表示再帶一個(gè)32bit的數(shù)據(jù),實(shí)際只有其中的12bit來表示立即數(shù),其中4bit表示移位的位數(shù)(循環(huán)右移,且數(shù)值x2),8bit用來表示要移位的一個(gè)基數(shù)。這就產(chǎn)生了非法立即數(shù)和合法立即數(shù)的問題,經(jīng)過移位操作,不為零的部分不能用8bit表示的數(shù)就是非法立即數(shù)。ldr偽指令就是用來解決非法立即數(shù)問題的。
ldr指令和ldr偽指令的使用區(qū)別:
ldr r0, =0xFFF0 @偽指令
ldr r0, 0xFFFF @指令
直觀的區(qū)別就是ldr偽指令使用時(shí),后面的數(shù)據(jù)前會(huì)有"=",實(shí)際使用時(shí),大部分都使用偽指令,這樣就不用考慮合法和非法立即數(shù)的問題。在編譯的時(shí)候,編譯器會(huì)將ldr偽指令進(jìn)行替換,用文字池的方式來解決非法立即數(shù)的問題。文字池就是劃分出一段地址空間用來存放常量或者地址,需要時(shí)用基址+變址的方式去取數(shù)據(jù),這樣就不用受到合法立即數(shù)的限制,可以表示32bit的數(shù)據(jù)。例如:
匯編源代碼:
_start:
ldr r0, =0x11111111
經(jīng)過反匯編:
00000000 <_start>:
0: e59f009c ldr r0, [pc, #156] ; a4 <delay_loop+0x10>
·
·
·
98: e1520003 cmp r2, r3
9c: 1afffffc bne 94 <delay_loop>
a0: e1a0f00e mov pc, lr
a4: 11111111 tstne r1, r1, lsl r1
分析:
通過反匯編可以看到,ldr偽指令被一條寄存器基址變址指令給替代了。其中以pc為基址,偏移156個(gè)字節(jié)(16進(jìn)制是0x9c)。這條指令的作用是將內(nèi)存地址"pc + 156"開頭的4個(gè)字節(jié)讀取到r0中,此時(shí)pc的值等于當(dāng)前執(zhí)行指令的地址+8(因?yàn)榱魉€的原因),因此pc + 156 = 0xa4,而0xa4地址處存的值剛好是0x11111111。這樣就完成了將0x11111111加載到r0。
補(bǔ)充1:
RAM處理器存在流水線,目前已經(jīng)有十幾級流水線,但是ARM為了兼容,無論Soc有多少級流水線,PC的值都是等于當(dāng)前指令地址 + 8。PC = 當(dāng)前指令地址 + 8, 記住就行。
補(bǔ)充2:
匯編語言ldr偽指令
偽指令是用來自動(dòng)拆分代碼值的,會(huì)把一條語句拆分成多條語句。
示例:
/* 匯編點(diǎn)亮一個(gè) LED 燈 */
.text
.global _start
_start:
ldr r1, =0x56000050
ldr r0, =0x100 /* 相當(dāng)于 mov r0, #0x100 */
str r0, [r1]
ldr r1, =0x56000054
ldr r0, =0 /* mov r0, #0 */
str r0, [r1]
halt:
b halt
ldr r1, =0x56000054就是一條偽指令,假設(shè)我們想把56000054值給r1寄存器,可以用 mov r1, #56000050 ,
但是長度超出了mov 能接收的長度,就要分為高低字節(jié)去發(fā)送,但是在某些時(shí)候我們還要去看開放文檔,才能知道
或者沒有開發(fā)文檔,那就讓偽指令自己去判斷。
原文鏈接:https://blog.csdn.net/weixin_42031299/article/details/114749604
相關(guān)推薦
- 2022-10-09 淺談C++中各種不同意義的new和delete的使用_C 語言
- 2021-12-05 Go語言配置數(shù)據(jù)庫連接池的實(shí)現(xiàn)_Golang
- 2022-07-26 使用Docker將容器目錄掛載到主機(jī)上的實(shí)現(xiàn)方法_docker
- 2022-08-15 GoAccess對Nginx日志分析完美分析
- 2022-08-23 python實(shí)現(xiàn)GATK多線程加速示例_python
- 2022-06-02 python?面向?qū)ο箝_發(fā)及基本特征_python
- 2023-07-28 el-input 文本域固定高度
- 2022-03-26 c#使用listbox的詳細(xì)方法和常見問題解決_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支