3.Arm机器码
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