從最簡單的例項學習ARM 指令集(一)

2021-06-29 04:40:40 字數 2392 閱讀 2167

打算為入門arm指令集寫點初級文章,沒什麼遠大理想,純當娛樂算了。

#include void main()

然後編譯:arm-linux-gnueabihf-gcc test.c -o test1

然後看看彙編**:arm-linux-gnueabihf-objdump -d test1;每一句的含義我已經給出詳細注釋。

835c:       b480            push                  

這裡,835c是main函式的位址,b480是機器碼表示的指令,push 就是給我們人類看的了。下面看test1的輸出:

0000835c :

程式用到了r7暫存器,所以需要保護以免破壞之前的資料

1    835c:       b480            push                

堆疊向下增長棧用的不多,只需要12個位元組就夠用了: int d需要4個,多出來的8個沒有使用

2   835e:       b083            sub     sp, #12     

因為r0-r7是通用暫存器,可以使勁用,堆疊暫存器sp只有沒辦法的時候才使用。只好用r7 = sp + 0這種笨辦法

3  8360:       af00            add     r7, sp, #0  

參與int d = 4這條語句的是r3,這是通用暫存器,spec定義大家都可以用,不需要保護

4    8362:       f04f 0304       mov.w   r3, #4    

把4儲存到sp+4所指定的棧裡,c語言描述:*(sp + 4) = 4;留給大家思考:為何不頂著sp放置--即*(sp+0)=4?

5    8366:       607b            str     r3, [r7, #4]    

還記得第二條:sub sp, #12嗎?此句和下一句是為從堆疊裡恢復原來的r7--pop ,做準備;

6    8368:       f107 070c       add.w   r7, r7, #12 

r7已經是原來的sp了

7    836c:       46bd            mov     sp, r7    

彈出sp指向的記憶體資料給r7,c語言:r7 = *sp;

8    836e:       bc80            pop      

沒有呼叫子函式,即沒有使用lr暫存器,所以不需要push lr。跳轉到lr位址--進入main函式的下一條位址

9    8370:       4770            bx      lr                 

10    8372:       bf00            nop

我們再編輯乙個稍微增加乙個變數:test2.c

#include void main()

0000835c :

1   835c:       b480            push   

2    835e:       b083            sub     sp, #12

3    8360:       af00            add     r7, sp, #0

4    8362:       f04f 0304       mov.w   r3, #4

把4儲存到sp+0所指定的棧裡,c語言描述:*(sp + 0) = 4,注意與上乙個例子的區別,這裡是頂著stack存放,為什麼?

5    8366:       603b            str     r3, [r7, #0] 

6    8368:       f04f 0302       mov.w   r3, #2

為何要這麼任性的存放變數b?

7    836c:       71fb            strb    r3, [r7, #7] 

8    836e:       f107 070c       add.w   r7, r7, #12

9    8372:       46bd            mov     sp, r7

10    8374:       bc80            pop    

11   8376:       4770            bx      lr

棧裡的資料是這樣的,b和d中間隔著好幾條街呢:)

從最簡單的例項學習ARM指令集

cpp view plain copy print include void f1 void main include void f1 void main 然後編譯 arm linux gnueabihf gcc test.c o test4 然後看看彙編 0000835c 1 835c b480 ...

ARM 指令集學習記錄

通用暫存器和狀態暫存器。通用暫存器包括r0 r15,可分為三類,未分組暫存器,分組暫存器及程式計數器。未分組暫存器 r0 r7,儲存資料或位址。分組暫存器 r8 r14,其中r8 r12對應兩個物理暫存器,r13 r14對應多個。r13常用作堆疊指標。r14稱作程式連線暫存器,lr 程式暫存器 pc...

Thumb指令集與ARM指令集的區別

thumb指令集 thumb指令可以看做是arm指令壓縮形式的子集,是針對 密度的問題而提出的,它具有16為的 密度。thumb不是乙個完整的體系結構,不能指望處理程式只執行thumb指令而不支援arm指令集。因此,thumb指令只需要支援通用功能,必要時,可借助完善的arm指令集,例如 所有異常自...