寄存器(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.c
      • 4.1.1 gcc -c register.c -o register.o
      • 4.1.2 objdump -x -s -d register.o 反汇编示例
    • 4.2 代码例子2:add_a_and_b
      • 4.2.1 简单代码:
      • 4.2.2 代码汇编说明:
    • 4.3. 代码例子3:callee
      • 4.3.1 huibian2.c
      • 4.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. 寄存器作用:

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

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   %ebp2. ebp记录当前函数栈的栈底位置mov    %esp,%ebp3. 申请栈空间sub    $0x3c,%esp4. 获取函数参数,进行数据处理
或者从调用者的栈空间获取,或者直接从寄存器(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<stdio.h>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 <func1>:
汇编指令                        汇编代码
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 <func1+0x3d>
25: 8b 45 f8                mov    -0x8(%rbp),%eax
28: 89 c6                   mov    %eax,%esi
2a: bf 00 00 00 00          mov    $0x0,%edi2b: R_X86_64_32 .rodata
2f: b8 00 00 00 00          mov    $0x0,%eax
34: e8 00 00 00 00          callq  39 <func1+0x39>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 <func1+0x25>
43: 8b 45 ec                mov    -0x14(%rbp),%eax
46: 89 c6                   mov    %eax,%esi
48: bf 00 00 00 00          mov    $0x0,%edi49: R_X86_64_32 .rodata+0xc
4d: b8 00 00 00 00          mov    $0x0,%eax
52: e8 00 00 00 00          callq  57 <func1+0x57>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,%edi5d: R_X86_64_32 .rodata+0x10
61: b8 00 00 00 00          mov    $0x0,%eax
66: e8 00 00 00 00          callq  6b <func1+0x6b>67: R_X86_64_PC32  printf-0x4
6b: 90                      nop
6c: c9                      leaveq
6d: c3                      retq   000000000000006e <main>:
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 <main+0x15>7f: R_X86_64_PC32   .data
83: 8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 89 <main+0x1b>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 <main+0x2e>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 <stdio.h>
#include <stdlib.h>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 <callee>:
汇编指令                        汇编代码
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 <caller>:汇编指令                 汇编代码
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 <caller+0x17>    //调用 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,%edi3d: R_X86_64_32 .rodata
41:   b8 00 00 00 00          mov    $0x0,%eax
46:   e8 00 00 00 00          callq  4b <caller+0x2e> // 调用 printf 打印47: R_X86_64_PC32       printf-0x4
4b:   c9                      leaveq
4c:   c3                      retq   000000000000004d <main>:汇编指令              汇编代码
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 <main+0x19>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 <XXXL_CTX_set_info_callback+77>
eflags         0x13206  [ PF IF #12 #13 RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
---Type <return> to continue, or q <return> 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 <+0>:     nopw   0x0(%rax,%rax,1)
0x00007f8ebfee4126 <+6>:     test   %rdi,%rdi
0x00007f8ebfee4129 <+9>:     je     0x7f8ebfee4198 <XXXL_CTX_set_info_callback+120>
0x00007f8ebfee412b <+11>:    cmpq   $0x0,(%rdi)
0x00007f8ebfee412f <+15>:    je     0x7f8ebfee4198 <XXXL_CTX_set_info_callback+120>
0x00007f8ebfee4131 <+17>:    push   %r13
0x00007f8ebfee4133 <+19>:    push   %r12
0x00007f8ebfee4135 <+21>:    mov    %rsi,%r12
0x00007f8ebfee4138 <+24>:    push   %rbp
0x00007f8ebfee4139 <+25>:    mov    %rdi,%rbp
0x00007f8ebfee413c <+28>:    push   %rbx
0x00007f8ebfee413d <+29>:    sub    $0x8,%rsp
0x00007f8ebfee4141 <+33>:    mov    0x205e78(%rip),%rax        # 0x7f8ec00e9fc0
0x00007f8ebfee4148 <+40>:    mov    (%rax),%ebx
0x00007f8ebfee414a <+42>:    callq  0x7f8ebfee17d0 <rcu_read_lock_memb@plt>
0x00007f8ebfee414f <+47>:    test   %ebx,%ebx
0x00007f8ebfee4151 <+49>:    je     0x7f8ebfee4186 <XXXL_CTX_set_info_callback+102>
0x00007f8ebfee4153 <+51>:    lea    -0x1(%rbx),%eax
---Type <return> to continue, or q <return> to quit---
0x00007f8ebfee4156 <+54>:    xor    %ebx,%ebx
0x00007f8ebfee4158 <+56>:    lea    0x8(,%rax,8),%r13
0x00007f8ebfee4160 <+64>:    mov    0x0(%rbp),%rax
0x00007f8ebfee4164 <+68>:    mov    (%rax,%rbx,1),%rax --- 相当于 rax = 2rax
0x00007f8ebfee4168 <+72>:    test   %rax,%rax
0x00007f8ebfee416b <+75>:    je     0x7f8ebfee417d <XXXL_CTX_set_info_callback+93>
=> 0x00007f8ebfee416d <+77>:    mov    (%rax),%rdi   //死在这一行 应该是 %rax 寄存器出了问题
0x00007f8ebfee4170 <+80>:    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

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

  1. 寄存器(3)KDB入门+MIPS汇编及汇编代码详解

    KDB入门和MIPS汇编 1. KDB 介绍及进入退出命令 1.1 KDB 介绍 1.2 进入KDB及退出KDB 2. KDB 调试 2.1 断点类 2.2 内存操作类 md 2.3 堆栈跟踪类 2. ...

  2. 【操作系统】Linux Kernel中memcpy的汇编实现 详解(包括必要基础概念等)

    memcpy汇编实现 由于这篇博客是从我的各种笔记上搬的 我不知道自己为什么看了mmcpy汇编实现,也许单纯就是因为好玩 在arch/x86/boot/Copy.S中,由Linus在1992年写的一段 ...

  3. Java web 开发的概念、环境配置、创建项目过程详解(Eclipse)

    Java Web 开发 Java Web 开发概念 搭建过程 详解 在eclipse创建Dynamic Web Project 创建时选择Tomcat的版本 创建项目成功 eclipse环境下如何配置 ...

  4. 计算机网络中的语法 语义 时序的概念,网络iso协议及语义语法时序详解

    网络iso协议及语义语法时序详解 计算机学习 网络协议的三要素 在计算机网路中,通信发生在不同系统的实体之间,,实体(entity)是能够发送和接收信息的任何事物.然而,两个实体间仅发送比特流就指望能 ...

  5. STM32F4X寄存器的代码详解—SDA_IN,

    资料:STM32F4XX中文参考手册-(7通用IO口/7.4GPIO寄存器) 问题描述: 我们在STM32F407关于IIC通讯实验例程中发现了一串看不懂的代码,代码所在文价夹是myiic.h ,代码 ...

  6. 数据库概念、分类(按存储方式)详解

    数据库概念 数据库(Database)是按照数据结构来组织.存储和管理数据的建立在计算机存储设备上的仓库. 简单的说数据库就是存储数据的仓库. 数据库分类(存储方式划分) 网络数据库 网络数据库是指把 ...

  7. 顺序查找的概念及实现代码详解

    文章目录 顺序查找的概念 一般线性表的顺序查找(顺序表) 完整代码 平均查找长度 一般线性表的顺序查找(链表) 完整代码 平均查找长度 顺序查找的优缺点 关键字有序的顺序表的顺序查找 平均查找长度 顺 ...

  8. python计算思维的概念_用Python学计算思维turtle详解

    Turtle 库是 Python 语言中一个很流行的绘制图像的函数库, 想象一个小乌龟, 在一个横轴 为 x .纵轴为 y 的坐标系原点, (0,0) 位置开始,它根据一组函数指令的控制,在这个平面坐 ...

  9. class属性表种类集合,以及字段详解

    目录: java虚拟机汇总 class文件结构分析 1).class文件常量池中的常量项结构 2). 常用的属性表的集合<<== 现在位置 类加载过程 1).类加载器的原理以及实现 虚拟机 ...

最新文章

  1. R语言可视化包ggplot2移除(remove)可视化结果的图例(legend)实战
  2. SAP gateway处理multiple key的逻辑
  3. 桌面计算机打开不了怎么办,电脑桌面上的所有东西都打不开了 怎么处理
  4. 14.6.3.1 The InnoDB Buffer Pool
  5. 这个华人程序员是如何 6 个月狂赚 125 亿的?
  6. Unity AnimatorController 混合树 状态机 骨骼
  7. 小程序短视频项目———视频详情页面开发(二)
  8. GIT在WINDOWS/LINUX下载的源码,回车换行有差异
  9. ESD-PCIe 402-1 CAN卡驱动安装及测试
  10. matlab数组从小到大排序,matlab数组排序
  11. Web端实现视频通话
  12. [Java] [SurfaceView] 使用EGL
  13. Cura Engine 源码解析:Settings
  14. 如何在手机上拍摄专业证件照片
  15. 遥感图像处理:最小噪声分离变换(Minimum Noise Fraction Rotation,MNF Rotation)
  16. matlab wolfe准则,[原创]用“人话”解释不精确线搜索中的Armijo-Goldstein准则及Wolfe-Powell准则...
  17. 动态链接库DLL创建及导出函数、调用DLL
  18. Android PopupWindow 弹框布局要显示在某个空间下面位置
  19. html+css制作简易12306页面
  20. 【计算机毕业设计】ssm+jsp二手车交易网站

热门文章

  1. centos 7 显示远程窗口到本地
  2. 如何查找并下载paper
  3. 关于OpenCV的个人小心得
  4. TFS实战培训 - 博时基金公司 (2016年8月)
  5. 数组转对象 和 对象转数组的简单处理
  6. 面试官:来考考你几道常见的MySQL题目吧
  7. 不是竞赛生学计算机专业,非计算机专业计算机设计大赛总结
  8. Java性能优化怎么做好
  9. 腾讯云GPU渲染型应用场景,腾讯云GPU实例类型,快速操作入门指南
  10. [附源码]Nodejs计算机毕业设计金牛社区疫情防控系统Express(程序+LW)