使用教材
《“笨办法” 学C语言(Learn C The Hard Way)》
https://www.jianshu.com/p/b0631208a794
完整源码
[习题18]回调函数: test_sorting( ..., ... , 排序函数, 排序规则)
https://www.jianshu.com/p/ed977157da73
输出函数自身的汇编字节码
- 新增函数
dump
,使用强制类型转换,用一个char类型
指针data
,指向函数cmp
的开头,使用%02x
输出十六进制数据
void dump(compare_cb cmp)
{
int i = 0;
unsigned char *data = (unsigned char *)cmp;
for(i = 0; i < 25; i++) {
printf("%02x:", data[i]);
}
printf("\n");
}
-
main
函数中新增用例,传入函数名sorted_order(后面在反汇编输出的数据里,也可以根据这个函数去找)
printf("Hex:\n");
dump(sorted_order);
- 命令行编译,运行结果:输出函数
cmp
开始处的25个字节
$ ./ex18_a 4 1 7 3 2 0 8
Hex:
55:48:89:e5:89:7d:fc:89:75:f8:8b:75:fc:2b:75:f8:89:f0:5d:c3:66:66:66:2e:0f:
反汇编
- 使用
objdump
命令,可以查看汇编指令以及真实的机器码;
[汇编]gcc生成汇编.s文件
$ gcc -Og -S sum.c /$ gcc -Og -S -masm=intel sum.c
与 反汇编 objdump
https://www.jianshu.com/p/42f87e4cb378
sorted_order 汇编字节码
- 可以看到
55
其实一个push
指令,48 89 e5
是一组,是一个mov
指令,以此类推,前25个字节都与运行结果里的输出是一致的; -
ATT
格式$ objdump -d ex18_a
0000000000400a00 :
400a00: 55 push %rbp
400a01: 48 89 e5 mov %rsp,%rbp
400a04: 89 7d fc mov %edi,-0x4(%rbp)
400a07: 89 75 f8 mov %esi,-0x8(%rbp)
400a0a: 8b 75 fc mov -0x4(%rbp),%esi
400a0d: 2b 75 f8 sub -0x8(%rbp),%esi
400a10: 89 f0 mov %esi,%eax
400a12: 5d pop %rbp
400a13: c3 retq
400a14: 66 66 66 2e 0f 1f 84 data32 data32 nopw %cs:0x0(%rax,%rax,1)
400a1b: 00 00 00 00 00
-
Intel
格式$ objdump -M intel -d ex18_a
0000000000400a00 :
400a00: 55 push rbp
400a01: 48 89 e5 mov rbp,rsp
400a04: 89 7d fc mov DWORD PTR [rbp-0x4],edi
400a07: 89 75 f8 mov DWORD PTR [rbp-0x8],esi
400a0a: 8b 75 fc mov esi,DWORD PTR [rbp-0x4]
400a0d: 2b 75 f8 sub esi,DWORD PTR [rbp-0x8]
400a10: 89 f0 mov eax,esi
400a12: 5d pop rbp
400a13: c3 ret
400a14: 66 66 66 2e 0f 1f 84 data32 data32 nop WORD PTR cs:[rax+rax*1+0x0]
400a1b: 00 00 00 00 00