问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

反汇编黑科技:C++调用汇编程序技巧大揭秘!

创作时间:
作者:
@小白创作中心

反汇编黑科技:C++调用汇编程序技巧大揭秘!

引用
简书
12
来源
1.
https://www.jianshu.com/p/1782e14a0766
2.
https://blog.csdn.net/MyArrow/article/details/9703371
3.
https://blog.csdn.net/zoomdy/article/details/50563680
4.
https://blog.csdn.net/qq_37232329/article/details/133460128
5.
https://blog.csdn.net/weixin_42031299/article/details/117577060
6.
https://zhuanlan.zhihu.com/p/335550245
7.
https://www.cnblogs.com/iBinary/p/10959448.html
8.
https://www.cnblogs.com/iBinary/p/10959448.html#_label2
9.
https://www.cnblogs.com/iBinary/p/10959448.html#_label0
10.
https://www.cnblogs.com/kongj/p/14031770.html#%E8%AF%AD%E6%B3%95%E7%BB%93%E6%9E%84
11.
https://www.cnblogs.com/kongj/p/14031770.html
12.
https://www.cnblogs.com/-glb/p/6984560.html

反汇编技术是深入了解计算机底层运行机制的重要手段,而C++与汇编语言的结合则为开发者提供了更强大的编程能力。本文将从反汇编工具的使用、C++调用汇编的具体方法,到实际开发中的应用技巧,全方位揭秘这一"黑科技"。

01

反汇编工具objdump入门

在开始C++与汇编的混合编程之前,我们先了解一下常用的反汇编工具objdump。它可以帮助我们查看编译后的二进制文件,理解程序的底层实现。

基本用法如下:

objdump -d a.out # 简单反汇编
objdump -S a.out # 反汇编代码中混入对应的源代码
objdump -C -S a.out # C++符号名逆向解析
objdump -j .text -l -C -S a.out # 打印源文件名和行号

例如,对于以下C++代码:

class Main {
    int a;
public:
    Main() {
        a = 0;
    }
    int getA() {
        return this->a;
    }
};

使用objdump -S a.out可以得到如下输出:

08048456 <_ZN4MainC1Ev>:
class Main
{
    int a;
public:
    Main()
8048456:   55                      push   %ebp
8048457:   89 e5                   mov    %esp,%ebp
    {
        a = 0;
8048459:   8b 45 08                mov    0x8(%ebp),%eax
804845c:   c7 00 00 00 00 00       movl   $0x0,(%eax)
    }
8048462:   5d                      pop    %ebp
8048463:   c3                      ret    

08048464 <_ZN4Main4getAEv>:

    int getA()
8048464:   55                      push   %ebp
8048465:   89 e5                   mov    %esp,%ebp
    {
        return this->a;
8048467:   8b 45 08                mov    0x8(%ebp),%eax
804846a:   8b 00                   mov    (%eax),%eax
    }
804846c:   5d                      pop    %ebp
804846d:   c3                      ret    
02

GCC内联汇编基础

GCC提供了内联汇编功能,允许在C/C++代码中直接嵌入汇编指令。基本格式如下:

asm("assembly code");

或者使用__asm__关键字,以避免与C++关键字冲突:

__asm__("assembly code");

多条指令需要每行用双引号,并以\n\t结尾:

asm(
    "movl %eax, %ebx\n\t"
    "addl $1, %ebx"
);

GCC使用AT&T汇编语法,与Intel语法的主要区别包括:

  1. 操作数顺序相反:AT&T是src, dst,Intel是dst, src
  2. 寄存器前加%前缀
  3. 立即数前加$前缀
  4. 操作数大小通过后缀表示:b(字节)、w(字)、l(长字)

例如:

asm("movl $1, %eax"); // 将1移动到eax寄存器
03

C++调用汇编函数

在实际项目中,我们通常需要在C++代码中调用独立的汇编函数。以下是具体步骤:

  1. 创建汇编文件:在项目中添加一个.asm文件。

  2. 配置项目:确保汇编文件能够参与项目构建。在Visual Studio中,需要将文件属性设置为"Microsoft Macro Assembler"。

  3. 编写汇编函数:例如,实现一个简单的加法函数:

.data

.const

.code

addNumber proc
    mov rax, rcx
    add rax, rdx
    ret
addNumber endp
end
  1. C++中调用汇编函数:在C++代码中声明并调用汇编函数:
extern "C" __int64 addNumber(__int64 a, __int64 b);

int main() {
    __int64 result = addNumber(10, 20);
    std::cout << "Result: " << result << std::endl;
    return 0;
}
04

汇编调用C++函数

在某些情况下,我们还需要从汇编代码中调用C++函数。这通常用于实现Hook或其他底层操作。

  1. 导出C++函数:在C++中使用extern "C"导出函数:
extern "C" {
    void targetFunction();
}
  1. 汇编中调用C++函数:在汇编代码中使用EXTERN声明外部函数:
EXTERN targetFunction:PROC

.CODE

fakefunction proc
    ; 保存寄存器状态
    push rax
    push rbx
    ; ...
    
    call targetFunction
    
    ; 恢复寄存器状态
    pop rbx
    pop rax
    ret
fakefunction endp
end
05

内联汇编高级应用

内联汇编可以实现一些C++无法直接完成的功能,例如硬件中断控制。

以下是在ARM架构下使能和禁止IRQ中断的示例:

void enable_IRQ() {
    int tmp;
    __asm {
        MRS tmp, CPSR     // 读取当前程序状态寄存器
        BIC tmp, tmp, #80 // 清除IRQ位
        MSR CPSR_c, tmp   // 更新程序状态寄存器
    }
}

void disable_IRQ() {
    int tmp;
    __asm {
        MRS tmp, CPSR     // 读取当前程序状态寄存器
        ORR tmp, tmp, #80 // 设置IRQ位
        MSR CPSR_c, tmp   // 更新程序状态寄存器
    }
}
06

混合编程注意事项

  1. 寄存器使用:小心使用物理寄存器,如R0~R3、IP(R12)、LR(R14)和CPSR中的标志位。计算汇编代码中的C表达式时,可能会修改这些寄存器和标志位。

  2. 变量访问:在内嵌汇编程序中允许使用C变量。用C变量来代替寄存器可以避免冲突。例如:

int var;
__asm {
    MOV var, x      // 把x的值给var
    ADD y, var, x/y // 计算x/y时不会修改R0
}
  1. 寄存器保存:编译器会自动保存和恢复内嵌汇编中用到的寄存器,用户不需要手动处理。但CPSR和SPSR寄存器需要特别注意。
07

总结与展望

C++与汇编的混合编程在系统级开发、性能优化、硬件控制等领域具有重要价值。通过掌握反汇编工具的使用和C++调用汇编的技术,开发者能够更好地理解程序运行机制,实现更高效的代码。

未来,随着硬件技术的发展,这种混合编程模式将在更多场景下发挥作用,特别是在嵌入式系统、实时系统和高性能计算领域。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号