我有一些排序算法的组装,我想知道它的确切功能。
我对一些说明有点困惑,特别是cmp和jle指令,所以我正在寻求帮助。该程序集对三个元素的数组进行排序。
0.00 : 4009f8: 48 8b 07 mov (%rdi),%rax
0.00 : 4009fb: 48 8b 57 08 mov 0x8(%rdi),%rdx
0.00 : 4009ff: 48 8b 4f 10 mov 0x10(%rdi),%rcx
0.00 : 400a03: 48 39 d0 cmp %rdx,%rax
0.00 : 400a06: 7e 2b jle 400a33 <b+0x3b>
0.00 : 400a08: 48 39 c8 cmp %rcx,%rax
0.00 : 400a0b: 7e 1a jle 400a27 <b+0x2f>
0.00 : 400a0d: 48 39 ca cmp %rcx,%rdx
0.00 : 400a10: 7e 0c jle 400a1e <b+0x26>
0.00 : 400a12: 48 89 0f mov %rcx,(%rdi)
0.00 : 400a15: 48 89 57 08 mov %rdx,0x8(%rdi)
0.00 : 400a19: 48 89 47 10 mov %rax,0x10(%rdi)
0.00 : 400a1d: c3 retq
0.00 : 400a1e: 48 89 17 mov %rdx,(%rdi)
0.00 : 400a21: 48 89 4f 08 mov %rcx,0x8(%rdi)
0.00 : 400a25: eb f2 jmp 400a19 <b+0x21>
0.00 : 400a27: 48 89 17 mov %rdx,(%rdi)
0.00 : 400a2a: 48 89 47 08 mov %rax,0x8(%rdi)
0.00 : 400a2e: 48 89 4f 10 mov %rcx,0x10(%rdi)
0.00 : 400a32: c3 retq
0.00 : 400a33: 48 39 ca cmp %rcx,%rdx
0.00 : 400a36: 7e 1d jle 400a55 <b+0x5d>
0.00 : 400a38: 48 39 c8 cmp %rcx,%rax
0.00 : 400a3b: 7e 0c jle 400a49 <b+0x51>
0.00 : 400a3d: 48 89 0f mov %rcx,(%rdi)
0.00 : 400a40: 48 89 47 08 mov %rax,0x8(%rdi)
0.00 : 400a44: 48 89 57 10 mov %rdx,0x10(%rdi)
0.00 : 400a48: c3 retq
0.00 : 400a49: 48 89 07 mov %rax,(%rdi)
0.00 : 400a4c: 48 89 4f 08 mov %rcx,0x8(%rdi)
0.00 : 400a50: 48 89 57 10 mov %rdx,0x10(%rdi)
0.00 : 400a54: c3 retq
0.00 : 400a55: 48 89 07 mov %rax,(%rdi)
0.00 : 400a58: 48 89 57 08 mov %rdx,0x8(%rdi)
0.00 : 400a5c: 48 89 4f 10 mov %rcx,0x10(%rdi)
0.00 : 400a60: c3 retq
0.00 : 400a61: 90 nop
如果有人可以引导我完成它,那将非常有帮助。我有点混淆操作数,如0x8(%rdi)和cmp和jle指令。谢谢。
答案 0 :(得分:4)
以下是说明的含义:
mov : move
cmp : compare
jle : jump if less or equal (branch)
ret : return from procedure
nop : no-op
%r**
是寄存器。它们通常是%e**
(例如:%eax
,%edx
,...),但这些是64位寄存器。
对于整个事情的反编译,这将需要更多的工作。
答案 1 :(得分:4)
有助于用适当的名称替换寄存器名称以跟踪数据流,并为控制流添加分支标签。
0.00 : 4009f8: 48 8b 07 mov (%argptr),%var1
0.00 : 4009fb: 48 8b 57 08 mov 0x8(%argptr),%var2
0.00 : 4009ff: 48 8b 4f 10 mov 0x10(%argptr),%var3
0.00 : 400a03: 48 39 d0 cmp %var2,%var1
0.00 : 400a06: 7e 2b jle @v2le1
0.00 : 400a08: 48 39 c8 cmp %var3,%var1
0.00 : 400a0b: 7e 1a jle @v3le1
0.00 : 400a0d: 48 39 ca cmp %var3,%var2
0.00 : 400a10: 7e 0c jle @v3le2
# Now we know that 2 > 1 and 3 > 1 and 3 > 2. Write them to memory in order.
etc
答案 2 :(得分:2)
0.00 : 4009f8: 48 8b 07 mov (%rdi),%rax
寄存器RDI包含阵列内存中某个位置的地址。上面的这一行将RAX寄存器的内容复制到数组的第一个元素中。由于x64中的指针是0x8字节,因此以下两行:
0.00 : 4009fb: 48 8b 57 08 mov 0x8(%rdi),%rdx
0.00 : 4009ff: 48 8b 4f 10 mov 0x10(%rdi),%rcx
将RDX和RCX寄存器的内容分别复制到数组的第二个和第三个元素中。现在我们需要开始比较这些值以查看我们需要交换的位置。
0.00 : 400a03: 48 39 d0 cmp %rdx,%rax
0.00 : 400a06: 7e 2b jle 400a33 <b+0x3b>
cmp将比较RDX的值与RAX的值(对阵列[0]基本上是数组[1])。如果RDX小于或等于RAX,那么这将直接将程序执行跳转到行400a33。您可以将其视为(array [1]&gt; array [0])。所以它继续,比较价值。
似乎代码正在尝试按降序排序。非常粗略地说,C代码可能看起来像这样:
array[0] = rax;
array[1] = rdx;
array[2] = rcx;
if (rdx > rax)
{
if (rcx > rax)
{
if (rcx > rdx)
{
rcx = array[0];
rdx = array[1];
LABEL:
rax = array[2];
}
else
{
rdx = array[0];
rcx = array[1];
GOTO LABEL;
}
}
else
{
rdx = array[0];
rax = array[1];
rcx = array[2];
}
}
else
{
if (rcx > rdx)
{
if (rcx > rax)
{
rcx = array[0];
rax = array[1];
rdx = array[2];
}
else
{
rax = array[0];
rdx = array[1];
rcx = array[2];
}
}
else
{
rax = array[0];
rdx = array[1];
rcx = array[2];
}
}