-6

I am working on converting assembly language to a C program. I understand that in the function below that there is one parameter set to equal 0 and it is compared to something (which I am unsure of what which is why I'm confused). if x is less than or equal to whatever it's being compared to, then the function will jump to f2 which will then copy 0 into a local variable but if not it will copy 1 into a local variable and copy that into register a which is returned. I don't understand what the parameter is being compared to in the first few lines. Can anyone point me in the right direction?

here is the language:

     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

This is what I think it should look like in C:

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

Thank You in advanced

user2101463
  • 343
  • 1
  • 4
  • 14
  • 3
    In order to answer this question you will need both: (1) to be able to understand the above assembly code, and (2) to be familiar with C syntax and have written at least a few simple C programs. If you cannot do both of those things, you have no hope of learning anything from asking other people to solve this for you. – Greg Hewgill May 11 '14 at 21:22
  • @Greg -- ironic, then, that a casual td;lr reading of this code only lead to a somewhat disappointed "is that all?". I guess I passed your (1)+(2) test ;-) – Jongware May 11 '14 at 21:26
  • I am familiar with C and assembly language, Let me make myself clear then. I see that there is one parameter set to equal 0 and it is compared to something which I am unsure of what which is why I'm confused. if x is less than or equal to whatever it's being compared to, then the function will jump to f2 which will then copy 0 into a local variable but if not it will copy 1 into a local variable and copy that into register a which is returned?? – user2101463 May 11 '14 at 21:27
  • Well, it sounds like you have actually understood most of the function. Your question wasn't so detailed, as *"confused as to what's going on"* does not inspire confidence. Perhaps you could edit your question to ask about *specific* instructions. Show that you actually do know most of what's going on. – Greg Hewgill May 11 '14 at 21:29

2 Answers2

2

(first of all, sorry but I'll translate to Intel syntax, I really can't wrap my mind around AT&T)

    push ebp
    mov ebp,esp
    sub esp,4

This is the usual function prologue; save the base pointer, set the stack pointer to the base pointer, make space on the stack for one local variable (later referred to as [ebp-4]); let's call this variable int ret.

    cmp dword ptr[ebp + 8], 0

Compares the value at ebp+8 with 0, and sets the flags register accordingly, so that later any conditional jump instruction can act basing on the result of the comparison. The location at ebp+8 is probably a 32-bit function parameter (ebp+4 being normally the return value of the function); let's call this parameter int x.

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

This is fairly straightforward; if in the last comparison the first operand (second operand in case of AT&T syntax) resulted less or equal than the second operand, jump to label .f2, otherwise go straight (and, after the mov, jump to .f3).

The net result is that, if x<=0, ret=0, otherwise ret=0.

    mov eax,dword ptr[ebp-4]

This moves ret to eax, which is the position where the return value is left in many calling conventions.

    leave
    ret

This is the standard function epilogue; it fixes up ebp and esp to the previous state, then ret returns to the caller.

So, the whole thing boils down to something like:

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

or, more succinctly:

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

By the way, all in all this looks like the output of gcc with optimizations disabled: compiling the first function I wrote with -m32 -c -S I get:

.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

which, after removing the cfi-directives and the like, is exactly what you posted.

(adding -O3, it gets definitely smarter:

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

)

Community
  • 1
  • 1
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
0

In the assembly language syntax you are using, $0 means the actual value zero. So the instruction

 cmpl     $0, 8(%ebp)

is comparing the value in memory location 8(%ebp) to the value zero. You have represented this value by x in your example code, but it doesn't need to be a variable.

The 8(%ebp) part represents a memory access. To understand what this is, consider what a call to this function might look like:

 pushl    $5
 call     fn

This is pushing the value 5 onto the stack and then calling your function. The call instruction then pushes the return address onto the stack. So there are two words on the stack by the time this function is called. The first instruction in the function pushes another word (the previous value of %ebp) onto the stack, so we have:

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

The new value of %ebp points to the bottom of this as indicated. The value at offset 8 from this (32-bit words here) is 5, the parameter to the function. So, the start of your function in C probably needs to look more like:

int fn(int x)
{
    if (x <= 0) ...
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285