Chapter 3 程序的机器级表示(下)

本文详细介绍了计算机程序中的控制结构,包括条件码的使用、无条件与条件跳转指令,以及各种循环结构的翻译方法,如do-while、while和for循环。通过具体的代码示例展示了如何将高级语言的控制结构转化为机器可执行的指令,强调了跳转表在switch语句中的应用和优化。
摘要由CSDN通过智能技术生成

一、控制代码

1.条件码

条件码
影响标志位的指令总结:

  1. 算术和逻辑指令(见右图)会设置标志位;
  2. leal/leaq指令是计算地址,不影响标志位;
  3. 逻辑操作,CF=0和OF=0;
  4. 移位操作以最后一个移出的位设置CF,OF=0;
  5. INC/DEC设置OF和ZF,不设置CF
  6. CMP类似于SUB,但比较指令只设置标志
  7. TEST指令对标志位影响和AND相同

规律:

  • 如果需要比较两个数的大小时需要使用cmp获得相减后结果,如果是一个bool类型(一个值),则往往使用test来将参考值写到条件码中。

访问条件码

  • 利用条件码状态设置某个字节(可以是内存单元或16个单字节寄存器之一)
  • 利用条件码完成跳转
  • 根据条件码而有条件地完成数据传送
    在这里插入图片描述
    set的作用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的改进
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值