1

次の単純な C コードを翻訳する必要があります。

int add(int a, int b);

int main()
{
    int a,b;
    a = 0;
    while(a<5)
    {
        a++;
        printi(a);
        prints("\n");
    }
    return 0;
}

int add(int a, int b)
{
    char cx = 'a';
    int x = a-b;
    return x;
}

そして、それを次の GNU x86 アセンブリ コードに変換するコンパイラを作成しました。(printi と prints は、翻訳後にリンクするライブラリ関数です)。

.section    .rodata
.LC0:
    .string "\n"
    .text
    .globl  main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    movl    $0, -4(%ebp)
    movl    -4(%ebp), %eax
    movl    %eax, -12(%ebp)
.L0:
    movl    $5, %eax
    movl    -4(%ebp), %edx
    cmpl    %edx, %eax
    jge .CH1
.CH0:
    movl    $1, -16(%ebp)
    jmp .CH2
.CH1:
    movl    $0, -16(%ebp)
.CH2:
    movl    $0, %eax
    cmpl    -16(%ebp), %eax
    je  .L2
    jmp .L1
.L1:
    movl    -4(%ebp), %eax
    movl    %eax, -20(%ebp)
    movl    -20(%ebp), %eax
    movl    $1, %edx
    addl    %edx, %eax
    movl    %eax, -4(%ebp)
    movl    -4(%ebp), %eax
    movl    %eax, (%esp)
    call    printi
    movl    %eax, -24(%ebp)
    movl    $.LC0, (%esp)
    call    prints
    movl    %eax, -28(%ebp)
    jmp .L0
.L2:
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .globl  add
    .type   add, @function
add:
    pushl   %ebp
    movl    %esp, %ebp
    movb    $97, -1(%ebp)
    movl    4(%ebp), %eax
    movl    8(%ebp), %edx
    subl    %edx, %eax
    movl    %eax, -9(%ebp)
    movl    -9(%ebp), %eax
    movl    %eax, -5(%ebp)
    movl    -5(%ebp), %eax
    leave
    ret
    .size   add, .-add

ただし、プログラムは何も出力しません。whileのチェック式のあたりでどこか間違えたようです。

命令cmpl %edx, %eaxは、フラグを 0 ~ 5、つまり -5 に設定する必要があります。したがって、jge はそれを .CH1 に分岐しません。したがって-16(%ebp)、1 として設定する必要があり、.CH2 に入る必要があります。1!=0 として、L1 に入る必要があります。どこが間違っているのかわかりません。

4

1 に答える 1

1

命令cmpl %edx, %eaxは、フラグを 0 ~ 5、つまり -5 に設定する必要があります。j

いいえ。AT&T 構文では、オペランドの順序はsource, destinationです。eax = 5とがedx = 0あるのでcmpl %edx, %eax、5-0 に基づいてフラグを設定します。その後、jge ジャンプします。

于 2014-11-09T12:13:57.953 に答える