久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4907|回復: 1
打印 上一主題 下一主題
收起左側

ARM指令adr adrl ldr mov是什么,ldr和adr區別在哪里?

[復制鏈接]
跳轉到指定樓層
樓主
ARM指令:什么是adr adrl ldr mov?
ADR是一條小范圍的地址讀取偽指令,它將基于PC的相對偏移的地址值讀到目標寄存器中。格式:ADR register,exper。
編譯源程序時,匯編器首先計算當前PC值(當前指令位置)到exper的距離,然后用一條ADD或者SUB指令替換這條偽指令,

      例如:ADD register,PC,#offset_to_exper。
      注意,標號exper與指令必須在同一代碼段。
      比如:adr r0, _start ://將指定地址賦到r0中
      ……
      _start:
      b _start
      r0的值為標號_start與此指令的距離差 + PC值。

ADRL:
這是一條中等范圍的地址讀取偽指令,它將基于PC的相對偏移的地址值讀到目標寄存器中。格式:ADRL register,exper。編譯源程序時,匯編器會用兩條合適的指令替換這條偽指令。

      比如:
      ADD register,PC,offset1
      ADD register,register,offset2
      與ADR相比,它能讀取更大范圍的地址。
      注意,標號exper與指令必須在同一代碼段。
      接下來是LDR,首先要說兩個家伙,他們都叫LDR。
      一個是LDR偽指令,一個是LDR指令,名字相同卻不是一個東西。
      區分的方法就是看第二個參數,如果有等號,就是偽指令。

LDR指令:

      例: ldr r0, 0x12345678
      是把0x12345678這個地址中的值存放到r0中。而mov不能干這個活,mov只能在寄存器之間移動數據,或者把立即數移動到寄存器中。

LDR偽指令:

      例1(立即數): ldr r0, =0x12345678
      這樣,就把0x12345678這個地址寫到r0中了。所以,ldr偽指令和mov是比較相似的。只不過mov指令限制了立即數的長度為8位,也就是不能超過512。而ldr偽指令沒有這個限制。如果使用ldr偽指令,后面跟的立即數沒有超過8位,那么在實際匯編的時候該ldr偽指令會被轉換為mov指令。
      例2(標號): ldr r0, =_start //將指定標號的值賦給r0
      這里取得的是標號_start的絕對地址,這個絕對地址(運行地址)是在鏈接的時候確定的。它要占用 2 個32bit的空間,一條是指令,另一條是文字池中存放_start 的絕對地址。
      對比adr r0, _start和 ldr r0, =_start
      它們的目的一樣,都是把標簽的賦給r0,區別---左邊是相對地址,右邊絕對地址。目的一樣,但結果不一定相同。結果是否相同,要看PC值是否和鏈接地址相同。

ldr 和 adr 的區別在哪里?

很多人在寫簡單的裸機代碼或分析uboot時,常常遇到adr ldr指令。卻分不清這2者的區別,今天就來談談adr與ldr指令。
參照韋老師的代碼和Makefile寫了test_adr.S

Makefile:

反匯編test_adr.S得到test_adr.dis:

很顯然,ldr獲取的是內存的值(至于這個內存存的是數據還是地址,不是問題重點),像指針一樣間接尋址(看到了〔〕符號咯),而adr是得到一個與PC有關的值,必定是個地址。
韋老師舉了個例子:
adr r0, _start,r0就是_start對應指令當前的地址
對于“_start對應指令當前的地址”,我理解了很久,終于想清楚,比如在uboot中,_start標號對應的指令(即b reset)的鏈接地址是0x33f80000確鑿無疑。
如果從NOR Flash啟動,b reset被燒在NOR Flash 0地址,那么b reset相對于此時的PC來說,它的地址就是0。
如果u-boot被直接下載到SDRAM的0x33f80000處運行,那么b reset自然處在SDRAM的0x33f80000。
所謂“當前”---是以運行時的PC為參照。
下面基于以上理解,分析test_adr.dis

1、先分析第一條指令ldr r0,test被編譯成ldr
r0, 〔pc, #8〕,即到當前PC+8的存儲器取值,運行第一條指令時,PC其實已經是8了(流水線決定的)。
那么8+8等于0x10,所以r0等于e1a00000,此指令的作用就是讀取test地址處存放的值。由于此處放了一條nop,即得到nop的機器碼。
2、第二條adr r0,test被編譯成add r0, pc, #4
這顯然是依賴程序執行到此處的PC值。ADR是小范圍地址讀取偽指令,會將基于PC 相對偏移的地址值讀取到寄存器中,此指令在4地址,PC是4+8=0xc再加4,于是r0=0x10。
從結果上來看,test自身的值(標號值),被讀到了r0,這個值是以PC為參考的,也就是test對應的指令(第二個nop)當前的地址。r0=(標號test的地址與此指令的距離差)+(此指令的地址)=((0x10-0x4=12)+(4))=16=0x10。
假如在0x30000000以上運行,r0=((12)+(0x30000004))= 0x30000010。
3、ldr r0,=test被編譯成兩個字,一個指令,一個文字池
執行到這里PC=8, 8+8+4=0x14,所以在14地址取值,編譯器在14地址處放了0x00000010,0x00000010是test的值,假如在Makefile指定連接地址是0x30000000,那么編譯器放在這里的就是0x30000010,可見,這個值是編譯時確定的。
最后一行andeq r0, r0, r0, lsl r0大概是編譯器的機械動作,把一個數字翻譯成了指令。
總結
ADR是小范圍的地址讀取偽指令,它將基于PC 相對偏移的地址值讀取到寄存器中。而ldr獲取的是內存的值,像指針一樣間接尋址。

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:233430 發表于 2017-9-16 09:15 | 只看該作者
樓主講的很好!頓時明白了,謝謝樓主解析,么么
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲啪啪| 97视频人人澡人人爽 | 在线观看中文字幕 | 国产目拍亚洲精品99久久精品 | 久久精品国产99国产精品 | 69热视频在线观看 | 日韩av免费看 | 一区二区三区四区不卡 | 日本黄色一级视频 | 国产中文字幕网 | 欧洲亚洲精品久久久久 | 永久精品 | 欧美久久免费观看 | 91亚洲精品国偷拍自产在线观看 | 亚洲视频免费在线观看 | 久视频在线观看 | 久在线视频播放免费视频 | www.色.com| 中文字字幕一区二区三区四区五区 | 欧美日韩免费一区二区三区 | 亚洲精品91 | 91最新入口 | 农村妇女毛片精品久久久 | 日韩三级免费观看 | 中文字幕国产一区 | 一区二区三区四区国产 | 狠狠色综合久久婷婷 | 99热精品在线 | 久久com| 国产不卡视频在线 | 久久精品免费观看 | 美女视频一区 | 亚洲一区二区三区视频免费观看 | 91精品在线播放 | 国产精品高潮呻吟久久 | 黄色网址免费看 | 欧洲精品久久久久毛片完整版 | 久热m3u8| 日韩精品一区中文字幕 | 国产99热在线 | 国产美女在线精品免费 |