c - 需要帮助将 64 位 Intel 汇编指令解密为 C

标签 c assembly x86-64 reverse-engineering

我有一个功能:

long foo(long x, long y, long z);

我得到了 GCC 的汇编输出,我试图弄清楚是什么 将其转换为 C 函数。

我是 assembly 新手,根本不知道这里发生了什么。

富:

subq   %rdx %rsi
imulq  %rsi %rdi 
movq   %rsi %rax 
salq   $63  %rax
sarq   $63  %rax
xorq   %rdi %rax 

x,y,z 分别传入寄存器 %rdi, %rsi, & %rdx

最佳答案

您需要了解符合 SystemV ABI 的系统(例如 POSIX/linux)的 x86_64 调用约定,才能将给定寄存器映射到函数原型(prototype)中的参数。尽管这是作为先决条件给出的,但查阅更详细地解释这一点的引用文献会很有帮助:http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64

<小时/>

此外,由于代码使用 %rdi,我们知道:

  1. 不是 Windows,因为 Windows ABI 不使用 rdi 作为其任何“传入寄存器”参数
  2. 我们知道我们正在使用“AT&T 语法”[因为 % 前缀],而不是“Intel 语法”...
  3. ...所以目标寄存器是指令的最右边

所有指令上的“q”后缀表示“四字”(即 64 位)。在 Windows 下,long 是 32 位[看图:-)],因此,这绝对是 SysV,因为在 Windows 下,第一条指令将是 32 位指令,使用 32 位寄存器名称[ 实际的寄存器会有所不同]:

    subl    %edx %esi
<小时/>

大多数 asm 指令应该很直观。

请注意,由于 long,这些操作适用于有符号整数。

结合所有这些,这是一个示例程序:

// x86_64 calling convention:
//   arg 0: %rdi
//   arg 1: %rsi
//   arg 2: %rdx
//   arg 3: %rdx
//   arg 4: %r8
//   arg 5: %r9

long
foo(long x,long y,long z)
// x -- %rdi
// y -- %rsi
// z -- %rdx
{
    long ret;

    // subq   %rdx %rsi
    y -= z;

    // imulq  %rsi %rdi
    x *= y;

    // movq   %rsi %rax
    ret = x;

    // salq   $63  %rax
    ret <<= 63;

    // sarq   $63  %rax
    ret >>= 63;

    // xorq   %rdi %rax
    ret ^= x;

    return ret;
}
<小时/>

[以 movq 开头]这两个移位操作是一个小“技巧”​​。

第一个 salq 将位 0 ​​左移到位 63,即符号位。 sarq 是一个算术右移,它移入左侧的符号位。最终效果是所有位都将设置为符号位。

所以,这相当于:

xor_mask = (x & 1) ? -1 : 0;

关于c - 需要帮助将 64 位 Intel 汇编指令解密为 C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40028534/

相关文章:

c - 使用内联汇编时出现段错误(核心转储)错误

linux - 为什么 'syscall' 指令在 Linux 下不起作用?

c - 如何在C中使用递归函数打印从1到N的数字

c - 使用 "jmp *%esp"时操作数类型不匹配

assembly - 这个堆栈检查 PPC 程序集在做什么?

Python程序变成标准程序集?

gcc - amd64 中的传递参数如何?

c - C 中的冒泡排序错误代码! [Deitel C 第 6 版]

c - 如何使用空环境获取终端类型

我可以获得 DOS 6.22 操作系统的 IP 地址吗?