这台机器代码在C中会怎么样?

时间:2014-06-11 03:50:23

标签: c assembly

我有这个机器代码,我过去4天一直在努力,但我似乎无法掌握它。

    pushl %ebp
    movl %esp, %ebp
    jmp .L3
L4:
    addl $3,8(%ebp)

L3:
    movl 8(%ebp),%eax // having issues here
    movzbl (%eax),%eax//here
    cmpb $1,%al// and here
    je .L5
    cmpl 12(%ebp),%eax
    jne .L4
    movl $8,%eax
.L5: leave
     ret

以下是我对解决方案的尝试:

int main(int s, char *t){
    while (s != 1) {
        if (s == *t){
            s = 8;
        }
        else{s+=3;}
    }
    return;
}

有人能告诉我,我是否正确接近这个?如果没有帮助我指向正确的方向?

3 个答案:

答案 0 :(得分:5)

该函数看起来是__cdecl,因为它引用了8(%ebp)12(%ebp)而没有初始化,这表明它们是参数。分别称他们为arg1arg2

我们可以注释程序集:

    /* Function prologue */
    pushl %ebp
    movl %esp, %ebp

    jmp .L3
L4:
    /* Move to next loop iteration */
    addl $3, arg1

L3:
    /* Copy value of arg1 to %eax */
    movl arg1, %eax
    /* (%eax) means to dereference %eax (as a memory address).
       movzbl means to load a single byte and zero-extend to the rest of the register.
       Therefore, the byte at address %eax is put into %eax. */
    movzbl (%eax), %eax
    /* Compare the low byte of %eax against 1 */
    cmpb $1, %al
    /* If equal, exit (%eax = 1) */
    je .L5
    /* Compare %eax against arg2 */
    cmpl arg2, %eax
    /* If not equal, keep looping */
    jne .L4

    /* Otherwise, if it was equal, we quit and return %eax = 8 */
    movl $8,%eax
.L5: leave
     ret

在C代码中,这变为

int fn(unsigned char *ptr, int sentinel) {
    while(1) {
        unsigned char c = *ptr;
        if(c == 1) return c;
        if(c == sentinel) return 8;
        ptr += 3;
    }
}

答案 1 :(得分:3)

以下是反汇编的注释版本:

    pushl %ebp        // save frame pointer
    movl %esp, %ebp   // setup new stack frame

    // The stack frame looks like this:
    // 0(%ebp) : previous frame pointer
    // 4(%ebp) : return address
    // 8(%ebp) : unsigned char *arg1
    // 12(%ebp) : int arg2

    jmp .L3                // jump to loop body
L4:
    addl $3,8(%ebp)        // arg1 += 3

L3:
    movl 8(%ebp),%eax      // %eax = arg1
    movzbl (%eax),%eax     // %eax = *arg1 (zero-extend from byte to dword)
    cmpb $1,%al            // *arg1 == 1?

    je .L5

    // *arg1 != 1
    cmpl 12(%ebp),%eax     // arg2 == *arg1?

    jne .L4

    // *arg1 == arg2
    movl $8,%eax           // result = 8

.L5: leave
     ret

由此,我们可以尝试编写等效的C代码:

int f(unsigned char *p, int v)
{
    unsigned char b;

    for(; (b = *p) != 1; p += 3) {
        if(b == v)
            return 8;
    }

    return b;
}

答案 2 :(得分:1)

更像这样,假设CDECL呼叫标准。

int fn(int s, int t){
    for(;*(char*)s != 1 && s != t;s += 3);
    if(s == t)
        return 8;
    else
        return s;
}

这是对你说过你没有得到的那些的解释。

movl 8(%ebp),%eax // Load s from stack into register eax.
movzbl (%eax),%eax // Load a byte from the address in eax (s) and set the higher 3 bytes of eax to 0.
cmpb $1,%al // Compare that byte loaded to 1.