目录
一:知识回顾
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.