一、控制代码
1.条件码
影响标志位的指令总结:
- 算术和逻辑指令(见右图)会设置标志位;
- leal/leaq指令是计算地址,不影响标志位;
- 逻辑操作,CF=0和OF=0;
- 移位操作以最后一个移出的位设置CF,OF=0;
- INC/DEC设置OF和ZF,不设置CF
- CMP类似于SUB,但比较指令只设置标志
- TEST指令对标志位影响和AND相同
规律:
- 如果需要比较两个数的大小时需要使用cmp获得相减后结果,如果是一个bool类型(一个值),则往往使用test来将参考值写到条件码中。
访问条件码
- 利用条件码状态设置某个字节(可以是内存单元或16个单字节寄存器之一)
- 利用条件码完成跳转
- 根据条件码而有条件地完成数据传送
set的作用
2.跳转
无条件跳转:jmp
条件跳转:je/jne/jz/jnz/jg/jge/jl/jle/ja/jae/jb/jbe
if语句的翻译
if(test-expr)
if_statement;
else
else_statement;
转换为:
int t = test-expr;
if(!t)
goto false;
if_statement;
goto done;
false:
else_statement;
done:
exit();
样例:
int absdiff(int x, int y) {
if (x < y)
return y - x;
else
return x - y;
}
转换为:
# x at %ebp+8, y at %ebp+12
movl 8(%ebp), %edx # Get x
movl 12(%ebp), %eax # Get y
cmpl %eax, %edx # Compare x:y
jge .L2 # if >= goto x_ge_y
subl %edx, %eax # Compute result = y-x
jmp .L3 # Goto done
.L2: # x_ge_y:
subl %eax, %edx # Compute result = x-y
movl %edx, %eax # Set result as return value
.L3: # done: Begin completion code
if语句的另外一种翻译形式
int t = test-expr;
if(t)
goto true;
else_statement;
goto done;
true:
then_statement;
done:
exit();
练习:
|
|
swich语句的翻译
- switch开关语句根据一个整数索引值来进行多重分支(multi-way branch)
- GCC编译器根据分支数量和开关值得稀疏程度来翻译开关语句。但数量较多且比较密集时会使用跳转表(jump table)
- 使用跳转表时,执行速度与分支数量没有关系
3.循环
do-while循环:
do
body-statement;
while(test-expr)
转换为goto的形式:
loop:
body-statement;
t = test-expr
if(t)
goto loop;
示例代码(求n!):
int fact_do(int n) {
int result = 1;
do {
result *= n;
n = n-1;
} while (n > 1);
return result;
}
转换为:
# Argument: n at %ebp+8
# Registers: n in %edx, result in %eax
movl 8(%ebp), %edx # Get n
movl $1, %eax # Set result = 1
.L2:
loop:
imull %edx, %eax # Compute result *= n
subl $1, %edx # Decrement n
cmpl $1, %edx # Compare n:1
jg .L2 # If >, goto loop
retq # Return result
while循环:
while(test-expr)
body-statement;
转换为
①jump to middle形式
goto test;
loop:
body-statement;
test:
if(test-expr)
goto loop;
②guarded-do形式
if(!test-expr)
goto done;
loop: // 其实从loop到goto done是一个完整的do-while,while只是比do-while
body-statement; // 最外层多了一层判断
if(!test-expr)
goto done;
done:
for循环:
for (init-expr; test-expr; update-expr)
body-statement
先转换为while:
init-expr;
while (test-expr) {
body-statement
update-expr;
}
按照guarded-do形式翻译出来
init-expr;
t = test-expr;
if (!t)
goto done;
loop:
body-statement
update-expr;
t = test-expr;
if (t)
goto loop;
done:
示例代码:
int fact_for(int n){
int i;
int result = 1;
for (i = 2; i <= n; i++)
result *= i;
return result;
}
init-expr i = 2
test-expr i <= n
update-expr i++
body-statement result
movl 8(%ebp), %ecx # Get n
movl $2, %edx # Set i to 2 (init)
movl $1, %eax # Set result to 1
cmpl $1, %ecx # Compare n:1 (!test)
jle .L14 # If <=, goto done
.L17: loop:
imull %edx, %eax # Compute result *= i (body)
addl $1, %edx # Increment i (update)
cmpl %edx, %ecx # Compare n:i (test)
jge .L17 # If >=, goto loop
.L14: done:
针对for中的continue的改进