ImageVerifierCode 换一换
格式:PPT , 页数:44 ,大小:146KB ,
资源ID:10283284      下载积分:12 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/10283284.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(4编译原理-陈意云--课后答案4教学文案.ppt)为本站上传会员【w****g】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

4编译原理-陈意云--课后答案4教学文案.ppt

1、单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,*,luanj,*,4编译原理,陈意云,课后答案4,6.1,使用Pascal的作用域规则,确定下面程序中用于名字a,b的每个出现的声明。程序输出整数1,2,3,4,program a(input output);procedure b(u,v,x,y:integer);var a:record a,b:integer end;b:record b,a:integer end;begin with a do begin a:=u;b:=v end;with b do begin a:=x;b:=y end;writeln(a.a

2、a.b,b.a,b.b)end;begin b(1,2,3,4)end.,5/14/2025,2,luanj,6.1(续),with aarecorda:=uaa.ab:=vba.bwith bbrecorda:=xab.ab:=ybb.b,5/14/2025,3,luanj,6.2,考虑下面的C程序 main()char*cp1,*cp2;cp1=“12345”;cp2=“abcdefghij”;strcpy(cp1,cp2);printf(“cp1=%s n cp2=%s n”,cp1,cp2);该程序经以前的某些C编译器编译后,运行结果为:cp1=abcdefghij cp2=ghij

3、 试分析为什么cp2被修改,5/14/2025,4,luanj,6.2(续),C语言中,字符串会添加0作为串的结束符,因此,串”12345”存储为”123450”,而串”123450abc0”打印出来的只有12345,常量区连续分配,因而本题中”12345”和”abcdefghij”存储为1 2 3 4 5 0 a b c d e f g h i j 0cp1 cp2拷贝后结果为a b c d e f g h i j 0 f g h i j 0cp1 cp2,现代编译器编译通过,执行时会出错。(GCC:段错误/VC 非法访问),5/14/2025,5,luanj,6.3,一个C程序如下:typ

4、edef struct _a char c1;long I;char c2;double f;a;typedef struct _b char c1;char c2;long l;double f;b;main()printf(“Size of double,long,char=%d,%d,%dn”,sizeof(double),sizeof(long),sizeof(char);printf(“Size of a,b=%d,%dn”,sizeof(a),sizeof(b);该程序在SPARC/Solaris工作站上运行结果如下:Size of double,long,char=8,4,1Si

5、ze of a,b=24,16试分析为什么,5/14/2025,6,luanj,6.3(续),数据对齐:为了寻址方便,A:charOXXXlongOOOOcharOXXX XXXXdoubleOOOO OOOO,B:charOcharOXXlongOOOO doubleOOOO OOOO,可以用gcc S命令查看编译后的汇编码VC下可以在debug模式下,菜单栏View-Debug Windows中 Dissassenbly查看编译后的汇编码,GCC:(GNU)3.2.2(Red Hat Linux 3.2.2-5)结果为20,16,5/14/2025,7,luanj,6.3(续),#incl

6、ude static struct _achar c1;long i;char c2;double f;a =A,1,B,1.0;,VC6下,Debug模式Memory窗口查看,GCC:(GNU)3.2.2 20030222(Red Hat Linux 3.2.2-5),|A|1|B|1.0|,5/14/2025,8,luanj,6.4,下面给出一个C程序及其在X86/Linux下的编译结果,根据所生成的汇编程序来解释程序中4个变量的存储分配、作用域、生成期和置初始值方式的区别static long aa=10;short bb=20;func()static long cc=30;short

7、 dd=40;生成的汇编代码:,5/14/2025,9,luanj,6.4(续),.file static.c“,.version“01.01”,gcc2_compiled:,.data,.align 4,.type aa,object,.size aa,4,aa:,.long 10,.globl bb,.align 2,.type bb,object,.size bb,2,bb:,.value 20,.align 4,.type cc.2,object,.size cc.2,4,cc.2:,.long 30,.text,.align 4,.globl func,.type func,func

8、tion,func:,pushl%ebp,movl%esp,%ebp,subl$4,%esp,movw$40,-2(%ebp),.L1:,leave,ret,.Lfe1:,.size func,.Lfe1-func,.ident GCC:(GNU)egcs-2.91.66 19990314/Linux(egcs-1.1.2 release)”,5/14/2025,10,luanj,6.4(续),.file static.c“,.version“01.01”,gcc2_compiled:,.data,.align 4,.type aa,object,.size aa,4,aa:,-aa分配在静态

9、数据区,作用域为本文件,生存期为整个程序,.long 10,aa静态置初值,.globl bb,-bb分配在静态数据区,作用域为全局,可以被其他文件引用,生存期为整个程序,.align 2,.type bb,object,.size bb,2,bb:,.value 20,bb静态置初值,.align 4,.type cc.2,object,.size cc.2,4,cc.2:,-cc,分配在静态数据区,作用域为本文件,生存期为整个程序。源程序中在函数内部,为防止重名,需要重命名为cc.2,.long 30,cc静态置初值,.text,.align 4,.globl func,.type fun

10、c,function,func:,pushl%ebp,movl%esp,%ebp,subl$4,%esp,movw$40,-2(%ebp),-dd分配在栈上,生存期为func调用期,动态置初值,.L1:,leave,ret,.Lfe1:,.size func,.Lfe1-func,.ident GCC:(GNU)egcs-2.91.66 19990314/Linux(egcs-1.1.2 release)”,5/14/2025,11,luanj,6.5,假定使用:(a)值调用;(b)引用调用;(c)值-结果调用;(d)换名调用。下面程序的结果分别是什么?program main(input,o

11、utput);var a,b:integer;procedure p(x,y,z:integer);begin y:=y+1;z:=z+x;end;begin a:=2;b:=3;p(a+b,a,a);print a;end.,5/14/2025,12,luanj,6.5(续),值调用x:=5;y:=2;z:=2;y:=y+1;z:=z+x;对形参的调用不改变实参的值,结果a为2,引用调用t:=a+b;a=a+1;a=a+t;结果a为8,值-结果调用t:=a+b;x:=t;y:=a;z:=ay:=y+1;z:=z+x;t:=x;a:=y;a:=z;结果为7,换名调用a:=a+1;a:=a+(a

12、b);结果为9,5/14/2025,13,luanj,6.6,一个C程序如下:func(i1,i2,i3)long i1,i2,i3;long j1,j2,j3;printf(“Address of i1 i2 i3=%o,%o,%on”,该程序在X86/Linux上运行结果为:Address of i1,i2,i3=27777775460,27777775464,27777775470Address of j1,j2,j3=27777775444,27777775440,27777775434从结果看func的3个形参地址逐渐升高,而3个局部变量地址逐渐降低。试说明为什么,5/14/202

13、5,14,luanj,6.6(续),C语言中,实参从右向左进栈,所以func(i1,i2,i3)按i3,i2,i1的顺序进栈,而j1,j2,j3按声明的顺序分配,5/14/2025,15,luanj,6.7,下面的C程序中,printf的调用仅含格式控制串,运行时输出3个参数,分析之main()printf(“%d%d%dn”);,5/14/2025,16,luanj,6.7(续),C语言不做实参和形参个数类型是否一致的检查,printf函数根据第一个参数格式控制列表,到栈中取参数,本题中虽然只传了格式控制列表,但是printf函数分析格式控制列表,认为程序员还传了3个整型数,因此继续去栈中取

14、3个参数,并输出之。,所以得到了三个不可预知值得整数。,5/14/2025,17,luanj,6.8,下面给出一个C程序及其在X86/Linux下的编译结果。从结果看,func的四个局部变量i1,j1,f1,e1的地址间隔和他们的类型一致,而形参i,j,f,e的地址间隔和他们的类型不一致,试分析原因func(i,j,f,e)short i,j;float f,e;short i1,j1;float f1,e1;printf(“Address of i,j,f,e=%o,%o,%o,%on”,运行结果:Address of i,j,f,e=35777772536,35777772542,3577

15、7772544,35777772554Address of i1,j1,f1,e1=35777772426,35777772426,35777772424,35777772420,35777772414Size of short,int,long,float,double=2,4,4,4,8,5/14/2025,18,luanj,6.8(续),C语言为了不保证实参和形参类型一致,因此为了尽可能保证得到正确结果,编译器在整型和实型做实参时,将他们提升为long和double传递。,但是函数内部取参数时,仍按照原来的类型去取,5/14/2025,19,luanj,6.8(续),main传参数时,提

16、升数据类型,func取参数时,按原来的数据类型,i:short-int,4字节,j:short-int,4字节,f:long-double,8字节,e:long-double,8字节,i:short 2字节,j:short 2字节,f:long 4字节,e:long 4字节,5/14/2025,20,luanj,6.9,一个C程序func(c,l)char c;long l;func(c,l);在x86/Linux上编译生成的汇编代码如下,请说明char和long在参数传递和存储分配上的区别,5/14/2025,21,luanj,6.9(续),.file parameter.c“,.versi

17、on“01.01”,gcc2_compiled.:,.text,.align 4,.globl func,.type func,function,func:,pushl%ebp -将老的基址指针压栈,movl%esp,%ebp -将当前栈顶指针作为基址,subl$4,%esp -分配空间,movl 8(%ebp),%eax,movb%al,-1(%ebp),movl 12(%ebp),%eax,pushl%eax,movsbl-1(%ebp),%eax pushl%eax,call func,addl$8,%esp,.L1:,leave,ret,.Lfe1:,.size func,.Lfe1-

18、func,.ident GCC:(GNU)egcs-2.91.66 19990314/Linux(egcs-1.1.2 release)”,5/14/2025,22,luanj,6.9(续)Some AT&T ASM Syntax,寄存器:8个32-bit寄存器%eax,%ebx,%ecx,%edx,%edi,%esi,%ebp,%esp;,操作符 源 目的,-1(%ebp):基址:%ebp,偏移:-1,加在指令后的符号表示操作数的长度:b(byte,8-bit)w(word,16-bits)l(long,32-bits),movsbl:movs:符号扩展指令movsbl意味着movs(fro

19、m)byte(to)long;movbw意味着movs(from)byte(to)word;movswl意味着movs(from)word(to)long。,More:plz google “AT&TASM”,5/14/2025,23,luanj,6.9(续),movl 8(%ebp),%eax,-取c,movb,%al,-1(%ebp),-取其字节值,存入分配的存储单元,movl 12(%ebp),%eax,-取l,pushl%eax,-l压栈,movsbl,-1(%ebp),%eax,-取c,并转换成long,pushl%eax,-c压栈,call func,-调用func,addl$8,

20、esp,-恢复压栈前状态,5/14/2025,24,luanj,6.10,从例6.5可以看到,C程序执行时只用到了控制链,不需要使用访问链.为什么Parscal程序执行时需要使用访问链,而C程序不需要?,5/14/2025,25,luanj,6.10(续),PASCAL允许过程嵌套,执行时,可以访问非全局且非局部的变量,所以需要访问链帮助确定数据所在活动记录在栈中的位置而C不允许过程嵌套,只能访问全局和局部变量,所以不需要访问链。,5/14/2025,26,luanj,6.11,下面是求阶乘的Pascal程序.画出程序第三次进入函数factor时的活动记录栈和静态链.program fact

21、input,output);var f,n:integer;function factor(n:integer):integer;beginif n=0 then factor:=1else factor:=n*(factor(n-1)end;begin n:=5;f:=factor(n);write(f)end.,5/14/2025,27,luanj,6.11(续),fact,f,n,factor,访问链,n,factor,访问链,n,factor,访问链,n,1,2,2,5/14/2025,28,luanj,6.12,在下面假想的程序中,第(11)行语句f:=a调用函数a,a传递函数ad

22、dm作为返回值.(a)画出该程序执行的活动树.(b)假定非局部名字使用静态作用域,为什么该程序在栈式分配情况下不能正确工作?(c)在堆分配策略下,该程序的输出是什么?,5/14/2025,29,luanj,6.12(续),program,ret,(input,output);,var f:function(integer):integer;,function,a,:function(integer):integer,var m:integer;,function,addm,(n:integer):integer,begin return m+n end;,begin m:=0;return a

23、ddm end;,procedure,b,(g:function(integer):integer);,begin writeln(g(2)end;,begin,f:=a;b(f),end,5/14/2025,30,luanj,6.12(续),活动树如右图,在执行addm时,只有ret,b和addm的活动记录,a的已释放。如果是静态作用域,n对应的是第(4)行中的m,他处于a的活动记录中,而此时a的已释放。,堆分配结果是2,ret,a,b,addm,5/14/2025,31,luanj,6.13,为什么C语言允许函数类型(的指针)作为函数的返回值类型,而Pascal语言却不允许?,5/14/2

24、025,32,luanj,6.13(续),参考6.12,课本P202,5/14/2025,33,luanj,6.14,一个C语言程序如下:int n;int f(int g)int m;m=n;if(m=0)return 1;elsen=n-1;return m*f(n);main()n=5;printf(“%d factorial is%dn”,n,f(n);该程序的运行结果不是我们所期望的 5 factorial is 120而是 0 factorial is 120试说明原因.,5/14/2025,34,luanj,6.14(续),参数逆序进栈,因此,f(n)先被执行,而f(n)执行结束

25、时,n值已经被改写为0,此时再将n值压栈,因而输出“0 factorial is 120”,5/14/2025,35,luanj,6.15,下面程序在SPARC/SUN工作站上运行时陷入死循环,试说明原因.如果将第7行的 long*p改成 short*p,并且将第22行 long k改成short k后,loop中的循环体执行一次便停止了.试说明原因.main()addr();loop();long*p;loop()long i,j;j=0;for(i=0;i10;i+)(*p)-;j+;addr()long k;k=0;p=,5/14/2025,36,luanj,6.15(续),程序运行时陷

26、入死循环的原因是由于指向分配给i的存储单元引起的。循环体执行一次便停止时由于p指向分配给i的高位字节引起的。,C语言的实现是采用栈式分配,使得函数addr和函数loop的活动记录先后从同样的存储单元开始分配,从而长整数k和i先后分配在同样的存储单元,因此p指向分配给i的存储单元。,SPARC/SUN 工作站上整数的存放方式是低地址放高位字节,而高地址放低位字节。另外,活动记录栈是从高地址向低地址方向增长。,当k改为短整型且p改为短整型指针后,那么p指向由i的两个低位字节组成的短整数。执行(*p)-使得这两个字节构成的短整数等于-1。而从整个4个字节看时,是65535,远大于10。所以循环体执行

27、一次便停止。,5/14/2025,37,luanj,6.16,一个C语言程序 main()func();printf(“Return from func n”);func()char s4;strcpy(s,”12345678”);printf(“%sn”,s);在X86/Linux操作系统上的运行结果如下:12345678 Return from func Segmentation fault(core dumped)试分析为什么会出现这样的运行错误.,5/14/2025,38,luanj,6.16(续),数组越界访问。,出现短错误,说明控制链被破坏,func可以返回main说明func的返

28、回地址没有被破坏,而main不能返回,说明main的返回地址被破坏,本,题Red Hat Linux 3.2.2/GCC:(GNU)3.2.2下结果为,12345678段错误main返回地址被破坏,5/14/2025,39,luanj,6.17,一个过程作为实在参数传递,它被激活时的计算环境有三种可能的规定.第一种是使用词法环境,即该过程激活时的计算环境是依据其定义点的静态作用域得到.Pascal和C都是使用这种方式.第二种是使用传递环境,即该过程激活时的计算环境是依据其作为实在参数的调用点的静态作用域得到.第三种可能是使用活动环境,即该过程激活时的计算环境是依据其激活点的静态作用域得到.我们

29、以下面的Pascal程序为例来解释.考虑该程序第(11)行f作为实在参数传递的情况,对应上面三种规定,第(8)行的非局部名m分别在第(6)(10)和(13)行的作用域内.在这三种情况下,该程序的输出分别是什么?,5/14/2025,40,luanj,6.17(续),(1)program param(input,output);,(2)procedure b(function h(n:integer):integer);,(3)var m:integer;,(4)begin m:=3;writeln(h(2)end;b,(5)procedure c;,(6)var m:integer;,(7)f

30、unction f(n:integer):integer;,(8)begin f:=m+n end;f,(9)procedure r;,(10)var m:integer;,(11)begin m:=7;b(f)end;r,(12)begin m:=0;r end;c,(13)begin,(14)c,(15)end.,5/14/2025,41,luanj,6.17(续),词法环境:定义点m值为0,结果为2,传递环境:第11行,c的过程体把f作为参数传给b,此时m值为7,因此结果为9;,活动环境:第4行,在b的过程体中,h(2)激活f,此时m值为3,因此结果为5;,5/14/2025,42,luanj,谢谢!,此课件下载可自行编辑修改,仅供参考!感谢您的支持,我们努力做得更好!谢谢,

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服