linux 反汇编初步

工具

十六进制编辑器:hexedit
还有objdump,xxd等查看工具


hexedit使用

暂时只用hexedit来读二进制文件

#hexedit filename  //查看文件  

常用操作键
Ctrl-X: save and exit
Ctrl-C: exit without saving
tab: 在hex和ascii窗口之间切换
Ctrl-U: undo all
Ctrl-S: search forward

objdump使用

编译程序的时候,gcc添加-g选项,增加调试信息

#gcc test.c -g -o test

常用参数
-S(source):表示读取哪个文件
-j:选择读出哪个section,可以通过objdump -h来查看所有的section



看懂AT&T汇编

由于objdump反汇编得到的结果主要都是AT&T格式的汇编(不过好像可以选择?),而且linux内核代码也有不少AT&T格式的汇编代码,所以有必要学习一下

AT&T汇编特点

1.寄存器前面要加%,如:mov %eab,%ebx
    注意源寄存器和目标寄存器的顺序与intel汇编更好相反,at&t中左边是源寄存器,右边是目标寄存器。所以上面指令是将eax的值赋给ebx
2.立即数/常数前面要加‘$’,符号常数值直接用。
    关于符号常量注意理解下面两句:
    mov A,%eax     //将A代表的值赋给eax,如A=10,则eax里面的值就是10
    mov $A,%eax     //将A代表的值当作地址,将对应地址的值赋给eax,如A=0x10,0x10处存则20,则把地址0x10处对应的值20赋给eax
3.movb:8位(byte)    movw:16位(word)    movl:32位(long)  
others:    s=short(16-bit integer) or single(32-bit floating point)
    q=quad(64 bits)
    t=ten bytes(80 bits floating point)
注:如果suffix没有指定且不是内存操作,GAS(Gnu AS)会根据目标寄存器的大小来决定
4.call/jmp语句的操作数前面要加上“*”作为前缀,远跳转ljmp,远调用lcall,远返回lret

5.寻址规则:displacement(base register, offset register, scalar multiplier)
  计算方法:(base+dis)+(offset*multiplier)
  举例:
    movl    -4(%ebp, %edx, 4), %eax  # Full example: load *(ebp - 4 + (edx * 4)) into eax
    movl    (%ecx), %edx             # No offset: copy the target of a pointer into a register

C语言内嵌汇编

格式:
asm(“asm statement”:outputs:inputs:registers-modified)
tips:
1.在嵌入汇编中,寄存器前面要加两个%,因为gcc在编译时,会去掉一个%再输出成汇编格式

主要寄存器及其作用

8086有14个16位寄存器,按照用途分为:

1.通用寄存器(8个)
2.指令指针(IP,1个)
3.标志寄存器(FR,1个)
4.段寄存器(4个)


通用寄存器又可以分成2类:数据寄存器和指针寄存器及变址寄存器,各4个
ax:常用于计算。另外所有的I/O指令都使用这一寄存器与外界设备传送数据
bx:基址寄存器
cx:计数寄存器
dx:数据寄存器

SP:堆栈指针,与SS配合使用,可指向目前的堆栈位置  
BP:基址寄存器,可作为SS的相对基址位置  
SI:source index,源变址寄存器------暂不理解  
DI:destination index,目的变址寄存器  
上面四个寄存器只能按16位进行操作,主要用来形成操作数的地址  

指令指针IP
IP:16位专用寄存器,用来指向当前执行指令的下一条指令的地址。注意,IP指向的是指令地址的段内地址偏移量
标志寄存器FR
16位的寄存器,有意义的有9位,6位是状态位,3位是控制位
分布图:

#################################################
#  #  #  #  #OF#DF#IF#TF#SF#ZF#  #AF#  #PF#  #CF#
#################################################
#15#14#13#12#11#10# 9# 8# 7# 6# 5# 4# 3# 2# 1# 0#
#################################################
各个标志的含义:  
OF:overflow  
DF:direction
IF:中断允许标志,标志是否响应CPU‘外部可屏蔽‘中断,1表示响应
TF:跟踪标志
SF:符号标志,与运算结果的最高位相同
ZF:零标志,反映运算结果是否为0
AF:辅助进位标志
PF:奇偶标志反映运算结果中’1‘的个数,PF=1表示偶数个’1CF:进位标志反映运算结果是否产生进位或借位

段寄存器
CS:code segment
DS:data segment
SS:stack segment
ES:extra segment


80386寄存器

寄存器都是32位宽
通用寄存器
EAX,EBX,ECX,EDX
特殊寄存器
ESI:通常在内存操作中作为“源地址指针”使用,DS是默认段寄存器
EDI:通常在内存操作中作为“目标地址指针”,DS是默认段寄存器
EBP:通常被高级语言编译器用以建造‘堆栈帧’来保存函数或过程的局部变量,SS是默认段寄存器


主要参考资料

汇编中各寄存器的作用-堂吉歌德
X86 Assembly/GAS Syntax