<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM 匯編的mov操作立即數(shù)的疑問(wèn)

          ARM 匯編的mov操作立即數(shù)的疑問(wèn)

          作者: 時(shí)間:2016-11-09 來(lái)源:網(wǎng)絡(luò) 收藏
          1. 因?yàn)閷?duì)arm匯編有些指令還不能理解,特別是一些相似功能指令間的區(qū)別。偶然在網(wǎng)上搜到“faq ARM assembly”,其中描述的幾個(gè)問(wèn)題還是值得好好研究一下。

          2. 慢慢的發(fā)現(xiàn)自己也不再害怕英文的文檔了,耐心看至少也能懂個(gè)大概。大批經(jīng)典的文章和書(shū)籍都是en文的,所以經(jīng)常看英文文檔是一個(gè)非常好的習(xí)慣??纯碐NU的一些reference manual,哪個(gè)不是經(jīng)典而又值得學(xué)習(xí)并研究的!

          本文引用地址:http://www.ex-cimer.com/article/201611/317882.htm

          3. 學(xué)習(xí)別人寫(xiě)文檔的風(fēng)格,重點(diǎn)要注意條理性。能夠把一個(gè)問(wèn)題、一個(gè)知識(shí)點(diǎn)闡述清晰明白,這不僅需要對(duì)知識(shí)點(diǎn)的掌握,還需要良好的語(yǔ)言表達(dá)能力以及對(duì)文章細(xì)心、整潔的排版。我想,這些細(xì)節(jié)才能夠體現(xiàn)一個(gè)人的水平和他所能到達(dá)的高度。

          --
          本篇來(lái)看一下mov這個(gè)指令,相關(guān)指令 ldr

          Question on MOV
          Does the instruction “Mov” have indirect addressing?
          Answer. No, e.g. you cannot use mov r1,[r2]
          “MOV loads a value into the destination register, from another register, a shifted register, or an immediate 8-bit value.”
          Examples:
          MOV R0, R1 if R1 has 0x01234, after this ,R1=R2=0x01234
          MOV R0, #0x12; after this R0 has #0x12
          MOV R0, #300; is wrong the value should be less than 255
          MOV R0, 200; is wrong, # is missing “mov R0,#200: is correct

          Note: the immediate value must be prefixed by #

          從上面的描述可以看出,mov的作用有兩個(gè):

          1. 在寄存器之間傳遞值。

          2. 給寄存器傳遞一個(gè)立即數(shù),此時(shí)需要用“#”來(lái)修飾立即數(shù),并且立即數(shù)為8位的,其值不能超過(guò)255.

          但是在vivi中的head.S里,有許多類(lèi)似 mov r1, #0x53 的語(yǔ)句:

          簡(jiǎn)單的寫(xiě)幾句匯編,測(cè)試一下:

          .global _start
          .align 0
          _start:
          mov r1, #0x12
          mov r2, #300
          mov r3, #0x53

          .end

          這樣,編譯并沒(méi)有報(bào)錯(cuò)。

          反匯編后如下

          8: e3a01012 mov r1, #18 ; 0x12
          8004: e3a02f4b mov r2, #300 ; 0x12c
          8008: e3a03453 mov r3, #1392508928 ; 0x53

          這是為什么呢?為什么用mov也可以?看別的匯編里都是寫(xiě)ldr r1, =0x53

          將程序改一下:

          .global _start
          .align 0
          _start:
          mov r1, #0x12
          mov r2, #300
          ldr r3, =0x53
          .end

          匯編也沒(méi)有報(bào)錯(cuò),反匯編可看到如下三句話:

          8: e3a01012 mov r1, #18 ; 0x12
          8004: e3a02f4b mov r2, #300 ; 0x12c
          8008: e3a03453 mov r3, #1392508928 ; 0x53

          發(fā)現(xiàn),ldr r3, =0x53 被經(jīng)過(guò)匯編之后,實(shí)際上變?yōu)榱?mov r3, #0x53 ??梢?jiàn),此處ldr相當(dāng)于一個(gè)偽指令。

          關(guān)于ldr,下面這段說(shuō)的很清楚。在分析匯編時(shí),很重要一點(diǎn)就是分清“地址” 和“地址里的內(nèi)容”,對(duì)這個(gè)能熟練把握了,相信能對(duì)C語(yǔ)言中的指針有更深的理解。

          Question on the use of LDR,ADR
          Are there any difference between statement 1,2,3 in the following program?
          Data1p DCD 0, 0 ;just happen the address is at 0x40
          ;DCD (reserve a 32-bit word)is a pseudo instruction to
          ;allocate a memory location for this data.
          align
          align
          :
          :
          Statment1 LDR R0, =Data1p ; Put the address Data1p into R0
          Statment2 ADR R0, Data1p ; Put the address Data1p into R0
          Statment3 LDR R0, =0x40 ; Put the value0x40 into R0,
          ;just happen it is the address of Data1p
          Answer: They are all the same. Every statement will generate the same result. Such that the address, not the data content, will be saved into R0. For example, the value in R0 is 0x40.

          到這里,相信一定對(duì)“mov”和“ldr”兩個(gè)產(chǎn)生了一些疑惑。(注:此處的ldr指的是偽指令pseudo-instruction,而不是內(nèi)存到寄存器傳遞值的instruction)

          下面的這段對(duì)兩者的區(qū)別作了很全面的分析。

          Question on differences between LDR and MOV
          What is the difference between MOV and LDR, they seem to have the same function of saving information into registers?
          Answer part 1: How different are they?
          Note: “#” for mov, “=” for ldr. To define an immediate value
          MOV can only move an 8-bit value (0x00->0xff=255) into a register while LDR can move a 32-bit value into a register. The immediate value is prefixed by different characters in mov and ldr: “#” formov, “=” for ldr. E.g.


          Mov r1,#255 ; ok, 255 is the biggest number you can mov
          Mov r1,255 ; is wrong , missing #
          Mov r1,#256 ; is wrong, the number is bigger than 255
          Mov r1,#0x12340 ; is wrong, the number is bigger than 255
          Ldr r1,=255; you can do this,
          Ldr r1,=256; you can do this,
          Ldr r1,=0x12340; you can do this,


          1. MOV can run faster than LDR.
          2. LDR can move a data from a memory address to a register, MOV can only i) move data between two registers or ii) save a 8-bit immediate value to a register. e.g.
          value1 DCD 0; this define an integer variable “value1” with address “=value1”

          :

          ;A standard pair of statements for moving a data into a register
          Ldr r0,=value1 ; 1) save the address of the variable value1 in r0
          Ldr r1,[r0] ;2)use r0 as the address (pointer) to get value1 to r1
          r1 Note: Mov cannot be used to achieve the same result, because mov,[r0] is not allowed
          Answer part 2 : How similar are they?.
          MOV is a real instruction, LDR is a pseudo instruction. If the immediate value is small, the assembler will use “mov” to implement it , otherwise it uses a literal pool to achieve the result.
          e.g.
          ldr r0,=14; the immediate value 14 <255, so it will be implemented using mov r0,#14, (see the use of # and = ) but if the immediate value is large than 255, e.g.
          The assembler will generate code to place the constant 0x55 ldr r0,=0x55; for a large immediate value “mov” does work.in a nearby table in the code area. Then it uses an instruction to load a data from that table pointed by the program counter and an offset to fill up r0. The reason is because there is no way to fit a 2-bit data into a 32-instruction, and ARM design always want to make sure instructions are 32-bit. Details can be found athttp://www.keil.com/support/man/docs/armasm/armasm_chdcegci.htm
          see also the directive “LTORG” for how to setup the table. Usually it is placed at the near by code area. You don’t need to worry too much because everything is automatic; you only need to place “LTORG” at the end of the code area as shown in the example at Keil.

          但是我在看完上面這段話之后還是存在疑問(wèn):為什么”mov r3, #0x53”是可行的呢?

          http://www.keil.com/support/man/docs/armasm/armasm_cihcdbca.htm

          這個(gè)網(wǎng)頁(yè)上對(duì)mov做了一些說(shuō)明,截取有關(guān)立即數(shù)的部分如下:

          Syntax
          MOV{cond} Rd, #imm16
          where:
          imm16
          is any value in the range 0-65535.

          可以看到,這里說(shuō) 立即數(shù)是16位的。

          看到這里,確實(shí)把自己弄糊涂了。理清一下:

          第一個(gè)說(shuō)imm為8位是在網(wǎng)絡(luò)上搜的一分資料,沒(méi)有什么權(quán)威性,其可信程度也值得懷疑。

          第二個(gè)是keil官司方網(wǎng)站里關(guān)于arm匯編的說(shuō)明。

          另外,在《arm體系結(jié)構(gòu)與編程》這本書(shū)里,并沒(méi)有說(shuō)立即數(shù)的具體范圍,在26頁(yè)有一句:

          mov r0, #0xfc0

          明顯立即數(shù)大于255了。

          在144頁(yè)有提到,“ldr偽指令讀取的數(shù)據(jù)超過(guò)mov操作范圍”。這說(shuō)明mov可操作的立即數(shù)是有一定范圍的,且比ldr小。

          再來(lái)分析一下立即數(shù)的產(chǎn)生,其尋址方式是這樣的:

          11 8 7 0
          +-+-+
          Rotate Imm
          +-+-+
          [7:0] Unsigned 8 bit immediate value
          [11:8] Shift applied to Imm
          The immediate operand rotate field is a 4 bit unsigned integer which specifies a shift operation on the 8 bit immediate value. This value is zero extended to 32 bits, and then subject to a rotate right by twice the value in the rotate field.This enables many common constants to be generated, for example all powers of 2

          1. 取低8位,先用0擴(kuò)展為32位數(shù)
          2. 將所得32位數(shù)循環(huán)右移 2*Rotate位,Rotate為[11:8]

          來(lái)分析一句:mov r2, #300。反匯編如下:

          8004: e3a02f4b mov r2, #300 ; 0x12c

          立即數(shù)是直接放在指令內(nèi)部的。

          1. 取其低8位:0x4b

          2. 擴(kuò)展為32位:0x0 004b

          3. 2*Rotate = 2*15 = 30

          4. 循環(huán)右移30位(相當(dāng)于左移2位)。即0100 1011 左移2位,得到1 0010 1100 ,即0x12c,十進(jìn)制等于300

          對(duì)于0x53的計(jì)算方法也是相同的。 mov r1, #0x53 這樣寫(xiě)確實(shí)是可行的。

          -

          總結(jié):對(duì)于mov 操作立即數(shù)時(shí)的操作范圍,現(xiàn)在還是不確定。但經(jīng)過(guò)這么多的分析以及實(shí)際寫(xiě)的幾句測(cè)試代碼,至少可以說(shuō)明在Linux里,用arm-linux-as來(lái)編譯,mov是可以操作32位的立即數(shù)的,不然vivi如何編譯成功。(懷疑是否這跟實(shí)際匯編器相關(guān)。)



          關(guān)鍵詞: ARM匯編mov操作立即

          評(píng)論


          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();