网络知识 娱乐 深入理解计算机系统作业(AT&T汇编转C)1 循环

深入理解计算机系统作业(AT&T汇编转C)1 循环

目录

一:知识回顾

1.条件码

2.算术操作

3. cmove 指令

4.jmp指令

二. 作业解析 && AC 代码 (直奔主题请点这)

1.switch语句的翻译

2.循环结构的翻译4(循环的嵌套)

3.循环结构的翻译3(for)

4.循环结构的翻译2(do...while)

5.循环结构的翻译1(while)

6.选择结构的翻译3

7.选择结构的翻译2

8.选择结构的翻译1


做完的时候整理题目目录才发现这出题顺序不是很友好..

温馨提示:作业中的 jump 尽量不要翻译成 C 中的 goto ,可以先考虑goto的结构然后把它转化为没有 goto 的形式(你反汇编的过程就应该大概知道为什么大家都不建议使用 goto 了,因为它让程序的控制流难以追踪,别人很难理解你写了个啥),当然,你如果觉得你的代码不需要别人懂,那就尽情的使用 goto 吧!

由于作者较懒,代码大部分为直译形式,所以都没有精简过

一:知识回顾

写作业前先回顾一些知识:

其实这个知识回顾是我自己忘记了条件码是啥,然后第二题就要用到条件码的概念,所以这里的知识回顾基本就代表我本人并没有记全指令集,但是既然做了就做稍微全点


1.条件码

注意条件码是来源于最近的一次操作

常见的条件码:

CF:进位标志

当我们最近的操作数的最高有效位发生改变的时候,CF = 1,其他情况CF = 0

IF:零标志

最近一次操作计算结果出现0 ,IF = 1,否则 IF = 0

SF:符号标志

最近一次操作得到的结果为负数 SF= 1,否则SF = 0

OF:溢出标志

最近一次操作出现溢出——正溢出或负溢出 OF = 1,否则 OF = 0

举个CF的例子:

例:

movl $1 %rax // x = 1 此时CF = 0

subl $2 %rax // x = 1 -  2 = -1 此操作后CF = 1 因为最高有效位发生了变化


2.算术操作

用法什么的就不做赘述了,书上都有.


3. cmove 指令


4.jmp指令


二. 作业解析 && AC 代码

反汇编和英译汉一样,熟悉各个指令的意思就能比较轻松的反汇编了。


1.switch语句的翻译

题目描述

下面的汇编代码是某个函数编译后生成的:

    movl $-1, %eax

    cmpl $80, %edi

    ja .L3

    leal 7(%rdi), %eax

    testl %edi, %edi

    cmovs %eax, %edi

    sarl $3, %edi

    subl $6, %edi

    movl $1, %eax

    cmpl $4, %edi

    ja .L3

    mov %edi, %edi

    movl CSWTCH.15(,%rdi,4), %eax

.L3:

    rep

    ret

在编译器输出的.s文件中还有下面的和该函数汇编指令有关的部分:

CSWTCH.15:

.long 2

.long 3

.long 4

.long 5

.long 5

main函数已经写好了,请根据上述汇编代码设计一个等价的C函数:

int main(){

    int n;

    scanf("%d",&n);

    printf("%dn",func(n));

    return 0;

}

输入描述

输入整型数n

输出描述

调用函数并输出函数的返回值

提示

你需要提交完整的程序,请将上面的main函数复制到你的程序中。

 思路:和翻译英文一样,一句一句对照翻译成C就好了,忘记的指令就去回顾一下书籍,没什么好说的

做题技巧:一段一段的看,一般到转折处(判断,跳转...)的时候就停下

AC code

#include

int func(int x)
{
    int v = -1;
    if(x  80) return v;
    /*
        注意这里是ja 为无符号大于
        即无符号目的数 > 无符号操作数
    */
    v = 7 + x;
    if(x >= 3;
    x -= 6;
    v = 1;
    if(x  4)
    {
        return v;
    }
    switch(x)
    {
        case 0 :
            v = 2;
            break;
        case 1 :
            v = 3;
            break;
        case 2 :
            v = 4;
            break;
        case 3 :
            v = 5;
            break;
        case 4 :
            v = 5;
        break;
    }
    return v;
}

int main(){

    int n;

    scanf("%d",&n);

    printf("%dn",func(n));

    return 0;

}


2.循环结构的翻译4(循环的嵌套)

题目描述

下面的汇编代码是某个函数编译后生成的:

    pushq %rbx

    movl %edx, %r9d

    movl $0, %r8d

    testl %edi, %edi

    jle .L6

    movl $10, %r10d

    movl $1, %r11d

    movl $1, %ebx

    jmp .L3

.L10:

    leal (%r10,%rcx), %edx

    movl %edx, %eax

    sarl $31, %edx

    idivl %r9d

    cmpl $1, %edx

    adcl $0, %r8d

    addl $1, %ecx

    cmpl %ecx, %esi

    jge .L10

.L8:

    addl $1, %r11d

    addl $10, %r10d

    cmpl %r11d, %edi

    jl .L6

.L3:

    movl %ebx, %ecx

    testl %esi, %esi

    jg .L10

    jmp .L8

.L6:

    movl %r8d, %eax

    popq %rbx

    ret

main函数已经写好了,请根据上述汇编代码设计一个等价的C函数:

int main(){

int a,b,c;

scanf("%d%d%d",&a,&b,&c);

printf("%dn",func(a,b,c));

return 0;

}

输入描述

输入整型数a,b和c

输出描述

调用函数并输出函数的返回值

提示

你需要提交完整的程序,请将上面的main函数复制到你的程序中。

本题使用了除法指令,请将教材中关于除法指令的知识点熟悉一下

难点:(其实最难的还是怎么去写 非 goto 版本的代码)

1.adcl 指令,这条指令书上并没有给到,下面给出这条指令的含义:
adcl 指令等价于 addl 唯一不同的一点是它要加上进位标志条件码 CF ,而我们要用到的CF来源于最近的一次计算操作,并非我们执行的这条指令本身.

例:

movel $1 %rax

subl $2 %rax  //这条指令 %rax = 1 - 2 = -1 最高有效位发生变化,所以此时 CF = 1

adcl $1 %rax  // 这条指令执行后 %rax 内的值为 1

// %rax = %rax + 1 + CF = -1 + 1 + 1 = 1

2.jump的非goto翻译,本人的做法就是先把整个程序翻译成我熟悉的带 goto 的 C,然后再把它转化为非 goto 的形式.

AC code:(goto && 非 goto 形式 都是AC的代码)

goto:

#include
#define L long
int func(int a, int b, int c)
{        //%edi    %esi   %edx
    int eb, ea;
    L rc;
    L r9 = c;
    L r8 = 0;
    if(a > 0)
    {
        L r10 = 10;
        L r11 = 1;
        eb = 1;
        goto L3;//
        
        L10:

        c = r10 + rc;
        ea = c;
        c >>= 31;
        c = ea % r9;
        ea = ea / r9;
        if(c - 1 = rc) goto L10;

        L8:

        r11++;
        r10 += 10;
        if(a  0) goto L10;

        goto L8;
    }
    L6:
    ea = r8;
    return ea;
}

int main()
{

    int a,b,c;

    scanf("%d%d%d",&a,&b,&c);

    printf("%dn",func(a,b,c));

    return 0;

}

非goto:

#include
#define L long
int func(int a, int b, int c)
{        //%edi    %esi   %edx
    int eb, ea;
    L rc;
    L r9 = c;
    L r8 = 0;
    if(a > 0)
    {
        L r10 = 10;
        L r11 = 1;
        eb = 1;
        do
        {
            rc = eb;
            if(b > 0)
            {
                do
                {
                    c = r10 + rc;
                    ea = c;
                    c >>= 31;
                    c = ea % r9;
                    ea = ea / r9;
                    if(c - 1 = rc);
            }
            r11++;
            r10 += 10;

        }while(a >= r11);
    }
    ea = r8;
    return ea;
}

int main()
{

    int a,b,c;

    scanf("%d%d%d",&a,&b,&c);

    printf("%dn",func(a,b,c));

    return 0;

}

3.循环结构的翻译3(for)

题目描述

下面的汇编代码是某个函数编译后生成的:

    movl $1, %ecx

    movl $0, %r8d

    testl %edi, %edi

    jle .L3

.L7:

    movl %ecx, %edx

    movl %ecx, %eax

    sarl $31, %edx

    idivl %esi

    leal (%r8,%rcx), %eax

    testl %edx, %edx

    cmove %eax, %r8d

    addl $1, %ecx

    cmpl %ecx, %edi

    jge .L7

.L3:

    movl %r8d, %eax

    ret

main函数已经写好了,请根据上述汇编代码设计一个等价的C函数:

int main(){

    int n,m;

    scanf("%d%d",&n,&m);

    printf("%dn",func(n,m));

    return 0;

}

输入描述

输入整型数n和m

输出描述

调用函数并输出函数的返回值

提示

你需要提交完整的程序,请将上面的main函数复制到你的程序中。

本题使用了除法指令,请将教材中关于除法指令的知识点熟悉一下

难点

我的观点是,搞懂上一题这题就不难了

AC code:(由于比较简单,所以不用像上题一样先写goto版本了)

#include
#define L long

int func(int n, int m)
{          //%edi    %esi
    L ec = 1;
    L r8 = 0;
    int ea, ed;

    if(n > 0)
    {
        do
        {
            ed = ec;
            ea = ec;
            ed >>= 31;
            
            ed = ea % m;
            ea = ea / m;

            ea = r8 + ec;
            if(ed == 0) r8 = ea;

            ec ++;

        }while(n >= ec);
    }

    ea = r8;
    return r8;
}

int main()
{
    int n, m;

    scanf("%d%d", &n, &m);

    printf("%dn", func(n, m));

    return 0;
}

4.循环结构的翻译2(do...while)

题目描述

下面的汇编代码是某个函数编译后生成的:

    movl $0, %eax

.L3:

    leal -1(%rdi), %edx

    movl %edx, %ecx

    imull %edi, %ecx

    subl $2, %edi

    imull %ecx, %edi

    addl %edi, %eax

    testl %edx, %edx

    jle .L2

    movl %edx, %edi

    jmp .L3

.L2:

    rep

    ret

main函数已经写好了,请根据上述汇编代码设计一个等价的C函数:

int main(){

int n;

scanf("%d",&n);

printf("%dn",func(n));

return 0;

}

输入描述

输入整型数n

输出描述

调用函数并输出函数的返回值

提示

你需要提交完整的程序,请将上面的main函数复制到你的程序中。

难点

无,对照翻译就好

AC code

#include
#define L long

int func(int n)
{          //%edi
    int ea = 0;
    L ed, ec;
    while(1)
    {
        ed = n - 1;
        ec = ed;
        ec = n * ec;
        n -= 2;
        n = n * ec;
        ea += n;
        if(ed <= 0) break;
        n = ed;
    }
    return ea;
}

int main()
{

    int n;

    scanf("%d",&n);

    printf("%dn",func(n));

    return 0;

}

5.循环结构的翻译1(while)

题目描述

下面的汇编代码是某个函数编译后生成的:

    testl %edi, %edi

    jle .L2

    movl $1, %edx

    movl $1, %ecx

.L3:

    movslq %edx, %rsi

    imulq %rsi, %rcx

    addq %rcx, %rax

    addl $1, %edx

    cmpl %edx, %edi

    jge .L3

.L2:

    rep

    ret

main函数已经写好了,请根据上述汇编代码设计一个等价的C函数:

int main(){

    int n;

    scanf("%d",&n);

    long result=func(n);

    printf("%ldn",result);

    return 0;

}

输入描述

输入整型数a

输出描述

调用函数并输出函数的返回值

提示

你需要提交完整的程序,请将上面的main函数复制到你的程序中。

 难点

无,对照翻译就好

AC code

#include
#define L long

L func(int n)
{       //%edi

    L ra = 0, rs;
    L rd, rc;

    if(n > 0)
    {
        rd = 1;
        rc = 1;
        do
        {
            rs = rd;
            rc = rc * rs;
            ra = ra + rc;
            rd += 1;

        }while(n >= rd);
    }
    return ra;
}

int main()
{
    int n;
    scanf("%d", &n);

    long result = func(n);

    printf("%ldn", result);

    return 0;

}


6.选择结构的翻译3

题目描述

下面的汇编代码是某个函数编译后生成的:

    cmpl %esi, %edi

    jge .L2

    movl %edx, %eax

    subl %esi, %eax

    movl %esi, %ecx

    subl %edx, %ecx

    cmpl %edx, %esi

    cmovge %ecx, %eax

    ret

.L2:

    movl %edx, %eax

    subl %edi, %eax

    movl %edi, %ecx

    subl %edx, %ecx

    cmpl %edx, %edi

    cmovge %ecx, %eax

    ret

main函数已经写好了,请根据上述汇编代码设计一个等价的C函数:

int main(){

    int a,b,c;

    scanf("%d%d%d",&a,&b,&c);

    printf("%dn",func(a,b,c));

    return 0;

}

输入描述

输入三个整型数a,b和c

输出描述

输出函数调用的返回值

提示

你需要提交完整的程序,请将上面的main函数复制到你的程序中。

 难点

无,对照翻译就好

AC code

#include
#define L long

L func(int a, int b, int c)
{       //%edi   //%esi  //%edx
    L ea, ec;

    if(a = c) ea = ec;
    }
    else
    {
        ea = c;
        ea= ea - a;
        ec = a;
        ec = ec - c;
        if(a >= c) ea = ec;
    }

    return ea;
}

int main()
{
    int a, b, c;

    scanf("%d%d%d", &a, &b, &c);

    printf("%dn", func(a, b, c));

    return 0;

}

7.选择结构的翻译2

题目描述

面的汇编代码是某个函数编译后生成的:

  cmpl $9, %edi

  jg .L2

  leal (%rsi,%rdi), %eax

  movl %edi, %edx

  subl %esi, %edx

  cmpl %esi, %edi

  cmovge %edx, %eax

  ret

.L2:

  movl $13, %eax

  imull %edi, %esi

  cmpl $19, %edi

  cmovle %esi, %eax

  ret

main函数已经写好了,请根据上述汇编代码设计一个等价的C函数:

int main(){

    int x,y;

    scanf("%d%d",&x,&y);

    printf("%dn",func(x,y));

    return 0;

}

输入描述

输入两个整型数x和y

输出描述

输出函数调用的返回值

提示

你需要提交完整的程序。请将题干中的main函数复制到你的程序中

难点

无,对照翻译就好

AC code

#include
#define L long

L func(int x, int y)
{       //%edi   //%esi

    L ea, ed;

    if(x = y) ea = ed;
    }
    else
    {
        ea = 13;
        y = x * y;
        if(x <= 19) ea = y;
    }
    return ea;
}

int main()
{
    int x, y;

    scanf("%d%d", &x, &y);

    printf("%dn", func(x, y));

    return 0;

}

8.选择结构的翻译1

题目描述

下面的汇编代码是某个函数编译后生成的:

movq %rdi, %rax

subq %rsi, %rax

leaq        (%rsi,%rdi), %rdx

cmpq %rsi, %rdi

cmovle %rdx, %rax

ret

main函数已经写好了,请根据上述汇编代码设计一个等价的C函数:

int main(){

long a,b;

scanf("%ld%ld",&a,&b);

printf("%ld",func(a,b));

return 0;

}

输入描述

输入两个长整型数a和b

输出描述

输出函数调用的返回值

提示

你需要提交main函数之外的其他代码。

  

难点

无,对照翻译就好

PS:不是很懂这题的数据范围,但是能过就行

AC code

long func(long a, long b)
{       //%rdi   //%rsi

    long ra = a - b;
    long rd = a + b;
    if(a <= b) ra = rd;

    return ra;
}

感觉这个出题顺序不是很合理昂,难度从难到易....

ending.