CSAPP第五次讨论课:参照汇编代码将 c 语言程序补充完整

文章目录

题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解答

f:
pushl %ebp         //保存old %ebp 
movl %esp, %ebp    //%ebp=%esp
movl 8(%ebp), %eax //%eax值变为x
movl %eax, %edx    //%edx值变为x
imull 8(%ebp), %edx //%edx和x做有符号乘,结果x*x保存在%edx中
movl 12(%ebp), %ecx //%ecx值变为y
movl $0, %eax      
subl %ecx, %eax 	  //%eax-%ecx,结果-y保存在%eax中
addl %eax, %eax     //%eax=-2*y
addl %edx, %eax     //%eax=-2y+x*x
popl %ebp 			  //栈的恢复
ret                  //返回值保存在%eax
由上述分析可知int f(int x,int y)函数返回值是x*x-2y。
main: 
pushl %ebp 
movl %esp, %ebp 
subl $56, %esp 
movl $3, -44(%ebp) 	//从%ebp-44到%ebp-9保存int 数组a[] 
movl $-5, -40(%ebp) 
movl $6, -36(%ebp) 
movl $7, -32(%ebp) 
movl $2, -28(%ebp) 
movl $-8, -24(%ebp) 
movl $10, -20(%ebp) 
movl $2, -16(%ebp) 
movl $4, -12(%ebp) 
movl $0, -8(%ebp)    //%ebp-8位置保存i,初值为0
movl $8, -4(%ebp)    //%ebp-4位置保存j,初值为8
movl $0, -8(%ebp) 
jmp.L3		//直接跳转到.L3

在这里插入图片描述

.L3:  
movl -8(%ebp), %eax //将i赋值给%eax
cmpl -4(%ebp), %eax //将i和j比较,i-j改变条件码
jl .L7 			   //如果i<j跳转到.L7,否则顺序执行
movl $0, %eax 
leave 					//结束main函数
ret

当i<j时,跳转到.L7:
.L7: 
movl -8(%ebp), %eax  //%eax=i
movl -44(%ebp,%eax,4), %eax //数组的访问,将a[i]写入%eax
testl %eax, %eax 				//%eax&%eax,改变条件码
js .L8							//SF=1,证明a[i]<0就跳转到.L8

当a[i]<0时跳转到.L8:
.L8: 
nop                         //空指令
.L5: 
addl $1, -8(%ebp) 			//i++
subl $1, -4(%ebp) 			//j--
.L3:

由汇编代码可知,当a[i]<0时跳转到.L8执行i++和j—操作,然后又执行判断,判断是否循环,所以对应c程序中的:
在这里插入图片描述
第一空for循环的判断条件为i<j,第二空则为i++,j–,第一个if语句判断条件为a[i]<0,如图:
在这里插入图片描述

当执行.L7中的jl .L7时,如果a[i]>0,不跳转,执行其后的汇编:

.L4: 
movl -8(%ebp), %eax 			  //%eax值变为i
movl -44(%ebp,%eax,4), %edx   //%edx值变为a[i]
movl %edx, %eax 
addl %eax, %eax 					//%edx值变为2*a[i]
addl %eax, %edx 				 //%edx值变为3*a[i]
movl -8(%ebp), %eax 			
movl -44(%ebp,%eax,4), %ecx   //%ecx=a[i]
movl -8(%ebp), %eax 
addl $1, %eax 				//i=i+1
movl -44(%ebp,%eax,4), %eax   //%eax=a[i+1]
addl %ecx, %eax 					//%eax=a[i]+a[i+1]
movl %edx,4(%esp)
//将3*a[i]放入esp+4到esp+7的内存中,做传递的第二个参数
movl %eax, (%esp) 	
//将a[i]+a[i+1]放入esp到esp+3的内存中,做传递的第一个参数
call f       //调用f函数
movl -4(%ebp), %edx   //%edx=j
movl -44(%ebp,%edx,4), %edx  //%edx=a[j]
cmpl %edx, %eax  //比较调用函数后得到的返回值和a[j]的大小并改变条件码
jle.L6          //如果f(a[i]+a[i+1],3*a[i])<a[j]就跳转到.L6
movl -8(%ebp), %eax  //%eax=i
movl %eax, %edx   //%edx=i
imull -4(%ebp), %edx //%edx=i*j
movl -8(%ebp), %eax 
movl %edx, -44(%ebp,%eax,4) //a[i]=i*j
jmp.L5 
.L6: 
movl -8(%ebp), %eax 
movl -8(%ebp), %edx 
movl %edx, -44(%ebp,%eax,4) //a[i]=i
jmp.L5

由上述分析可知,如果f(a[i]+a[i+1],3a[i])<a[j]就跳转到.L6执行a[i]=i,对应C程序中的else分支,如果f(a[i]+a[i+1],3a[i])>a[j]执行a[i]=i*j.
所以for循环内部填空为:
在这里插入图片描述

综上,本题答案为:
在这里插入图片描述

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值