Sorting 理解装配
我有一些排序算法的汇编,我想弄清楚它到底是如何工作的 我对一些说明有点困惑,特别是cmp和jle说明,所以我正在寻求帮助。此程序集对由三个元素组成的数组进行排序Sorting 理解装配,sorting,assembly,Sorting,Assembly,我有一些排序算法的汇编,我想弄清楚它到底是如何工作的 我对一些说明有点困惑,特别是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:
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
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
0.00:400a08:48 39 c8 cmp%rcx,%rax
0.00:400a0b:7e 1a jle 400a27
0.00:400a0d:48 39 ca cmp%rcx%rdx
0.00:400a10:7e 0c jle 400a1e
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
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
0.00:400a38:48 39 c8 cmp%rcx,%rax
0.00:400a3b:7e 0c jle 400a49
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:48895710MOV%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无
如果有人能带我走过,那会很有帮助的。我对0x8(%rdi)等操作数以及cmp和jle指令感到有些困惑。谢谢 以下是说明的含义:
mov : move
cmp : compare
jle : jump if less or equal (branch)
ret : return from procedure
nop : no-op
%r**
是寄存器。它们通常是%e**
(例如:%eax
,%edx
,…),但它们是64位寄存器
至于反编译整件事,那将需要更多的工作
请参见:用专有名称替换寄存器名称有助于跟踪数据流,并为控制流添加分支标签
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
寄存器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>
你现在正在读哪本书?我很早(6502年)就养成了一种习惯,认为cmp是一种放弃结果的减法。IIRC(这要追溯到很久以前)x86上的jle有点模棱两可-有两条指令执行听起来相同的操作,但一条对有符号值正确,另一条对无符号值正确。我不记得是哪个jle了。当然,我已经完全过时了——这只是我想说的,IMO扩展首字母缩略词并不足以解释太多。当然,这个链接确实解决了这个问题。通常,LT/GT/LE/GE是有符号的,而HI/LO/HS/LS是无符号的。还有溢出设置/清除(我忘了是O、V还是X)和进位设置/清除(CC/CS)。我已经为ARM指定了它们,但我怀疑x86与之类似;据我所知,唯一显著不同的(现代两位的补码)处理器是PPC,其中有符号/无符号/浮点比较,因为IEEE浮点比较不容易映射到CVNZ(进位、溢出、负、零)状态位。一些反汇编程序可以为您做这些事情,至少是半自动的。以前有一个免费版本的IDA Pro,它几乎是你能在Windows上获得的最好版本。可悲的是,即使你仍然可以得到它,它也只能支持32位,我想,而且全价版本可能并不便宜。也许值得尝试一下这个演示,或者寻找一个具有类似功能的反汇编程序。答案是错误的。这是AT&T语法,源操作数和目标操作数与此处的intel语法相反。例如:上面这一行将RAX寄存器的内容复制到数组的第一个元素中,这与发生的情况相反。
0.00 : 400a03: 48 39 d0 cmp %rdx,%rax
0.00 : 400a06: 7e 2b jle 400a33 <b+0x3b>
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];
}
}