在c代码中编写汇编语言需要帮助

时间:2014-05-11 21:18:47

标签: c assembly

我正致力于将汇编语言转换为C程序。据我所知,在下面的函数中,有一个参数设置为0,并将其与某些东西进行比较(我不确定这是为什么我感到困惑)。如果x小于或等于它被比较的任何东西,那么函数将跳转到f2,然后将0复制到局部变量,但如果不是,它将1复制到局部变量并将其复制到寄存器a中返回。我不明白在前几行中与参数进行比较的内容。有人能指出我正确的方向吗?

这是语言:

     pushl    %ebp
     movl     %esp, %ebp
     subl     $4, %esp
     cmpl     $0, 8(%ebp)
     jle . f2
     movl     $1, -4(%ebp)
     jmp. f3  
 .f2:
     movl     $0, -4(%ebp)

 .f3:
     movl     -4(%ebp), %eax
     leave
     ret

我认为这应该是在C:

中的样子
         fn(int x)
         {
            x = 0;
           if    x    <=   ?   :
                int   y  =   0;
           else
                int y  = 1;
          }
          return y;

先谢谢你了

2 个答案:

答案 0 :(得分:2)

(首先,抱歉,但我会转换为英特尔语法,我真的不能把我的想法包围在AT&amp; T)

    push ebp
    mov ebp,esp
    sub esp,4

这是通常的功能序幕;保存基指针,将堆栈指针设置为基指针,在堆栈上为一个局部变量创建空间(以后称为[ebp-4]);我们称这个变量为int ret

    cmp dword ptr[ebp + 8], 0

ebp+8的值与0进行比较,并相应地设置标志寄存器,以便以后任何条件跳转指令都可以根据比较结果进行操作。 ebp+8处的位置可能是32位函数参数(ebp+4通常是函数的返回值);我们称这个参数为int x

    jle .f2
    mov dword ptr[ebp-4], 1
    jmp .f3  
.f2:
    mov dword ptr[ebp-4], 0
.f3:

这是相当简单的;如果在最后一次比较中第一个操作数(AT&amp; T语法情况下的第二个操作数)小于或等于第二个操作数,则跳转到标签.f2,否则直行(并且在mov之后,跳转到.f3)。

最终结果是:x<=0ret=0,否则为ret=0

    mov eax,dword ptr[ebp-4]

这将ret移动到eax,这是许多调用约定中返回值的位置。

    leave
    ret

这是标准功能结尾;它将ebpesp修复为上一个状态,然后ret返回给调用者。

所以,整个事情归结为:

int f(int x)
{
    int ret;
    if(x<=0)
        ret=0;
    else
        ret=1;
    return ret;
}

或者,更简洁:

int f(int x)
{
    return x>0;
}

顺便说一句,总而言之这看起来就像禁用了优化的gcc的输出:编译我用-m32 -c -S写的第一个函数我得到了:

.LFE0:
    .size   g, .-g
    .globl  f
    .type   f, @function
f:
.LFB1:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $16, %esp
    cmpl    $0, 8(%ebp)
    jg  .L4
    movl    $0, -4(%ebp)
    jmp .L5
.L4:
    movl    $1, -4(%ebp)
.L5:
    movl    -4(%ebp), %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret

,删除cfi-directives之后,就是你发布的内容。

(添加-O3,它肯定更聪明:

movl    4(%esp), %edx
xorl    %eax, %eax
testl   %edx, %edx
setg    %al
ret

答案 1 :(得分:0)

在您使用的汇编语言语法中,$0表示实际值为零。所以说明

 cmpl     $0, 8(%ebp)

将内存位置8(%ebp)中的值与零值进行比较。您已在示例代码中用x表示此值,但它不需要是变量。

8(%ebp)部分代表内存访问。要了解这是什么,请考虑对此函数的调用可能如下:

 pushl    $5
 call     fn

这会将值5推入堆栈,然后调用您的函数。然后call指令将返回地址压入堆栈。因此,在调用此函数时,堆栈上有两个单词。函数中的第一条指令将另一个单词(%ebp的前一个值)推入堆栈,因此我们有:

 +----------------+
 | 5              |
 +----------------+
 | return address |
 +----------------+
 | old %ebp       |
 +----------------+ <- %ebp

%ebp的新值指向此底部。偏移量为8的值(此处为32位字)为5,即函数的参数。因此,在C中启动函数可能需要看起来更像:

int fn(int x)
{
    if (x <= 0) ...