寄存器(1)寄存器概念,x86寄存器种类说明及汇编代码详解 您所在的位置:网站首页 x86寄存器地址 寄存器(1)寄存器概念,x86寄存器种类说明及汇编代码详解

寄存器(1)寄存器概念,x86寄存器种类说明及汇编代码详解

2024-07-03 08:25| 来源: 网络整理| 查看: 265

寄存器(1)寄存器概念,x86寄存器种类说明及汇编代码详解 1. 什么是寄存器1.1 概念1. 什么是寄存器:2. 寄存器作用: 1.2 通俗易懂理解寄存器 2. x86寄存器种类说明及汇编代码详解2.1 通用寄存器2.1.1 ax/eax/rax 累加(Accumulator)寄存器2.1.2 bx/ebx/rbx 基址(Base)寄存器2.1.3 cx/ecx/rcx 计数器(Counter)寄存器2.1.4 dx/edx/rdx 数据(Data)寄存器2.2.5 si/esi/rsi 来源索引(Source Index)寄存器2.2.6 di/edi/rdi 目的索引(Destination Index) 2.2. 指针寄存器2.3.1 bp/ebp/rbp 基址指针(Base Point)寄存器2.3.2 sp/esp/rsp 堆栈指针(Stack Point)寄存器 2.3. 段寄存器2.4. 标志寄存器2.5. 其他寄存器:EIP寄存器,tr寄存器2.5.1 EIP寄存器2.5.2tr寄存器-任务寄存器TR 2.6. x86-64 参数传递:%rdi, %rsi, %rdx, %rcx, %r8, %r9 用作函数参数,依次对应第1个参数,第2个参数 … 3. x86函数大致处理流程4. x86汇编代码详解4.1 代码例子1:register.c4.1.1 gcc -c register.c -o register.o4.1.2 objdump -x -s -d register.o 反汇编示例 4.2 代码例子2:add_a_and_b4.2.1 简单代码:4.2.2 代码汇编说明: 4.3. 代码例子3:callee4.3.1 huibian2.c4.3.2 汇编代码及解释 5. 其他:函数帧说明5.1 函数帧概念:5.2 gdb 调试:5.2.1. frame num 6. 常用定位处理流程(以x86为例):6.1 第一步:看堆栈,看死在哪个函数(如果是release版本栈不全)6.2 第二步: 看寄存器(看入参,rdi rsi,rdx……是否对的上,是否被修改过)6.2.1 x /10gx 0x7f8ebd47e0a0 看内存值6.2.2 (gdb) info symbol 0x7f8ec0487760 看符号,函数名 6.3 第三步:如果寄存器值被改变,那就反汇编看函数:disassemble func 7. KDB,MIPS汇编相关详解参考 寄存器(3)KDB入门+MIPS汇编及汇编代码详解 https://blog.csdn.net/lqy971966/article/details/115862769

1. 什么是寄存器 1.1 概念 1. 什么是寄存器:

CPU 本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU 要用的时候就去内存读写数据。但是,CPU 的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存。基本上,CPU 缓存可以看作是读写速度较快的内存。

但是,CPU 缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU 每次读写都要寻址也会拖慢速度。因此,除了缓存之外,CPU 还自带了寄存器(register),用来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据。

2. 寄存器作用: 寄存器是CPU的组成部部分,用来暂存指令、数据和地址是有限存储容量的高速存储部件,其读写速度是最快的,不需要IO传输寄存器的作用主要是: 可将寄存器内的数据执行算术及逻辑运算; 存于寄存器内的地址可用来指向内存的某个位置,即寻址; 可以用来读写数据到电脑的周边设备。 1.2 通俗易懂理解寄存器

寄存器就是你的口袋。身上只有那么几个,只装最常用或者马上要用的东西。 内存就是你的背包。有时候拿点什么放到口袋里,有时候从口袋里拿出点东西放在背包里。 辅存就是你家里的抽屉。可以放很多东西,但存取不方便。

常用寄存器 16/32/64位

2. x86寄存器种类说明及汇编代码详解

有八个常用程序寄存器%eax、%ecx、%edx、%ebx、%esi、%edi、%espρ和%ebp 前六个是通用寄存器,一般可以一般使用,后两个是指针寄存器

2.1 通用寄存器

顾名思义,通用寄存器是那些你可以根据自己的意愿使用的寄存器,修改他们的值通常不会对计算机的运行造成很大的影响。通用寄存器最多的用途是计算。

2.1.1 ax/eax/rax 累加(Accumulator)寄存器

常用于乘、除法和函数返回值

2.1.2 bx/ebx/rbx 基址(Base)寄存器

被调用者保存/常做内存数据的指针, 或者说常以它为基址来访问内存.

2.1.3 cx/ecx/rcx 计数器(Counter)寄存器

常做字符串和循环操作中的计数器

2.1.4 dx/edx/rdx 数据(Data)寄存器

常用于乘、除法和 I/O 指针

2.2.5 si/esi/rsi 来源索引(Source Index)寄存器

存储器指针、串指令中的源操作数指针

2.2.6 di/edi/rdi 目的索引(Destination Index)

存储器指针、串指令中的目的操作数指针

2.2. 指针寄存器

有八个程序寄存器%eax、%ecx、%edx、%ebx、%esi、%edi、%espρ和%ebp

2.3.1 bp/ebp/rbp 基址指针(Base Point)寄存器

被调用者保存/栈基址寄存器-指向栈底

2.3.2 sp/esp/rsp 堆栈指针(Stack Point)寄存器

栈寄存器-指向栈顶

2.3. 段寄存器

CS——代码段寄存器(CodeSegmentRegister),其值为代码段的段值; DS——数据段寄存器(DataSegmentRegister),其值为数据段的段值; SS——堆栈段寄存器(StackSegmentRegister),其值为堆栈段的段值; ES——附加段寄存器(ExtraSegmentRegister),其值为附加数据段的段值; FS——附加段寄存器(ExtraSegmentRegister),其值为附加数据段的段值(32位CPU新增); GS——附加段寄存器(ExtraSegmentRegister),其值为附加数据段的段值(32位CPU新增)。

2.4. 标志寄存器

进位标志CF(CarryFlag) 奇偶标志PF(ParityFlag) 辅助进位标志AF(AuxiliaryCarryFlag) 零标志ZF(ZeroFlag) 符号标志SF(SignFlag) 溢出标志OF(OverflowFlag)

2.5. 其他寄存器:EIP寄存器,tr寄存器 2.5.1 EIP寄存器

用来存储CPU要读取指令的地址,CPU通过EIP寄存器读取即将要执行的指令。每次CPU执行完相应的汇编指令之后,EIP寄存器的值就会增加。

2.5.2tr寄存器-任务寄存器TR

TR用于寻址一个特殊的任务状态段(Task State Segment,TSS)。 应用: 总结在进程从用户态到内核态切换过程,Linux主要做的事 1.读取tr寄存器,访问TSS段 2.从TSS段中的sp0获取进程内核栈的栈顶指针 3.由控制单元在内核栈中保存当前eflags,cs,ss,eip,esp寄存器的值。 4.由SAVE_ALL保存其寄存器的值到内核栈 5.把内核代码选择符写入CS寄存器,内核栈指针写入ESP寄存器,把内核入口点的线性地址写入EIP寄存. 此时,CPU已经切换到内核态,根据EIP中的值开始执行内核入口点的第一条指令(中断处理等)

2.6. x86-64 参数传递:%rdi, %rsi, %rdx, %rcx, %r8, %r9 用作函数参数,依次对应第1个参数,第2个参数 …

x86-64最多可以用 6 个寄存器传递参数,参数多于 6 个时,使用栈传递参数,如下,第一列表示寄存器位宽:

|----+------+------+------+------+------+------| | | 1 | 2 | 3 | 4 | 5 | 6 | |----+------+------+------+------+------+------| | 64 | %rdi | %rsi | %rdx | %rcx | %r8 | %r9 | | 32 | %edi | %esi | %edx | %ecx | %r8d | %r9d | | 16 | %di | %si | %dx | %cx | %r8w | %r9w | | 8 | %dil | %sil | %dl | %cl | %r8b | %r9b | |----+------+------+------+------+------+------|

%rdi, %rsi, %rdx, %rcx, %r8, %r9 用作函数参数,依次对应第1个参数,第2个参数 … r8(64位) r8d(32位) r8w(16位) r8b(8位) 返回值使用 rax 寄存器保存 在这里插入图片描述

3. x86函数大致处理流程 1. 调用者函数栈帧的栈底指针寄存器ebp入栈 push %ebp 2. ebp记录当前函数栈的栈底位置 mov %esp,%ebp 3. 申请栈空间 sub $0x3c,%esp 4. 获取函数参数,进行数据处理 或者从调用者的栈空间获取,或者直接从寄存器(eax/edx/ecx)中获取 5. 准备子函数参数,调用子函数(call指令),子函数返回(ret指令) 6. 函数返回,释放栈空间

说明: call指令负责跳转到指定的指令地址,并将返回指令地址IP(call指令的下一条指令)入栈,有时候需要将CS寄存器的值入栈; ret指令将返回地址出栈,跳转到返回地址;

参数传递 由于x86寄存器比较少的缘故,缺省情况下,函数调用,参数的传递使用的是栈,而不是寄存器。 一般情况下,参数的压栈顺序是从右至左。也许我们会看到一种叫做“fastcall”的调用方式,GCC会使用两个寄存器来传递参数,其它的参数,则还是使用栈来传递

4. x86汇编代码详解 4.1 代码例子1:register.c 4.1.1 gcc -c register.c -o register.o root@ubuntu-admin-a1:/home# cat register.c #include int printf(const char* format,...); int g_init_var = 2; int g_uinit_var; void func1(int i) { int res = i*i; int iLoop = 0; for(iLoop = 0;iLoop < 3;iLoop++) { printf("iLoop = %d\n",iLoop); } printf("%d\n",i); printf("i*i = %d\n",res); } int main() { static int iStaticVar = 3; static int iStaticVar2; int a = 1; int b; func1(iStaticVar + iStaticVar2 + a + b); return 0; } root@ubuntu-admin-a1:/home# 4.1.2 objdump -x -s -d register.o 反汇编示例 root@ubuntu-admin-a1:/home# objdump -x -s -d register.o …………省略 0000000000000000 : 汇编指令 汇编代码 0: 55 push %rbp 压栈 1: 48 89 e5 mov %rsp,%rbp %rsp=%rbp 4: 48 83 ec 20 sub $0x20,%rsp %rsp-=0x20 开栈大小32字节 8: 89 7d ec mov %edi,-0x14(%rbp) %rbp - 0x14 =%edi 参数i赋值到%rbp-0x14 处 b: 8b 45 ec mov -0x14(%rbp),%eax 下面类似 e: 0f af 45 ec imul -0x14(%rbp),%eax 12: 89 45 fc mov %eax,-0x4(%rbp) 15: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp) 1c: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp) 23: eb 18 jmp 3d 25: 8b 45 f8 mov -0x8(%rbp),%eax 28: 89 c6 mov %eax,%esi 2a: bf 00 00 00 00 mov $0x0,%edi 2b: R_X86_64_32 .rodata 2f: b8 00 00 00 00 mov $0x0,%eax 34: e8 00 00 00 00 callq 39 35: R_X86_64_PC32 printf-0x4 39: 83 45 f8 01 addl $0x1,-0x8(%rbp) 3d: 83 7d f8 02 cmpl $0x2,-0x8(%rbp) 41: 7e e2 jle 25 43: 8b 45 ec mov -0x14(%rbp),%eax 46: 89 c6 mov %eax,%esi 48: bf 00 00 00 00 mov $0x0,%edi 49: R_X86_64_32 .rodata+0xc 4d: b8 00 00 00 00 mov $0x0,%eax 52: e8 00 00 00 00 callq 57 53: R_X86_64_PC32 printf-0x4 57: 8b 45 fc mov -0x4(%rbp),%eax 5a: 89 c6 mov %eax,%esi 5c: bf 00 00 00 00 mov $0x0,%edi 5d: R_X86_64_32 .rodata+0x10 61: b8 00 00 00 00 mov $0x0,%eax 66: e8 00 00 00 00 callq 6b 67: R_X86_64_PC32 printf-0x4 6b: 90 nop 6c: c9 leaveq 6d: c3 retq 000000000000006e : 6e: 55 push %rbp 6f: 48 89 e5 mov %rsp,%rbp 72: 48 83 ec 10 sub $0x10,%rsp 76: c7 45 f8 01 00 00 00 movl $0x1,-0x8(%rbp) 7d: 8b 15 00 00 00 00 mov 0x0(%rip),%edx # 83 7f: R_X86_64_PC32 .data 83: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 89 85: R_X86_64_PC32 .bss-0x4 89: 01 c2 add %eax,%edx 8b: 8b 45 f8 mov -0x8(%rbp),%eax 8e: 01 c2 add %eax,%edx 90: 8b 45 fc mov -0x4(%rbp),%eax 93: 01 d0 add %edx,%eax 95: 89 c7 mov %eax,%edi 97: e8 00 00 00 00 callq 9c 98: R_X86_64_PC32 func1-0x4 9c: b8 00 00 00 00 mov $0x0,%eax a1: c9 leaveq a2: c3 retq root@ubuntu-admin-a1:/home#

readelf 和 objdump 例子详解及区别 https://blog.csdn.net/lqy971966/article/details/106905237

4.2 代码例子2:add_a_and_b 4.2.1 简单代码: int add_a_and_b(int a, int b) { return a + b; } int main() { return add_a_and_b(2, 3); } 4.2.2 代码汇编说明: _add_a_and_b: push %ebx //5. 表示将 EBX 寄存器里面的值,写入_add_a_and_b这个帧 push 指令会再将 ESP 寄存器里面的地址减去4个字节(累计减去12) mov %eax, [%esp+8] //6. 这一行代码表示,先将 ESP 寄存器里面的地址加上8个字节, 得到一个新的地址,然后按照这个地址在 Stack 取出数据 根据前面的步骤,可以推算出这里取出的是2,再将2写入 EAX 寄存器 mov 指令用于将一个值写入某个寄存器 mov %ebx, [%esp+12] //7. 上面的代码将 ESP 寄存器的值加12个字节, 再按照这个地址在 Stack 取出数据,这次取出的是3,将其写入 EBX 寄存器 add %eax, %ebx // 7. 将 EAX 寄存器的值(即2)加上 EBX 寄存器的值(即3),得到结果5, 再将这个结果写入第一个运算子 EAX 寄存器 add 指令用于将两个运算子相加,并将结果写入第一个运算子 pop %ebx // 8. 取出 Stack 最近写入的值(即 EBX 寄存器的原始值), 再将这个值写回 EBX 寄存器(因为加法已经做完了,EBX 寄存器用不到了 pop 指令用于取出 Stack 最近一个写入的值(即最低位地址的值), 并将这个值写入运算子指定的位置 注意, pop 指令还会将 ESP 寄存器里面的地址加4, 即回收4个字节 push的时候加的4字节。 ret // 9. ret指令用于终止当前函数的执行, 将运行权交还给上层函数。也就是,当前函数的帧将被回收。 /* 1. 根据约定,程序从_main标签开始执行,这时会在 Stack 上为main建立一个帧, 并将 Stack 所指向的地址,写入 ESP 寄存器。 后面如果有数据要写入main这个帧,就会写在 ESP 寄存器所保存的地址。 */ _main: push 3 //2. push 指令用于将运算子放入 Stack,这里就是将3写入main这个帧 push 指令其实有一个前置操作。 它会先取出 ESP 寄存器里面的地址, 将其减去4个字节,然后将新地址写入 ESP 寄存器。 使用减法是因为 Stack 从高位向低位发展, 4个字节则是因为3的类型是int,占用4个字节。 push 2 //3. push 指令将2写入main这个帧,位置紧贴着前面写入的3。 这时,ESP 寄存器会再减去 4个字节(累计减去8)。 call _add_a_and_b //4. call 指令用来调用函数,这里表示调用add_a_and_b函数。 这时,程序就会去找_add_a_and_b标签,并为该函数建立一个新的帧。 add %esp, 8 // 10. 将 ESP 寄存器里面的地址,手动加上8个字节,再写回 ESP 寄存器 前面的pop操作已经回收了4个字节,这里再回收8个字节,等于全部回收 ret // 11. 最后,main函数运行结束,ret指令退出程序执行。

参考: http://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html

4.3. 代码例子3:callee 4.3.1 huibian2.c #include #include int callee(int a, long b) { int c = a; c += (int)b; return c; } void caller() { int v = callee(10, 20); printf("v=%d\n", v); } int main(int argc, char** argv) { caller(); return 0; } 4.3.2 汇编代码及解释

[root@localhost home]# gcc -c huibian2.c -o hui2.o [root@localhost home]# objdump -x -s -d hui2.o

0000000000000000 : 汇编指令 汇编代码 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 89 7d ec mov %edi,-0x14(%rbp) //edi寄存器中的值 10 放到 rbp 寄存器向下移动 20 字节处 7: 48 89 75 e0 mov %rsi,-0x20(%rbp) //rsi 寄存器中的值 20 放到 rbp 寄存器向下移动 32 字节处 b: 8b 45 ec mov -0x14(%rbp),%eax //bp 寄存器向下移动20字节 就是 10 放到 eax 寄存器中 e: 89 45 fc mov %eax,-0x4(%rbp) //eax中的值 就是10 放到 bp 向下4字节出 也就是变量c中 11: 48 8b 45 e0 mov -0x20(%rbp),%rax // bp 向下32字节 也就是 20 放到寄存器 rax 中 15: 01 45 fc add %eax,-0x4(%rbp) // rbp = (rbp - 4) + eax 就是 20 + 10 18: 8b 45 fc mov -0x4(%rbp),%eax // 将 30 放到 eax 寄存器中 1b: 5d pop %rbp 1c: c3 retq 000000000000001d : 汇编指令 汇编代码 1d: 55 push %rbp 1e: 48 89 e5 mov %rsp,%rbp 21: 48 83 ec 10 sub $0x10,%rsp //开栈 25: be 14 00 00 00 mov $0x14,%esi //将 20 赋值给 esi 寄存器 2a: bf 0a 00 00 00 mov $0xa,%edi //将 10 赋值给 edi 寄存器 2f: e8 00 00 00 00 callq 34 //调用 callee 函数 30: R_X86_64_PC32 callee-0x4 34: 89 45 fc mov %eax,-0x4(%rbp) // 将上面 callee 返回值 30 存到 bp -4字节处 也就是 v 中 37: 8b 45 fc mov -0x4(%rbp),%eax 3a: 89 c6 mov %eax,%esi 3c: bf 00 00 00 00 mov $0x0,%edi 3d: R_X86_64_32 .rodata 41: b8 00 00 00 00 mov $0x0,%eax 46: e8 00 00 00 00 callq 4b // 调用 printf 打印 47: R_X86_64_PC32 printf-0x4 4b: c9 leaveq 4c: c3 retq 000000000000004d : 汇编指令 汇编代码 4d: 55 push %rbp 4e: 48 89 e5 mov %rsp,%rbp 51: 48 83 ec 10 sub $0x10,%rsp //开栈 55: 89 7d fc mov %edi,-0x4(%rbp) 58: 48 89 75 f0 mov %rsi,-0x10(%rbp) 5c: b8 00 00 00 00 mov $0x0,%eax 61: e8 00 00 00 00 callq 66 62: R_X86_64_PC32 caller-0x4 66: b8 00 00 00 00 mov $0x0,%eax 6b: c9 leaveq 6c: c3 retq [root@localhost home]# 5. 其他:函数帧说明 5.1 函数帧概念:

函数调用栈由连续的栈帧组成。每个栈帧记录一个函数调用的信息,这些信息包括函数参数,函数变量,函数运行地址。

当程序启动后,栈中只有一个帧,这个帧就是main函数的帧。我们把这个帧叫做初始化帧或者叫做最外层帧。 每当一个函数被调用,一个新帧将被建立,每当一个函数返回时,函数帧将被剔除。 如果函数是个递归函数,栈中将有很多帧是 记录同一个函数的。但前执行的函数的帧被称作最深帧,这个帧是现存栈中最近被创建的帧。

5.2 gdb 调试:

gdb 为所有存活的栈帧分配一个数字编号,最深帧的编号是0,被它调用的内个帧的编号就是1。 这些编号子程序中是不存在的,只不过时调试的时候被gdb用的。

关于函数帧的两个指令:

5.2.1. frame num 移动到 num 指定的栈帧中去,并打印选中的栈的信息。如: frame 3 num 可以时帧编号或者时帧的地址。如果没有args,则打印当前帧的信息。 6. 常用定位处理流程(以x86为例): 6.1 第一步:看堆栈,看死在哪个函数(如果是release版本栈不全) (gdb) bt #0 0x00007f8ebfee416d in YYY_CTX_set_info_callback () from /lib/libfwdssl.so #1 0x00007f8ec0493301 in _conn_UsrAccept () from /lib/libXXX_lb.so #2 0x00007f8ec04938b0 in _conn_ListenNotify () from /lib/libXXX_lb.so #3 0x00007f8f4b4bc406 in tp_fsm_ProcNewEstaConn () from /lib/libXXX_tcpproxy.so #4 0x00007f8f4b4bd69c in tp_fsm_SynReceived_Ack () from /lib/libXXX_tcpproxy.so

如果还能复现,就直接断住该函数,单步跟踪查看即可看出问题所在。下面就不用看了

6.2 第二步: 看寄存器(看入参,rdi rsi,rdx……是否对的上,是否被修改过)

如果是指针入参,看是否为空 踩空指针

(gdb) info registers rax 0xfedabebb 4275748539 rbx 0x0 0 rcx 0x4f 79 rcx …… rdx 0x1 1 rdx 第三个参数 rsi 0x7f8f3ef01500 140253212972288 rsi 第二个参数 rdi 0xc 12 rdi 第一个参数 rbp 0x7f8ebd47e0a0 0x7f8ebd47e0a0 rsp 0x7f8f3eefe800 0x7f8f3eefe800 r8 0x7f8f5f9e12c0 140253761245888 r9 0x0 0 r10 0x1b73230 28783152 r11 0x0 0 r12 0x7f8ec0487760 140251088058208 r13 0x80 128 r14 0x4 4 r15 0x7f8ec076c2e0 140251091092192 rip 0x7f8ebfee416d 0x7f8ebfee416d eflags 0x13206 [ PF IF #12 #13 RF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 ---Type to continue, or q to quit--- fs 0x0 0 gs 0x0 0 6.2.1 x /10gx 0x7f8ebd47e0a0 看内存值 (gdb) x /10gx 0x7f8ebd47e0a0 10个内存单元 g:8字节 x:按十六进制格式显示变量 0x7f8ebd47e0a0: 0x00007f8ebd244370 0x0000000000000000 0x7f8ebd47e0b0: 0x00007f8ebfee5500 0x00007f8ebfee5500 0x7f8ebd47e0c0: 0x00000000fedabedb 0x0000000000000175 0x7f8ebd47e0d0: 0x00007f8f5fc01560 0x00007f8f5fc015b0 0x7f8ebd47e0e0: 0x00007f8f5fc01600 0x00007f8f5fc01650 (gdb) 6.2.2 (gdb) info symbol 0x7f8ec0487760 看符号,函数名 (gdb) info symbol 0x7f8ec0487760 YYY_Debug_InfoCallback in section .text of /lib/libBBB_lb.so (gdb) 6.3 第三步:如果寄存器值被改变,那就反汇编看函数:disassemble func

对着代码 1.通过=> 看死在那一次寄存器操作 2.通过推导 看寄存器怎么死的

(gdb) disassemble XXX_CTX_set_info_callback Dump of assembler code for function XXXL_CTX_set_info_callback: 0x00007f8ebfee4120 : nopw 0x0(%rax,%rax,1) 0x00007f8ebfee4126 : test %rdi,%rdi 0x00007f8ebfee4129 : je 0x7f8ebfee4198 0x00007f8ebfee412b : cmpq $0x0,(%rdi) 0x00007f8ebfee412f : je 0x7f8ebfee4198 0x00007f8ebfee4131 : push %r13 0x00007f8ebfee4133 : push %r12 0x00007f8ebfee4135 : mov %rsi,%r12 0x00007f8ebfee4138 : push %rbp 0x00007f8ebfee4139 : mov %rdi,%rbp 0x00007f8ebfee413c : push %rbx 0x00007f8ebfee413d : sub $0x8,%rsp 0x00007f8ebfee4141 : mov 0x205e78(%rip),%rax # 0x7f8ec00e9fc0 0x00007f8ebfee4148 : mov (%rax),%ebx 0x00007f8ebfee414a : callq 0x7f8ebfee17d0 0x00007f8ebfee414f : test %ebx,%ebx 0x00007f8ebfee4151 : je 0x7f8ebfee4186 0x00007f8ebfee4153 : lea -0x1(%rbx),%eax ---Type to continue, or q to quit--- 0x00007f8ebfee4156 : xor %ebx,%ebx 0x00007f8ebfee4158 : lea 0x8(,%rax,8),%r13 0x00007f8ebfee4160 : mov 0x0(%rbp),%rax 0x00007f8ebfee4164 : mov (%rax,%rbx,1),%rax --- 相当于 rax = 2rax 0x00007f8ebfee4168 : test %rax,%rax 0x00007f8ebfee416b : je 0x7f8ebfee417d => 0x00007f8ebfee416d : mov (%rax),%rdi //死在这一行 应该是 %rax 寄存器出了问题 0x00007f8ebfee4170 : test %rdi,%rdi …… …… End of assembler dump. (gdb)

6.4 反汇编 lib 看函数 符号

bash-4.4# objdump -d /lib/libXXX_lb.so > 2.txt bash-4.4# ls -l *.txt -rwxrwxrwx 1 root root 19852165 Jun 9 17:35 2.txt bash-4.4# 然后查看txt搜索函数名

这个好像没啥用 还不如直接反汇编看函数:disassemble func

7. KDB,MIPS汇编相关详解

寄存器(3)KDB入门+MIPS汇编及汇编代码详解 https://blog.csdn.net/lqy971966/article/details/115862769

参考

https://www.cnblogs.com/findumars/p/4121962.html https://blog.csdn.net/striver1205/article/details/25420891



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有