4. 比较指令差异¶
以一段C代码为例,实现两数相乘
#include <stdio.h>
int main(){
int a = 2;
int b = 5;
int c = a * b;
printf("a * b = %d\n", c);
}
编译并且反汇编出可执行程序的汇编代码:
gcc add.c
objdump -d add.out
Kunpeng | intel
|
0000000000400600 <main>: │ 000000000040052d <main>:
400600: a9be7bfd stp x29, x30, [sp,#-32]! │ 40052d: 55 push %rbp
400604: 910003fd mov x29, sp │ 40052e: 48 89 e5 mov %rsp,%rbp
400608: 52800040 mov w0, #0x2 // #2│ 400531: 48 83 ec 10 sub $0x10,%rsp
40060c: b9001fa0 str w0, [x29,#28] │ 400535: c7 45 fc 02 00 00 00 movl $0x2,-0x4(%rbp)
400610: 528000a0 mov w0, #0x5 // #5│ 40053c: c7 45 f8 05 00 00 00 movl $0x5,-0x8(%rbp)
400614: b9001ba0 str w0, [x29,#24] │ 400543: 8b 45 fc mov -0x4(%rbp),%eax
400618: b9401fa1 ldr w1, [x29,#28] │ 400546: 0f af 45 f8 imul -0x8(%rbp),%eax
40061c: b9401ba0 ldr w0, [x29,#24] │ 40054a: 89 45 f4 mov %eax,-0xc(%rbp)
400620: 1b007c20 mul w0, w1, w0 │ 40054d: 8b 45 f4 mov -0xc(%rbp),%eax
400624: b90017a0 str w0, [x29,#20] │ 400550: 89 c6 mov %eax,%esi
400628: 90000000 adrp x0, 400000 <_init-0x428│ 400552: bf 00 06 40 00 mov $0x400600,%edi
40062c: 911b8000 add x0, x0, #0x6e0 │ 400557: b8 00 00 00 00 mov $0x0,%eax
400630: b94017a1 ldr w1, [x29,#20] │ 40055c: e8 af fe ff ff callq 400410 <printf@plt>
400634: 97ffff97 bl 400490 <printf@plt> │ 400561: c9 leaveq
400638: a8c27bfd ldp x29, x30, [sp],#32 │ 400562: c3 retq
40063c: d65f03c0 ret │ 400563: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
│ 40056a: 00 00 00
│ 40056d: 0f 1f 00 nopl (%rax)
我们总结差如下
- ARM的指令都是8字节的(64位机上),intel 是可变长的,如第二行的push指令是1字节,编码是55。 第三行的mov指令是3字节,编码是48 89 e5。
- ARM和intel的寻址方式表示不一样
- ARM的寄存器是X(8字节)或者W(4字节)加数字。 intel的寄存器是eax, ebx等名称