3.Arm機器碼
首先匯編程序轉化為機器碼,才能在機器內運行。
首先我們對上面的裸機的代碼中生的.elf文件進行反匯編:
start.elf: file format elf32-littlearm
Disassembly of section .text:
50008000 <_start>:
.text
.global _start
_start:
@ldr和str的操作
mov r0,#0xff
50008000: e3a000ff mov r0, #255 ; 0xff
str r0,[r1]
50008004: e5810000 str r0, [r1]
ldr r2,[r1]
50008008: e5912000 ldr r2, [r1]
@程序狀態字寄存器訪問
mrs r0,cpsr
5000800c: e10f0000 mrs r0, CPSR
orr r0,#0b100
50008010: e3800004 orr r0, r0, #4 ; 0x4
msr cpsr,r0
50008014: e129f000 msr CPSR_fc, r0
@ror:循環右移
mov r1,#0b11
50008018: e3a01003 mov r1, #3 ; 0x3
mov r1,r1,ror#1
5000801c: e1a010e1 ror r1, r1, #1
@lsl:左移
mov r1,#0b11
50008020: e3a01003 mov r1, #3 ; 0x3
mov r1,r1,lsl#2
50008024: e1a01101 lsl r1, r1, #2
@bl指令:帶鏈接跳轉
bl func1
50008028: eb000005 bl 50008044 <func1>
@b指令:
mov r1,#6
5000802c: e3a01006 mov r1, #6 ; 0x6
mov r2,#7
50008030: e3a02007 mov r2, #7 ; 0x7
cmp r1,r2
50008034: e1510002 cmp r1, r2
bgt branch1@gt表示大於的時候跳轉
50008038: ca000003 bgt 5000804c <branch1>
add r3,r1,r2
5000803c: e0813002 add r3, r1, r2
b end
50008040: ea000002 b 50008050 <end>
50008044 <func1>:
func1:
mov r1,#23
50008044: e3a01017 mov r1, #23 ; 0x17
mov pc,lr@函數的返回,固定格式。
50008048: e1a0f00e mov pc, lr
5000804c <branch1>:
branch1:
sub r3,r1,r2
5000804c: e0413002 sub r3, r1, r2
50008050 <end>:
end:
nop
50008050: e1a00000 nop (mov r0,r0)
@tst指令:
mov r1,#0b101
50008054: e3a01005 mov r1, #5 ; 0x5
tst r1,#0b01
50008058: e3110001 tst r1, #1 ; 0x1
mov r1,#0b101
5000805c: e3a01005 mov r1, #5 ; 0x5
tst r1,#0b10
50008060: e3110002 tst r1, #2 ; 0x2
@cmp指令的操作:
mov r1,#2
50008064: e3a01002 mov r1, #2 ; 0x2
cmp r1,#1
50008068: e3510001 cmp r1, #1 ; 0x1
mov r1,#2
5000806c: e3a01002 mov r1, #2 ; 0x2
cmp r1,#3
50008070: e3510003 cmp r1, #3 ; 0x3
mov r1,#2
50008074: e3a01002 mov r1, #2 ; 0x2
cmp r1,#2
50008078: e3510002 cmp r1, #2 ; 0x2
@bic:位清除指令
mov r1,#0b1101011
5000807c: e3a0106b mov r1, #107 ; 0x6b
bic r2,r1,#0b1000011
50008080: e3c12043 bic r2, r1, #67 ; 0x43
@and的用法:邏輯與
mov r1,#5
50008084: e3a01005 mov r1, #5 ; 0x5
and r2,r1,#0
50008088: e2012000 and r2, r1, #0 ; 0x0
mov r1,#5
5000808c: e3a01005 mov r1, #5 ; 0x5
and r2,r1,#1
50008090: e2012001 and r2, r1, #1 ; 0x1
@add:加法:
add r1,r0,r2
50008094: e0801002 add r1, r0, r2
@sub:減法,注意被減數不能是立即數
mov r2,#4
50008098: e3a02004 mov r2, #4 ; 0x4
sub r0,r2,#2
5000809c: e2420002 sub r0, r2, #2 ; 0x2
mov r1,#3
500080a0: e3a01003 mov r1, #3 ; 0x3
sub r3,r1,r0
500080a4: e0413000 sub r3, r1, r0
@這是注釋,mov指令
mov r1,#6
500080a8: e3a01006 mov r1, #6 ; 0x6
mov r2,r1
500080ac: e1a02001 mov r2, r1
mov r3,#10
500080b0: e3a0300a mov r3, #10 ; 0xa
@mvn:傳值取反的值
mvn r0,#4 @r0:4取反變為-5
500080b4: e3e00004 mvn r0, #4 ; 0x4
mvn r1,#0b111000
500080b8: e3e01038 mvn r1, #56 ; 0x38
mvn r2,r1 @r2:0b111000
500080bc: e1e02001 mvn r2, r1
Disassembly of section .ARM.attributes:
00000000 <.ARM.attributes>:
0: 00001741 andeq r1, r0, r1, asr #14
4: 61656100 cmnvs r5, r0, lsl #2
8: 01006962 tsteq r0, r2, ror #18
c: 0000000d andeq r0, r0, sp
10: 00543405 subseq r3, r4, r5, lsl #8
14: 01080206 tsteq r8, r6, lsl #4
Disassembly of section .debug_line:
00000000 <.debug_line>:
0: 00000060 andeq r0, r0, r0, rrx
4: 001e0002 andseq r0, lr, r2
8: 01020000 tsteq r2, r0
c: 000d0efb strdeq r0, [sp], -fp
10: 01010101 tsteq r1, r1, lsl #2
14: 01000000 tsteq r0, r0
18: 00010000 andeq r0, r1, r0
1c: 72617473 rsbvc r7, r1, #1929379840 ; 0x73000000
20: 00532e74 subseq r2, r3, r4, ror lr
24: 00000000 andeq r0, r0, r0
28: 00020500 andeq r0, r2, r0, lsl #10
2c: 16500080 ldrbne r0, [r0], -r0, lsl #1
30: 2f302f2f svccs 0x00302f2f
34: 302f302f eorcc r3, pc, pc, lsr #32
38: 2f30302f svccs 0x0030302f
3c: 2f2f2f2f svccs 0x002f2f2f
40: 30312f30 eorscc r2, r1, r0, lsr pc
44: 2f302f30 svccs 0x00302f30
48: 2f302f30 svccs 0x00302f30
4c: 2f302f30 svccs 0x00302f30
50: 2f302f30 svccs 0x00302f30
54: 2f2f3030 svccs 0x002f3030
58: 2f2f302f svccs 0x002f302f
5c: 022f2f30 eoreq r2, pc, #192 ; 0xc0
60: 01010002 tsteq r1, r2
Disassembly of section .debug_info:
00000000 <.debug_info>:
0: 00000045 andeq r0, r0, r5, asr #32
4: 00000002 andeq r0, r0, r2
8: 01040000 tsteq r4, r0
c: 00000000 andeq r0, r0, r0
10: 50008000 andpl r8, r0, r0
14: 500080c0 andpl r8, r0, r0, asr #1
18: 72617473 rsbvc r7, r1, #1929379840 ; 0x73000000
1c: 00532e74 subseq r2, r3, r4, ror lr
20: 6d6f682f stclvs 8, cr6, [pc, #-188]!
24: 61732f65 cmnvs r3, r5, ror #30
28: 2f61626d svccs 0x0061626d
2c: 6a6f756c bvs 1bdd5e4 <_start-0x4e42aa1c>
30: 61702f69 cmnvs r0, r9, ror #30
34: 00317472 eorseq r7, r1, r2, ror r4
38: 20554e47 subscs r4, r5, r7, asr #28
3c: 32205341 eorcc r5, r0, #67108865 ; 0x4000001
40: 2e38312e rsfcsep f3, f0, #0.5
44: 01003035 tsteq r0, r5, lsr r0
48: Address 0x00000048 is out of bounds.
Disassembly of section .debug_abbrev:
00000000 <.debug_abbrev>:
0: 10001101 andne r1, r0, r1, lsl #2
4: 12011106 andne r1, r1, #-2147483647 ; 0x80000001
8: 1b080301 blne 200c14 <_start-0x4fe073ec>
c: 13082508 movwne r2, #34056 ; 0x8508
10: 00000005 andeq r0, r0, r5
Disassembly of section .debug_aranges:
00000000 <.debug_aranges>:
0: 0000001c andeq r0, r0, ip, lsl r0
4: 00000002 andeq r0, r0, r2
8: 00040000 andeq r0, r4, r0
c: 00000000 andeq r0, r0, r0
10: 50008000 andpl r8, r0, r0
14: 000000c0 andeq r0, r0, r0, asr #1
...
我們從上面的反匯編的代碼看到,在內存地址的后面有一串數字,這就是機器碼。
接下來我們打開我們的ARM Architecture Reference Manual.pdf。這是一份很重要的資料。在第三章的第一節:
上面就是機器碼的格式了。下面是31~28四位是條件信息:
Opcode指令類型的信息:21~14位:
下面我們就以mov指令為例,來講他的機器碼的內容。就是他對應的機器碼:
這里我們一下面兩條代碼:
為例:指令的詳解
首先是反匯編:如下:
我們通過轉變:
Mov r0,r1的機器碼0xe1a00001= 0b 1110 00 0 1101 0 0000 0000 000000000001
Moveq r0,0xff的機器碼0x03a000ff=0b 0000 00 1 1101 0 0000 0000 000011111111
上面就是兩個指令對應的機器碼:
下面是mov機器碼的格式:
我們在上面的機器碼分析中知道,后12位是表示數的大小的。可是只有8位2進制數大小,前面四位是移位信息位。所以表示的數最大0xff。當我們把他改為0x1ff的時候會報錯:
這就是下來要學習的了:偽指令。
偽指令
2.偽指令定義:
偽/指令本身並沒有所對應的機器碼,它只是在編譯的時候起作用,或者轉化為其他的實際指令來運行。
指令看似該指令執行了操作,其實他不會產生機器碼。偽指令的作用:1、它只是在編譯的時候起作用,就像我們在C語言用#define定義一個宏一樣,只是在編譯的時候起作用。
2、能夠起到操作的作用,是轉為其他指令運行。
一、定義類偽指令:
Global:定義一個全局的符號。
Data:定義數據段。數據存到數據段。
Ascii:字符串
Byte:字節
Word:字
Equ:相當於宏定義
Align:設置對齊。
代碼:
編譯的截圖:
上圖知道:data的起始地址是500080c8:往下內容:
上面可以看到,我們的數據已經存進了數據段了。以后,我們就可以通過標號訪問數據段的數據了。
Equ:宏定義偽指令
上面可以看到r0是0x89,宏定義成功。
Align的例子:
我們從上面的例子知道,bh標號處的地址是500080d3,是沒有四字節對齊的。現在我們設置他四字節對齊:
設置后的地址變成500080e0是能被四整除的,是四字節對齊。
-
操作類偽指令:
Ldr的例子:
運行結果:
由於偽指令是轉為實際的指令執行的呢?
反匯編看看:
他是轉化為實際的ldr存儲器指令運行的。
Nop的例子:是空操作是延時的作用。
反匯編:
實際的操作是mov r0,r0的操作,沒有什么意義,只是延時操作。
反匯編的命令:
arm-linux-objdump -D -S start.elf
查看信息:
arm-linux-readelf -a start.elf