代码之家  ›  专栏  ›  技术社区  ›  CCSab

了解程序集

  •  3
  • CCSab  · 技术社区  · 14 年前

    我有一些排序算法的汇编,我想弄清楚它到底是如何工作的。

    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指令之类的操作数有些困惑。谢谢。

    3 回复  |  直到 14 年前
        1
  •  2
  •   nithins    14 年前
    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的值(基本上是数组[1]和数组[0])。如果RDX小于或等于RAX,那么这将直接将程序执行跳转到第400a33行。您可以将其视为(array[1]>array[0])。所以它继续比较这些值。

    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];
        }
    }
    
        2
  •  4
  •   NullUserException Mark Roddy    14 年前

    mov : move
    cmp : compare
    jle : jump if less or equal (branch)
    ret : return from procedure
    nop : no-op
    

    %r** 是寄存器。它们通常是 %e** %eax , %edx ,…),但这些是64位寄存器。

    看这个: http://www.x86-64.org/documentation/assembly

        3
  •  4
  •   Potatoswatter    14 年前

    它有助于用专有名称替换寄存器名称以跟踪数据流,并为控制流添加分支标签。

    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