天天看點

反彙編解析S3C2440彙編點燈

目錄

    • 代碼
    • 反彙編
      • 對比
      • 解析
      • 總結
    • dis和bin對比

代碼

首先回顧代碼

/*
*點亮LED:GPF4
*/
.text //表明它是代碼段
.global _start

_start:

/*配置GPF4為輸出引腳
*把0x100寫到位址0x56000050上,熄滅led
*/
	ldr r1, =0x56000050  	/*将這個位址存放到r1中*/
	ldr r0, =0x100			/*或者使用 mov r0, #0x100  将0x100放入r0 */ 
	str r0, [r1]			/*将r0的值寫入到r1的位址中*/

/*設定GPF4輸出高電平
*把0x00寫到位址0x56000054上,點亮led
*/
	ldr r1, =0x56000054  	/*将這個位址存放到r1中*/
	ldr r0, =0				/*或者使用 mov r0, #0x100  将0放入r0 */ 
	str r0, [r1]			/*将r0的值寫入到r1的位址中*/


halt:						/*假設這個程式隻有十幾個位元組*/
	b halt					/*這十幾個位元組後的内容是不确定的,是以要讓他在這裡死循環*/
           

我們使用的ldr是僞指令,将位址存放在r1和r0中

僞指令,就是假的arm指令

它對應哪些真正的arm指令呢

反彙編

要想知道這個僞指令對應的真正的arm指令

我們就需要将elf檔案反彙編

反彙編解析S3C2440彙編點燈
arm-linux-objdump -D led.elf  > led.dis
           

輸入指令反彙編

将生成的dis檔案傳到windows,并使用notepad打開

反彙編解析S3C2440彙編點燈

對比

反彙編解析S3C2440彙編點燈

左側是我們使用的僞指令

可以看到真實的arm指令,是将這個位址放在記憶體中,使用pc讀取記憶體中1c和20的位址給r1

第二條指令直接使用mov,将位址存放在r0當中

解析

2440中有CPU,CPU中有r0到r15,16個寄存器。這裡是如何使用PC值來表示寄存器呢

反彙編解析S3C2440彙編點燈
  • pc——Program Counter(程式計數器)

    當你把一個位址寫道R15也就是程式計數器時,程式就跳到那個位址中去

    位址為目前指令的位址+8

  • lr——Link Register(傳回位址)

    使用函數調用的時候,執行完畢要跳回原來的地方。R14/lr就是用來儲存原來的位址

  • st——Stack Pointer(棧指針)
反彙編解析S3C2440彙編點燈

PC是什麼?

目前指令的位址使0,PC的位址是目前指令加8

因為ARM系統裡面,為了使執行效率更加高,CPU是以流水線的方式執行的

  • 流水線:目前執行位址A的指令;已經在對位址A+4的指令進行譯碼;已經在讀取位址A+8(PC)的指令。

對于上面的圖

r1的值,等于[pc+20]這個位址的值,等于[8+20],28對應16進制就是0x1c

即,r1的值,就是0x1c位址中存放的值,就是0x5600,0050

第三條指令,将0x100寫入r1對應的記憶體,就是把0x100寫入0x5600,0050

第四條指令,r1等于[pc+12]=[0xc+8+12]=[32]=[0x20]

即,去0x20這個位址讀取值,存放到r1裡面,就是0x5600,0054

總結

在程式裡面,寄存器和記憶體沒有本質的差别。CPU都把它們當作記憶體來使用

隻是這些記憶體比較特殊,配置他們能控制一些引腳

dis和bin對比

dis是反彙編檔案

反彙編解析S3C2440彙編點燈

我們知道,bin檔案中都是二進制的機器碼,那麼我們來對比以下dis的彙編碼和bin中的機器碼

反彙編解析S3C2440彙編點燈

可以看到是完全一緻的

反彙編dis檔案中的彙編碼的源頭們就是我們編寫的代碼,那些僞指令和彙編碼

步驟如下

  • 編譯器将僞指令轉化為真正的彙編碼,對于真正的彙編碼保持不變
  • 轉換完成後,将所有的彙編碼轉換為機器碼,然後存為bin檔案。這些bin檔案就可以直接燒寫到單闆上了。
上一篇: SBT總結SBT
下一篇: S3C2440看門狗