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

標(biāo)題: ARM指令adr adrl ldr mov是什么,ldr和adr區(qū)別在哪里? [打印本頁]

作者: kasuy    時間: 2017-9-7 16:35
標(biāo)題: ARM指令adr adrl ldr mov是什么,ldr和adr區(qū)別在哪里?
ARM指令:什么是adr adrl ldr mov?
ADR是一條小范圍的地址讀取偽指令,它將基于PC的相對偏移的地址值讀到目標(biāo)寄存器中。格式:ADR register,exper。
編譯源程序時,匯編器首先計算當(dāng)前PC值(當(dāng)前指令位置)到exper的距離,然后用一條ADD或者SUB指令替換這條偽指令,

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

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

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

LDR指令:

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

LDR偽指令:

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

ldr 和 adr 的區(qū)別在哪里?

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

Makefile:

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

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

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

作者: fwb152_qq    時間: 2017-9-16 09:15
樓主講的很好!頓時明白了,謝謝樓主解析,么么




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 玖玖色资源 | 亚洲av毛片成人精品 | 成人在线视频网 | 一区二区三区四区在线视频 | www.午夜 | 俄罗斯毛片 | 欧美国产日韩一区二区 | 国产一级视频在线观看 | 亚洲黄色在线 | 中文字幕亚洲天堂 | 亚洲综合网站 | 一级片免费视频 | 亚洲欧美日韩一区 | 中文字幕自拍 | 色综合天天综合网国产成人网 | 亚洲精品美女 | 午夜在线观看视频网站 | 草草视频在线 | 黄色一级在线观看 | 国产欧美日韩综合精品 | 欧美视频在线观看 | 欧美在线小视频 | 国模一区二区 | 国产精品免费一区二区三区 | 人人草人人爽 | 国产精品自拍一区 | 午夜视频免费 | www.中文字幕 | www亚洲天堂 | 精品一二三区 | 国产欧美激情 | 成人黄色av| 亚洲午夜18毛片在线看 | 国产在线一 | 在线播放a| 国产一区二三区 | 欧美一区二区在线视频 | 国产香蕉视频在线观看 | 天天干天天草 | 亚洲成人av在线播放 | 亚洲黄色小视频 |