嵌入式linux 彙編碼和機器碼

2021-09-13 11:25:09 字數 2745 閱讀 2486

使用點亮led的簡單程式分析其彙編碼和機器碼,通過直接修改bin檔案中的機器碼修改功能,點亮其他的led燈。

首先修改makefile檔案把elf檔案反彙編生成dis檔案,檢視其真正的彙編指令:

all:

arm-linux-gcc -c -o led_on.o led_on.s

arm-linux-ld -ttext 0 led_on.o -o led_on.elf

arm-linux-objcopy -o binary -s led_on.elf led_on.bin

arm-linux-objdump -d led_on.elf > led_on.dis

clean:

rm *.bin *.o *.elf

反彙編之後開啟dis檔案,真正的彙編指令:

led_on.elf:     file format elf32-littlearm

disassembly of section .text:

00000000 <_start>:

/*[第1行]*/ 0: e59f1014 ldr r1, [pc, #20] ; 1c <.text>

/*[第2行]*/ 4: e3a00c01 mov r0, #256 ; 0x100

/*[第3行]*/ 8: e5810000 str r0, [r1]

/*[第4行]*/ c: e59f100c ldr r1, [pc, #12] ; 20 <.text>

/*[第5行]*/ 10: e3a00000 mov r0, #0 ; 0x0

/*[第6行]*/ 14: e5810000 str r0, [r1]

00000018 :

18: eafffffe b 18 1c: 56000050 undefined

20: 56000054 undefined

在彙編指令中,最右邊是彙編碼,中間是機器碼,最左邊是位址。

在cpu中有27個暫存器,其中16個可以使用,如上圖所示,最右邊一列是暫存器的別名。其中pc為program counter程式計數器,當把乙個位址寫入此暫存器中時,程式就跳到此位址中去。lr是link register鏈結暫存器,用來儲存返回位址,當程式執行完後調回到這個位址。sp是stack point棧指標暫存器。

程式解析過程說明:

/*[第1行]*/   0:    e59f1014     ldr    r1, [pc, #20]    ; 1c <.text> 在這一行程式中,當前指令位址為0,pc為當前指令位址加8,所以r1 = 0 + 8 + 20 = 28 = 0x1c,但是為什麼是加8?因為在arm系統中cpu是以流水線(arm核心使得執行效率更加高)的方式進行工作的,即當前執行位址a的指令,那麼cpu已經在對位址a+4的指令進行解碼,同時已經在讀取位址a+8的指令,這裡a+8就是pc的值。所以在下邊已經給出了0x1c位址的值就是56000050,賦給r1。

/*[第2行]*/   4:    e3a00c01     mov    r0, #256    ; 0x100  在這一行中,mov指令將立即數0x100賦給r0

/*[第3行]*/   8:    e5810000     str    r0, [r1]   在這一行將0x100寫入r1對應的記憶體

/*[第4行]*/   c:    e59f100c     ldr    r1, [pc, #12]    ; 20 <.text> 在這一行中pc等於當前位址加8,所以r1=pc + 12 = 0xc + 8 + 12 =32=0x20,所以下邊已經給出此位址的值為56000054,讀取出來賦給r1。

/*[第5行]*/  10:    e3a00000     mov    r0, #0    ; 0x0 在這一行中將立即數賦給r0。

/*[第6行]*/  14:    e5810000     str    r0, [r1] 在這一行將0寫入r1對應的記憶體

編譯器將彙編碼轉換為機器碼,這個機器碼就是bin檔案的內容。如果想將點亮的第乙個led燈換成第二個,經過查閱手冊將gpfcon賦值改為0x400,可以通過修改匯程式設計序然後編譯鏈結,但是也可以通過修改機器碼來實現,就是修改第二行的mov指令對應的機器碼,首先查閱mov指令機器碼儲存結構。

e3a00c01的位:

bit15~bit12用來表示r0,bit11~bit0用來表示賦值的數值立即數。其中bit11~bit8表示高四位rotate,剩下的是低8位immed_8。而立即數 = immed_8迴圈右移(2 * rotate)位。

根據上圖rotate是12,所以是1迴圈右移24位得到0..(23)..100000000也就是立即數0x100

但是如果是立即數是0x400,怎麼使用rotate和immed_8表示呢,將0x400展開是0..(21)..100 0000 0000數一下0的個數可知道是1迴圈右移22位得到,所以ratate=22/2=11,rotate為0b1011,所以12位立即數為1011 0000 0001,所以直接修改機器碼e3a00c01為e3a00b01即可解決問題。

32位嵌入式系統和嵌入式Linux

32位嵌入式系統和嵌入式linux 嵌入式linux是一種開發原始碼 軟實時 多工的嵌入式作業系統,是標準linux的嵌入式系統移植版。眾所周知,linux能在pc中可靠地執行,正是因為當前的pc硬體已經全部採用了32位乃至64位系統,才會給象windows linux unix這些32位作業系統提...

嵌入式Linux之ARM彙編基礎

對於 cortex a 晶元來講,大部分晶元在上電以後c 語言環境還沒準備好,所以第一行程式肯定是彙編的,至於要寫多少匯程式設計序,那就看你能在哪一步把 c 語言環境準備好。所謂的 c語言環境就是保證 c 語言能夠正常執行。c 語言中的函式呼叫涉及到出棧入棧,出棧入棧就要對堆疊進行操作,所謂的堆疊其...

彙編中call指令和其對應的機器碼

call這個指令很神奇,他和別的指令不太一樣 對比下,當我們執行 mov eax,1 的時候,他的對應機器碼是 66 b8 01 00 00 00 這其中 66 b8 對應的是 mov eax,x 後面的 01 00 00 00 就是 1 在32位中的little endian了 所以說,在對mov...