我有一个功能:
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
,我们知道:
- 这不是 Windows,因为 Windows ABI 不使用
rdi
作为其任何“传入寄存器”参数 - 我们知道我们正在使用“AT&T 语法”[因为
%
前缀],而不是“Intel 语法”... - ...所以目标寄存器是指令的最右边。
所有指令上的“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/