ICS第三章习题答案_第1页
ICS第三章习题答案_第2页
ICS第三章习题答案_第3页
ICS第三章习题答案_第4页
ICS第三章习题答案_第5页
已阅读5页,还剩19页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1.给出以下概念的解释说明。机器语言程序机器指令汇编语言汇编指令汇编语言程序汇编助记符汇编程序反汇编程序机器级程序通用寄存器定点通用寄存器栈指针寄存器指令指针寄存器标志寄存器条件标志(条件码)控制标志寻址方式立即寻址寄存器寻址存储器操作数实地址模式保护模式比例变址非比例变址比例系数(比例因子)MMX指令SSE指令集SIMD多媒体扩展通用寄存器栈(Stack)调用者保存寄存器被调用者保存寄存器帧指针寄存器当前栈帧按值传递参数按地址传递参数嵌套调用递归调用缓冲区溢出缓冲区溢出攻击栈随机化.简单回答下列问题。一条机器指令通常由哪些字段组成?各字段的含义分别是什么?(2)将一个高级语言源程序转换成计算机能直接执行的机器代码通常需要哪几个步骤?IA-32中的逻辑运算指令如何生成条件标志?移位指令可能会改变哪些条件标志?(4)执行条件转移指令时所用到的条件标志信息从何而来?请举例说明。(5)无条件转移指令和调用指令的相同点和不同点是什么?(6)按值传递参数和按地址传递参数两种方式有哪些不同点?(7)为什么在递归深度较深时递归调用的时间开销和空间开销都会较大?(8)为什么数据在存储器中最好按地址对齐方式存放?(9)造成缓冲区溢出的根本原因是什么?.对于以下AT&T格式汇编指令,根据操作数的长度确定对应指令助记符中的长度后缀,并说明每个操作数的寻址方式。(1)mov8(%ebp,%ebx,4),%ax(2)mov%al,12(%ebp)(3)add(,%ebx,4),%ebx(4)or(%ebx),%dh(5)push$0xF8(6)mov$0xFFF0,%eax(7)test%ex,%ex(8)lea8(%ebx,%esi),%eax参考答案:(1)后缀:w>源:基址+比例变址+偏移,目:寄存器(2)后缀:b,源:寄存器,目:基址“移(3)后缀:L源:比例变址,目:寄存器(4)后缀:b,源:基址,目:寄存器(5)后缀:L源:立即数,目:栈(6)后缀:I,源:立即数,目:寄存器

(7)后缀:w,源:寄存器, 目:寄存器(8)后缀:1,源:基址校址盗移, 目:寄存器.使用汇编器处理以下各行AT&T格式代码时都会产生错误,请说明每一行存在什么错误。(1)movlOxFF,(%eax)(2)movb%ax,12(%ebp)(3)addl%ecx,$OxFO(4)orw$OxFFFFO,(%ebx)(5)addb$0xF8,(%dl)(6)movl%bx,%eax(7)andl%esi,%esx(8)movw8(%ebp,,4),%ax参考答案:(1)源操作数是立即数OxFF,需在前面加'$'(2)源操作数是16位,而长度后缀是字节'b,,不一致(3)目的操作数不能是立即数寻址(4)操作数位数超过16位,而长度后缀为16位的'w,(5)不能用8位寄存器作为目的操作数地址所在寄存器(6)源操作数寄存器与目操作数寄存器长度不一致(7)不存在ESX寄存器(8)源操作数地址中缺少变址寄存器.假设变量x和pfr的类型声明如下:src_typex;dst_type*ptr;这里,src_type和dstjype是用typedef声明的数据类型。有以下一个C语言赋值语句:*ptr=(dst_type)x;若x存储在寄存器EAX或AX或AL中,pfr存储在寄存器EDX中,则对于表3.12中给出的§rc_type和dstjype的类型组合,写出实现上述赋值语句的机器级代码。要求用AT&T格式汇编指令表示机器级代码。表3.12题5用表src_typedstjype机器级表示charintintcharintunsignedshortintunsignedcharunsignedcharunsignedintint参考答案:表3.12题5用表src_typedstjype机器级表示charintmovsbl%al,(%edx)intcharmovb%al,(%edx)intunsignedmovl%eax,(%edx)shortintmovswl%ax,(%edx)unsignedcharunsignedmovzH%al,(%edx)charunsignedmovsbl%al.(%edx)movblo«oo??intintmovl%eax,(%edx).假设某个C语言函数func的原型声明如下:voidfunc(int*xptr,int*yptr,int*zptr);函数func的过程体对应的机器级代码用AT&T汇编形式表示如下:1movl8(%ebp),%eax2movl12(%ebp),%ebx3movl16(%ebp),%ecx4movl(%ebx),%edx5movl(%ecx),%esi6movl(%eax),%edi7movl%edi,(%ebx)8movl%edx,(%ecx)9movl%esi,(%eax)请回答下列问题或完成下列任务。(1)在过程体开始时三个入口参数对应实参所存放的存储单元地址是什么?(提示:当前栈帧底部由帧指针寄存器EBP指示)(2)根据上述机器级代码写出函数func的C语言代码。参考答案:(1)xptr>yptr和zptr对应实参所存放的存储单元地址分别为:R[ebp]+8>R[ebp]+12>R[ebp]+16o(2)函数func的C语言代码如下:voidfunc(int*xptr,int*yptr,int*zptr){inttempx=*xptr;inttempy=*yptr;inttempz=*zptr;*yptr=tempx;*zptr=tempy;*xptr=tempz;}.假设变量x和y分别存放在寄存器EAX和ECX中,请给出以下每条指令执行后寄存器EDX中的结果。leal(%eax),%edxleal4(%eax,%ecx),%edxleal(%eax,%ecx,8),%edxlealOxC(%ecx,%eax,2),%edxleal(,%eax,4),%edxleal(%eax,%ecx),%edx参考答案:R[edx]=xR[edx]=x+y+4

R(edx]=x+8*yR[edx]=y+2*x+12R[edx]=4*yR[edx]=x+y8.假设以下地址以及寄存器中存放的机器数如表3.13所示。表3.13题8用表地址机器数寄存器机器数0x8049300OxfffffffOEAX0x080493000x80494000x80000008EBX0x000001000x80493840x80f7ff00ECX0x000000100x80493800x908fl2a8EDX0x00000080分别说明执行以下指令后,哪些地址或寄存器中的内容会发生改变?改变后的内容是什么?条件标志OF、SF、ZF和CF会发生什么改变?(1)add)(%eax),%edx(2)subl(%eax,%ebx),%ecx(3)orw4(%eax,%ecx,8),%bx(4)testb$0x80,%dl(5)imull$32,(%eax,%edx)(6)decw%ex参考答案:(1)指令功能为:R[edx|^-R|edx|+M[R|eax|]=0x00000080+M[0x8049300],寄存器EDX中内容改变。改变后的内容为以下运算的结果:Q0000080H+FFFFFFF0H0000000000000000000000001(X)00000+11111111111111i1111111111111()00()100000000000000000000000001110000因此,EDX中的内容改变为0x00000070。根据表3.5可知,加法指令会影响OF、SF、ZF和CF标志。OF=0,ZF=0,SF=0,CF=lo(2)指令功能为:R|ecxKR|ecx|-M[R[eax]+R[ebx]]=0x00000010+M[0x8049400],寄存器ECX中内容改变。改变后的内容为以下运算的结果:0000001OH-80000008H0000000000000000000000000(X)10(X)0+01111111111111111111111111111000010000000000000000000000000001000因此,ECX中的内容改为0x80000008。根据表35可知,减法指令会影响OF、SF、ZF和CF标志。OF=1,ZF=0,SF=1,CF=l©0=L(3)指令功能为:R[bx|^R|bx]orMjR[eax]+R[ecx)*8+4],寄存器BX中内容改变。改变后的内容为以下运算的结果:0x0100orM|0x8049384]=0100HorFF00H(XXX)0(X)100000000ormimiooooooooIlli111100000000因此,BX中的内容改为OxFFOO。由3.33节可知,OR指令执行后OF=CF=0;因为结果不为0,故ZF=0;因为最高位为1,故SF=1。

(4)test指令不改变任何通用寄存器,但根据以下“与,骤作改变标志:R[dl]and0x80I(XX)0(XX)and10000000KXX)(X)(X)由3・33节可知,TEST指令执行后OF=CF=0;因为结果不为0,故ZF=0;因为最高位为1,故SF=1。(5)指令功能为:M[R[eax]+R[edx]]<-M[R[eax]+R[edx]]*32,即存储单元0x8049380中的内容改变为以下运算的结果:M[0x8049380]*32=0x908fl2a8*32,也即只要将0x908fl2a8左移5位即可得到结果。10010000100011110001001010101000«5=00010001111000100101010100000000因此,指令执行后,单元0x8049380中的内容改变为0xlle25500。显然,这个结果是溢出的。但是,根据表3.5可知,乘法指令不影响标志位,也即并不会使OF=L(6)指令功能为:R[cx] 即CX寄存器的内容减一。000000000001(XXX)+111111111111111110000000000001111因此,指令执行后CX中的内容从0x0010变为OxOOOF。由表35可知,DEC指令会影响OF、ZF,SF,根据上述运算结果,得到OF=0,ZF=O,SF=O.9.假设函数operate的部分C代码如下:operate(int&inty,intz,intk)232345intv=.returnv;以下汇编代码用来实现第3行语句的功能,请写出每条汇编指令的注释,并根据以下汇编代码,填写。perate函movlsailmovlmovl12(%ebp),%movlsailmovlmovl12(%ebp),%ecx$8,%ecx8(%ebp),%eax20(%ebp),%edximull%edx,%eaxmovl16(%ebp),%edxandl$65520,%edx//R[ecx|«-M[R[ebp]+12],将y送ECX//R[ecxJ+-R[ecx]«8,将y*256送ECX//R[eax|«-M[R[ebp]+8],将x送EAX〃R[edx]-M[RIebp]+20],将k送EDX//R[eax]<-R[eax]*R[edxl,将x*k送EAX//R[edx|<-M[R[ebp]+16],将z送EDX//R[edx]<-Rledx]and65520,将z&OxFFFO送EDX数缺失的部分。1movl12(%ebp),%ecx2sail$8,%ecx3movl8(%ebp),%eax4movl20(%ebp),%edx5imull%edx,%eax6movl16(%ebp),%edx7andl$65520,%edx8addl%ecx,%edx9subl参考答案:%edx,%eaxaddl%ecx,%edx//R[edx]4-R[edx]+R[ecx],将z&0xFFF0+y*256送EDXsubl%edx,%eax//R[eax|<-R[eax]-R[edxl,将x*k・(z&0xFFF0+y*256)送EAX根据以上分析可知,第3行缺失部分为:3intv=x*k・(z&0xFFF0+y*256);10.假设函数product的C语言代码如下,其中nuni_type是用typedef声明的数据类型。voidproduct(num_type*d,unsignedx,num_typey){*d=x*y;}函数product的过程体对应的主要汇编代码如下:movl 12(%ebp),%eaxmovl 20(%ebp),%ecximull %eax,%ecxmull 16(%ebp)leal (%ecx,%edx),%edxmovl 8(%ebp),%ecxmovl %eax,(%ecx)movl %edx,4(%ecx)请给出上述每条汇编指令的注释,并说明num_type是什么类型。参考答案:从汇编代码的第2行和第4行看,y应该是占8个字节,R[ebp]+20开始的4个字节为高32位字节,记为丫卜;R[ebp]+16开始的4个字节为低32位字节,记为y,.根据第4行为无符号数乘法指令,得知y的数据类型num.type为unsignedlonglong.movl 12(%ebp), %eax //R[eax|«-MIR[ebpl+12],将x送EAXmovl 20(%ebp), %ecx 〃R[ecx]-M[R[ebp]+20],将yh送ECXimull %eax,%ecx //R[ecx|«—R|ecx]*R|eax],将y/x的低32位送ECXmull 16(%ebp) 〃R[edx|R[eax]—MR[ebp]+16]*R[eax],将 yi*x送EDX-EAXleal(%ecx,%edx),%edx//R[edxKR[ecx]+R[edx],将yi*x的高32位与yh*x的低32位相加后送EDXmovl8(%ebp),%ecx 〃R[ecx]—M[R[ebp]+8],将d送ECXmovl %eax,(%ecx) //M(R[ecx]|«—R[eax],将x*y低32位送d指向的低32位movl %edx,4(%ecx)//M[R[ecx]+4|«—R[edx],将x*y高32位送d指向的高32位11.已知IA-32是小端方式处理器,根据给出的IA-32机器代码的反汇编结果(部分信息用x表示)回答问题。(1)已知je指令的操作码为01110100,je指令的转移目标地址是什么?call指令中的转移目标地址0x80483bl是如何反汇编出来的?804838c: 7408 je xxxxxxx804838e: e8le000000 call 80483bl<test>(2)已知jb指令的操作码为01110010,jb指令的转移目标地址是什么?movl指令中的目的地址如何反汇编出来的?8048390: 72f6 jb xxxxxxx8048392: c60500a8040801movl$0x1,0x804a8008048399: 000000(3)已知jle指令的操作码为01111110,mov指令的地址是什么?xxxxxxx: 7e16 jle 80492e0xxxxxxx: 89dO mov%edx,%eax

(4)已知jmp指令的转移目标地址采用相对寻址方式,jmp指令操作码为11101001,其转移目标地址是什么?8048296: e9OOffffff jmp xxxxxxx804829b: 29c2 sub%eax,%edx参考答案:根据第3.3.4节得知,条件转移指令都采用相对转移方式在段内直接转移,即条件转移指令的转移目标地址为:(PC)本移量。(1)因为je指令的操作码为01110100,所以机器代码7408H中的08H是偏移量,故转移目标地址为:0x804838c+2+0x8=0x8048396。call指令中的转移目标地址0x80483bl=0x804838e+5+0xle,由此,可以看出,call指令机器代码中后面的4个字节是偏移量,因IA-32采用小端方式,故偏移量为0000001EH。call指令机器代码共占5个字节,因此,下条指令的地址为当前指令地址0x804838e加5.jb指令中F6H是偏移量,故其转移目标地址为:0x8048390+2+0xf6=0x8048488。movl指令的机器代码有10个字节,前两个字节是操作码等,后面8个字节为两个立即数,因为是小端方式,所以,第一个立即数为0804A800H,即汇编指令中的目的地址0x8()4a800,最后4个字节为立即数OOOOOOOIH,即汇编指令中的常数0x1。jle指令中的7EH为操作码,16H为偏移量,其汇编形式中的0x80492e0是转移目的地址,因此,假定后面的mov指令的地址为x,则x满足以下公式:0x80492e0=x+0x16,故x=0x80492e0-0xl6=0x80492ca。jmp指令中的E9H为操作码,后面4个字节为偏移量,因为是小端方式,故偏移量为FFFFFF00H,即-100H=-256.后面的sub指令的地址为0x804829b,故jmp指令的转移目标地址为0x804829b+0xffffff00=0x804829b-0x100=0x804819b,12.已知函数comp的C语言代码及其过程体对应的汇编代码如下:1voidcomp(*p)1voidcomp(*p)2(3if(p&&x<0)4*p+=X;5}1movb8(%ebp),%dl2movl12(%cbp),%eax3testl%eax,%eax4je.LI5testb$0x80,%dl6je.LI7addb%dl,(%eax)8.LI:要求回答下列问题或完成下列任务。(1)给出每条汇编指令的注释,并说明为什么C代码只有一个if语句而汇编代码有两条条件转移指令。(2)按照书中图3.22给出的“ifOgoto…”语句形式写出汇编代码对应的C语言代码。参考答案:(1)汇编指令的注解说明如下:1movb8(%ebp),%dl//R[dl]<-M[R[ebp]+8],将x送DL2mov)12(%ebp),%eaxZ/R[eax|«-MIR[ebp]+12],将p送EAX3testl%eax,%eax//R|eax|andR[eax],判断p是否为04je.LI/喏p为。,则转.LI执行5testb$0x80,%dl//R[dl]and80H,判断x的第一位是否为06je.LI/席x>=0,则转.L1执行7addb%dl,(%eax)//M[R[eax||*-M(R[eax]]+R|dl],即*p+=x8.L1:因为C语言if语句中的条件表达式可以对多个条件进行逻辑运算,而汇编代码中一条指令只能进行一种逻辑运算,并且在每条逻辑运算指令生成的标志都是存放在同一个EFLAGS寄存器中,所以,最好在一条逻辑

指令后跟一条条件转移指令,把EFLAGS中标志用完,然后再执行另一次逻辑判断并根据条件进行转移的操作。(2)按照书中图322给出的“if()goto…”语句形式写出汇编代码对应的C语言代码如下:voidcomp(charx,int*p)TOC\o"1-5"\h\z(if(p!=0)if(x<0)*p+=x;}13.已知函数func的C语言代码框架及其过程体对应的汇编代码如下,根据对应的汇编代码填写C代码中缺失的表达式。intfunc(intx,inty)1intz=;if(){if()z=elsez=;)elseif()z=;returnz;)1movl1movl8(%ebp),%eax2movl12(%ebp),%edx3cmpl$-100,%eax4jg.LI5cmpl%eax,%edx6jle.L27addl%edx,%eax8jmp.L39.L2:10subl%edx,%eax11jmp,L312.LI:13cmpl$16,%eax14jl.L415andl%edx,%eax16jmp.L317.L4:18imull%edx,%eax19.L3:intfiinc(intx,inty)(intz=x*y;if( ){if(y>x )z=x-1-y ;elsez= ;}elseif(x>=16)z= x&v;returnz;114.已知函数do_loop的C语言代码如下:shortdo_loop(shortx,shorty,shortk){do{x*=(y%k);

k-;}while((k>O)&&(y>k));returnx;}函数do.loop的过程体对应的汇编代码如下:1movw8(%ebp),%bx2movw12(%ebp),%si3movw16(%ebp),%ex4.LI:5movw%si,%dx6movw%dx,%ax7sarw$15,%dx8idiv%ex9imulw%dx,%bx10decw%ex11testw%ex,%ex12jle.L213cmpw%ex,%si14jg.LI15.L2:16movswl%bx,%eax请回答下列问题或完成下列任务:(D给每条汇编指令添加注释,并说明每条指令执行后,目的寄存器中存放的是什么信息?(2)上述函数过程体中用到了哪些被调用者保存寄存器和哪些调用者保存寄存器?在该函数过程体前面的准备阶段哪些寄存器必须保存到栈中?(3)为什么第7行中的DX寄存器需要算术右移15位?参考答案:(1)每个入口参数都要按4字节边界对齐,因此,参数x、y和A入栈时都占4个字节。12movwmovw8(%ebp),%bx12(%ebp),%si//R|bx|-M|R[ehp]+8],将x送BX//R|sil^-MlR(ebp]+12],将y送SI3movw16(%ebp),%ex//R[cx]«-M[R[ebp]+16],将★送CX4.LI:5movw%si,%dx〃R[dx]-R[si],将y送DX6movw%dx,%ax//R[ax|-R[dx],将y送AX7sarw$15,%dx//R[dx|<-R[dx]»15,将y的符号扩展16位送DX8idiv%ex〃R[dx]—R[dx-ax]+R[cxJ的余数,将y%A送DX〃R[ax]—R|dx-ax]+R[cx]的商,将冰送AX9imulw%dx,%bx//R[bxKR[bx]*R[dx],将x*(y%A)送BX10decw%ex//R[cx|«-R[cx]-1,将hl送CX11testw%ex,%ex//R[cx]andR|cx|,得OF=CF=0,负数则SF=1,零则ZF=112jle.L2/诺★小于等于0,则转.L213cmpw%ex,%si//R[si]-R[cx],将y与A相减得到各标志14jg.LI/唐y大于左则转.L115.L2:

16movswi%bx,%eax//R(eax]-<—R[bx],将x*(y%A)送AX(2)被调用者保存寄存器有BX、SI,调用者保存寄存器有AX、CX和DX。在该函数过程体前面的准备阶段,被调用者保存的寄存器EBX和ESI必须保存到栈中。(3)因为执行第8行除法指令前必须先将被除数扩展为32位,而这里是带符号数除法,因此,采用算术右移以扩展16位符号,放在高16位的DX中,低16位在AX中。15.已知函数fl的C语言代码框架及其过程体对应的汇编代码如下,根据对应的汇编代码填写C代码中缺失部分,并说明函数fl的功能。1intfl(unsignedx)21intfl(unsignedx)2(3inty=0;4while(_){56)7return ;8)1movl8(%ebp),%edx2movl$0,%eax3testl%edx,%edx4je.LI5.L2:6xorl%edx,%eax7shrl$l,%edx8jne.L29.LI:10andl$1,%eax参考答案:intri(unsignedx)TOC\o"1-5"\h\z{inty=0;while( x!=0){y“=x ;x»=l;}return y&Oxl;}函数fl的功能返回:(xAx»l"x>>2八….)&0xl,因此fl用于检测x的奇偶性,当x中有奇数个1,则返回为1,否则返回0。16.已知函数sw的C语言代码框架如下:intsw(intx){intv=0;switch(x){/*switch语句中的处理部分省略*/}returnv;)对函数sw进行编译,得到函数过程体中开始部分的汇编代码以及跳转表如下:

1movl1movl8(%ebp),%eax2addl$3,%eax3cmpl$7,%eax4ja.L75jmp*.L8(,%eax,4)6.L7:7 81.L8:2Jong.L73long.L24long.L25.long.L36long.L47long.L58.long.L79Jong.L6回答下列问题:函数SW中的switch语句处理部分标号的取值情况如何?标号的取值在什么情况下执行default分支?哪些标号的取值会执行同一个case分支?参考答案:函数SW只有一个入口参数心根据汇编代码的第2~5行指令知,当x+3>7时转标号.L7处执行,否则,按照跳转表中的地址转移执行,x与跳转目标处标号的关系如下:x+3=0:.L7x+3=l:.L2x+3=2:.L2x+3=3:.L3x+3=4:.\Ax+3=5:.L5x+3=6:.L7x+3=7:.L6由此可知,switch(x)中省略的处理部分结构如下:case-2:case-1:…… 〃.L2标号处指令序列对应的语句break;case0:…… 〃.L3标号处指令序列对应的语句break;…….//.L4标号处指令序列对应的语句break;…… 〃.L5标号处指令序列对应的语句break;case4:…… //.L6标号处指令序列对应的语句break;default:…… 〃.L7标号处指令序列对应的语句17.已知函数test的入口参数有a、b、c和p,C语言过程体代码如下:*p=a;returnb*c;函数test过程体对应的汇编代码如下:movl20(%ebp),%edxmovsbw8(%ebp),%axmovw %ax,(%edx)movzwl12(%ebp),%eaxmovzwl16(%ebp),%ecxmull %ecx,%eax写出函数test的原型,给出返回参数的类型以及入口参数a、b、c和〃的类型和顺序。参考答案:根据第2、3行指令可知,参数a是char型,参数p是指向short型变量的指针;根据第4、5行指令可知,参数b和c都是unsignedshort型,根据第6行指令可知,test的返回参数类型为unsignedint。因此,test的原型为:unsignedinttest(chara,unsignedshortb,unsignedshortc,short*p);.已知函数fund的C语言代码如下:intfunct(viod){intx,y;scanf("%x%x”,&x,&y);returnx-y;)函数fund对应的汇编代码如下:1funct:2push1%ebp3movl%esp,%ebp4subl$40,%esp5leal-8(%ebp),%eax6movl%eax,8(%esp)7leal-4(%ebp),%eax8movl%eax,4(%esp)9movl$.LC0,(%esp)〃将指向字符串“%x%x”的指针入栈10callscanf〃假定scanf执行后x=15,y=2011movl-4(%ebp),%eax12subl-8(%ebp),%eax13leave14ret假设函数fund开始执行时,R[esp]=0xbc000020,R[ebp]=0xbc000030,执行第10行call指令后,scanf从标准输入读入的值为0x16和0x100,指向字符串“%x%x”的指针为0x804c000o回答下列问题或完成下列任务。(1)执行第3、10和13行的指令后,寄存器EBP中的内容分别是什么?(2)执行第3、10和13行的指令后,寄存器ESP中的内容分别是什么?(3)局部变量x和y所在存储单元的地址分别是什么?(4)画出执行第10行指令后funct的栈帧,指出栈帧中的内容及其地址。参考答案:每次执行pushl指令后,R[esp]=R[esp]-4,因此,第2行指令执行后R[esp]=0xbd)()()01c。(1)执行第3行指令后,R(ebp]=R[esp|=0xbc00001Co到第12条指令执行结束都没有改变EBP的内容,因而执行第10行指令后,EBP的内容还是为OxbcOOOOlc。执行第13行指令后,EBP的内容恢复为进入函数funct时的值0xbc000030.(2)执行第3行指令后,R[esp]=0xbc0()001c((执行第4行指令后R|esp]=R[esp]-40=0xbc00001c-0x28=0xbbfffff4o因而执行第10行指令后,未跳转到scanf函数执行时,ESP中的内容为0xbbfffff4-4=0xbbfffff();在从scanf函数返回后ESP中的内容为0xbbfffff4,执行第13行指令后,ESP的内容恢复为进入函数funct时的旧值,即R|esp]=0xbc000020.

(3)第5、6两行指令将scanf的第三个参数&y入栈,入栈的内容为R[ebp]-8=0xbc000014;第7、8两行指令将scanf的第二个参数&x入栈,入栈的内容为Rlebp]-4=0xbc000018.故x和y所在的地址分别为0xbc000018和0xbi-000014o(4)执行第10行指令后,fund栈帧的地址范围及其内容如下:OxbcOOOOlcOxbcOOOO3O<-EBPOxbcOOOO18x=l50xbdXXX)14y=20OxbcOOOOlO()xbc(XXM)()cOxbcOOOOO80xbc()00004OxbcOOOOOOOxbbfffffc0xbc000014OxbbfffffBOxbc(XXM)l80xbbfffff40x804c000Oxbbfffffl)从scanf返回的地址—ESP栈帧底部.已知递归函数refunc的C语言代码框架如下:intrefunc(unsignedx){if()return;unsignednx =;intrv=refunc(nx);return;}上述递归函数过程体对应的汇编代码如下:1movl8(%ebp),%ebx2movl$0,%eax3testl%ebx,%ebx4je.L25movl%ebx,%eax6shrl$1,%eax7movl%eax,(%esp)8callrefunc9movl%ebx,%edx10andl$1,%edx11leal(%edx,%eax),%eax12.L2:ret根据对应的汇编代码填写C代码中缺失部分,并说明函数的功能。参考答案:第1行汇编指令说明参数x存放在EBX中,根据第4行判断x=0则转.L2,否则继续执行第5〜10行指令。根据第5、6、7行指令可知,入栈参数〃式的计算公式为x»l;根据第9、10、11行指令可知,返回值为(x&l)+rv。由此推断出C缺失部分如下:

intrefunc(unsignedx){if( x==0 )return0 ;unsignednx=x»l;intrv=refunc(nx);return(x&0x1)+rv;)该函数的功能为计算x的各个数位中1的个数。.填写表3.14,说明每个数组的元素大小、整个数组的大小以及第i个元素的地址。表3.14题20用表数组元素大小(B)数组大小(B)起始地址元素i的地址charA[10]&A[0]intB[100]&B(0]short*C[5]&C[0]short♦♦D[6]&D[0]longdoubleE(10)&E(01longdouble*F[10]&F[0]参考答案:在IA-32中,GCC为数据类型加ngdouble型变量分配12字节空间,实际上只占用10个字节。数组元素大小(B)数组大小(B)起始地址元素i的地址charA[10]110&A[0]&A[0]+iintB[100)4400&B[0]&B[0]+4ishort*C[5]420&C[01&C[0]+41short**D[6]424&D[0]&D[0]+4ilongdoulMeE|10]12120&E(01&E|0]+12ilong double*F[10]440&F[0]&F[0]+4i.假设short型数组S的首地址4s和数组下标(索引)变量i(int型)分别存放在寄存器EDX和ECX中,下列给出的表达式的结果存放在EAX或AX中,仿照例子填写表3.15,说明表达式的类型、值和相应的汇编代码。表3.15题21用表参考答案:参考答案:表达式类型值汇编代码sS+iS[i]shortmovw(%edx,%ecx,2),%ax&S[10]&S[i+2]short*A^+2*i+4leal4(%edx,%ecx,2),%eax&S[i]-SS[4*i+4]♦(S+i-2)表达式类型值汇编代码

Sshort*Aleal(%edx),%eaxS+ishort*A,G2*ileal(%edx,%ecx,2),%eaxSR]shortM[As+2*i]movw(%edx,%ecx,2),%ax&S[10]short*A卢20leal20(%edx),%eax&S[i+2]short*45+2*1+4leal4(%edx,%ecx,2),%eax&S[i]£int(A^2*i-As)/2=imovl%ecx,%eaxmovl$i,%eax??S[4*i+4]shortM[A,s+2*(4*i+4)]movw8(%edx,%ecx,8),%ax*(S+i-2)shortM(As+2*(<-2)]movw-4(%edx,%ecx,2),%ax.假设函数sumij的C代码如下,其中,M和N是用#define声明的常数。1inta[M][N],b[N][M];23intsumij(inti,intj){4returna[i][j]+b[j][i];5}已知函数sumij的过程体对应的汇编代码如下:1movl8(%ebp),%ecx2movl12(%ebp),%edx3leal(,%ecx,8),%eax4subl%ecx,%eax5add!%edx,%eax6leal(%edx,%edx,4),%edx7addl%ecx,%edx8movla(9%eax,4),%eax9addlb(,%edx,4),%eax根据上述汇编代码,确定M和N的值。参考答案:根据汇编指令功能可以推断最终在EAX中返回的值为:M[a+28*i+4*j]+M|b+20*j+4*i],因为数组a和b都是int型,每个数组元素占4B,因此,M=5,N=7O(若a和b的每个元素占一个字节,则的地址为a+i*N+j; 的地址为b+j*M+i).假设函数st_ele的C代码如下,其中,L.M和N是用#define声明的常数。inta[L][M][N];intst_ele(inti,intj,intk,int*dst){*dst=a[i][j][k];returnsizeof(a);}已知函数st.ele的过程体对应的汇编代码如下:1movl8(%ebp),%ecx2movl12(%ebp),%edx3leal(%edx,%edx,8),%edx4movl%ecx,%eax5sail$6,%eax6subl%ecx,%eax7addl%eax,%edx8addl16(%ebp),%edx9movla(,%edx,4),%eax10movl20(%ebp),%edx11movl%eax,(%edx)12movl$4536,%eax根据上述汇编代码,确定L、M和N的值。参考答案:执行第11行指令后,aJiHjHk]的地址为a+4*(63*i+9*j+k),所以,可以推断出中间的M=9,N=63/9=7«根据第12行指令,可知数组a的大小为4536字节,故L=4536/(4*L*M)=18。24.假设函数trans_matrix的C代码如下,其中,M是用#define声明的常数。voidtrans_matrix(inta[M][M]){inti,j,t;for(i=0;i<M;i++)for(j=0;j<M;j++){t=a[i][j];a[i]U]=a[j][i];a[j][i]=t;})已知采用优化编译(选项-02)后函数trans_matrix的内循环对应的汇编代码如下:1.L2:2movl(%ebx),%eax3movl(%esi,%ecx,4),%edx4movl%eax,(%esi,%ecx,4)5addl$1,%ecx6movl%edx,(%ebx)7addl$76,%ebx8cmpl%edi,%ecx9.)1.L2根据上述汇编代码,回答下列问题或完成下列任务。M的值是多少?常数M和变量j分别存放在哪个寄存器中?(2)写出上述优化汇编代码对应的函数trans_matrix的C代码。参考答案:(1)常数M=76/4=19,存放在EDI中,变量j存放在ECX中。(2)上述优化汇编代码对应的函数transjnatrix的C代码如下:voidtrans_matrix(inta[M][M]){intLj,t,*p;intc=(M«2);for(i=0;i<M;i++){p=&a[0Hil;for(j=0;j<M;j++){t=*p;*P=a[i][j];a[i]U]=t;+=

1011)121.假设结构类型node的定义、函数npjnit的C代码及其对应的部分汇编代码如下:structnode{int*p;struct{intx;inty;structnode*next;};voidnp_init(structnode*np)np->s.xnp->pstructnode{int*p;struct{intx;inty;structnode*next;};voidnp_init(structnode*np)np->s.xnp->pnp->ncxtmovl8(%ebp),%eaxmovl8(%eax),%edxmovl%edx,4(%eax)leal4(%eax),%edxmovl%edx,(%eax)movl%eax,12(%eax)回答下列问题或完成下列任务。(1)结构node所需存储空间有多少字节?成员小&x、和next的偏移地址分别为多少?(2)根据汇编代码填写np_init中缺失的表达式。参考答案:node所需存储空间需要4+(4+4)+4=16字节。成员p、s.x、s.y和next的偏移地址分别为0、4、8和12.npjnit中缺失的表达式如下:voidnpjnit(structnode*np){np->s.x二n|»s・y;np->p=&(np->s.x) ;np->next=np;}.假设联合类型utype的定义如下:typedefunion{struct{intx;shorty;shortz;}slstruct{shorta[2];int b;char *p;}s2}utype;若存在具有如下形式的一组函数:viodgetvalue(utype*uptr,TYPE*dst){*dst=EXPR;)该组函数用于计算不同表达式EXPR的值,返回值的数据类型根据表达式的类型确定。假设函数getvalue的入口参数uptr和dst分别被装入寄存器EAX和EDX中,仿照例子填写下表,说明在不同的表达式下的TYPE类型以及表达式对应的汇编指令序列(要求尽量只用EAX和EDX,不够用时再使用ECX)。表达式EXPRTYPE类型汇编指令序列uptr->sl.xintmovl(%eax),%eax

movi%eax,(%edx)uptr->sl.y&uptr>>sl.zuptr->s2.auptr->s2.a[uptr->s2.b]*uptr->s2.p参考答案:表达式EXPRTYPE类型汇编指令序列uptr->sl.xintmovi(%eax),%eaxmovi%eax,(%edx)uptr->sl.yshortmovw4(%eax),%axmovw%ax,(%edx)&uptr->sl.zshort*leal6(%eax),%eaxmovw%eax,(%edx)uptr->s2.ashort*movi%eax,(%edx)uptr->s2.a[uptr->s2.b]shortmovi4(%eax),%ecxmovi(%eax,%ecx,2),%eaxmovi%eax,(%edx)*uptr->s2.pcharmovi8(%eax),%eaxmovb(%eax),%almovb%al,(%edx).给出下列各个结构类型中每个成员的偏移量、结构总大小以及在IA-32/Linux下结构起始位置的对齐要求。(1)(2)(1)(2)(3)(4)(5)(6)structS2{inti;shorts;chare;chard;};structS3{charc;shorts;inti;chard;};structS4{shorts[3];charc;};structS5{charc[3];short*s;inti;chard;doublee;};structS6{structSIc[3];structS2*s;chard;};参考答案:(1)SI:scid02 48总共12字节,按4字节边界对齐(2)S2:scd04 67总共8字节,按4字节边界对齐(3)S3:csid02 48总共12字节,按4字节边界对齐(4)S4:sc06总共8字节,按2字节边界对齐(5)S5:cside04 81216总共24字节,按4字节边界对齐(6)S6:csd03640总共44字节,按4字节边界对齐(Linux下double型按4字节对齐).以下是结构test的声明:struct{chardoubleintshort

TOC\o"1-5"\h\zchar *p;long 1;longlongg;void *v;}test;假设在Windows平台上编译,则这个结构中每个成员的偏移量是多少?结构总大小为多少字节?如何调整成员的先后顺序使得结构所占空间最小?参考答案:Windows平台要求不同的基本类型按照其数据长度进行对齐。每个成员的偏移量如下:c d i s p 1 g v0 8 16 20 24 28 32 40结构总大小为48字节,因为其中的d和g必须是按8字节边界对齐,所以,必须在末尾再加上4个字节,即44+4=48字节。变量长度按照从大到小顺序排列,可以使得结构所占空间最小,因此调整顺序后的结构定义如下:struct{d;g:i;*I;*v;doublelonglongintcharlongvoidshortchard;g:i;*I;*v;0 8 16 20 24 283234结构总大小为34+6=40字节。.以下是函数甥tline存在漏洞和问题的C语言代码实现,右边是其对应的反汇编部分结果:char*getline()(120804840c<getline>:push%ebp804840c:55charbuf|8J;3804840d:89e5mov%esp,%ebpchar*result;4804840f:83ec28sub$0x28,%esp58048412:895df4mov%ebx,-Oxc(%ebp)68048415:8975f8mov%esi,-0x8(%ebp)result=malloc(strlen(buf));78048418:897dfcmov%edi,-0x4(%ebp)strcpy(result,buf);8804841b:8d75eclea-0xl4(%ebp),%esireturnresult;980484le:893424mov%esi,(%esp))108048421:e8a3ffffffcall80483c9<gets>假定有一个调用过程P调用了函数getline,其返回地址为0x80485c8,为调用getline函数而执行完call指令时,部分寄存器的内容如下:R[ebp]=0xbffc0800,R[esp]=0xbffc07f0,R[ebx]=0x5,R[esi]=0xl0,R[edi]=0x8.执行程序时从标准输入读入的一行字符串为“0123456789ABCDEF0123456789A”,此时,程序会发生段错误(segmentationfault)并中止执行,经调试确认错误是在执行getline的ret指令时发生的。回答下列问题或完成下列任务。(1)分别画出执行第7行和第10行汇编指令后栈中的信息存放情况。要求给出存储地址和存储内容,并指出存储内容的含义(如返回地址、EBX旧值、局部变量、入口参数等)。(2)当执行到getline的旧指令时,假如程序不发生段错误,则正确的返回地址是什么?发生段错误是因

为执行getline的何指令时得到了什么样的返回地址?(3)执行完第10行汇编指令后,哪些寄存器的内容已被破坏?(4)除了可能发生缓冲区溢出以外,getline的C代码还有哪些错误?参考答案:(1)执行第7行和第10行指令后栈中信息存放情况如下图所示。其中gets函数的入口参数为buf数组首地址,应等于getline函数的栈帧底部指针EBP的内容减0x14,而getline函数的栈帧底部指针EBP的内容应等于执行完getline中第2行指令(push%ebp)后ESP的内容,此时,R[esp]==0xbffc07f0-4=0xbffc07cc,故buf数组首地址为R[ebp]-0xl4=R[esp]-0x14=0xbffc07e<rOx14=0xbffc07d8.080485c8080485c8返回P的地址EBP-►bffc0800EBP在P中旧值00000008]被调用者保00000010*存寄存器在00000005JP中的旧值buf[7]-buf[4]ESP—>Ibuf⑶〜buflO]a)执行第7行后的栈08413938返回p的地址EBP—>37363534EBP在P中旧值33323130被调用者保46454443标存寄存器在42413938JP中的旧值37363534buf[7]-buf[4]33323130buf[3卜buf[O]ESP-►bffc07d8gets入口参数b)执行第10行后的栈(2)当执行到getline的ret指令时,假如程序不发生段错误,则正确的返回地址应该是0x80485c8,发生段错误是因为执行getline的mt指令时得到的返回地址为0x8413938,这个地址所在存储段可能是不可执行的数据段,因而发生了段错误(segmentationfault)。(3)执行完第10行汇编指令后,被调用者保存寄存器EBX、ESI和EDI在P中的内容已被破坏,同时还破坏了EBP在P中的内容。getline的C代码中malloc函数的参数应该为strlen(buf)+l,此外,应该检查malloc函数的返回值是否为NULL..假定函数abc的入口参数有a、b和c,每个参数都可能是带符号整数类型或无符号整数类型,而且它们的长度也可能不同。该函数具有如下过程体:*b+=c;*a+=*b;在x8&64机器上编译后的汇编代码如下:abc:addl (%rdx),%edimovl %edi,(%rdx)movslq %edi,%rdiaddq %rdi,(%rsi)ret分析上述汇编代码,以确定三个入口参数的顺序和可能的数据类型,写出函数abc可能的4种合理的函数原型。参考答案:X86-64过程调用时参数传递是通过通用寄存器进行的,前三个参数所用寄存器顺序为RDLRSI、RDX.abc的4种合理的函数原型为:viodabc(intc,long*a,int*b);viodabc(unsignedc,longint*b);(3)viodabc(longc,long*a,int*b);④viodabc(unsignedlongc,long*a,int*b);根据第3、4行指令可知,参数b肯定指向一个32位带符号整数类型;根据第5行指令可知,参数a指向64位带符号整数类型;而参数c可以是32位,也可以是64位,因为*b为32位,所以取RDI中的低32位R[cdi](截断为32位),再和*b相加。同时,参数c可以是带符号整数类型,也可以是无符号整数类型,因为第2行加法指令addl的执行结果对于带符号整数和无符号整数都一样。31.函数Iproc的过程体对应的汇编代码如下:movl 8(%ebp),%edxmovl 12(%ebp),%ecxmovl $255,%esimovl $-2147483648,%edi.L3:movl %edi,%eaxandl %edx,%eaxxorl %eax,%esimovl %ecx,%ebxshrl %bl,%editestl %edi,%edijne .L3movl %esi,%eax上述代码根据以下Iproc函数的C代码编译生成:intlproc(intx,intk)(intval=;inti;for(i=;1;i=){valA=;}returnval;}回答下列问题或完成下列任务。(1)给每条汇编指令添加注释。(2)参数x和A分别存放在哪个寄存器中?局部变量叩/和i分别存放在哪个寄存器中?(3)局部变量m/和i的初始值分别是什么?(4)循环终止条件是什么?循环控制变量i是如何被修改的?(5)填写C代码中的缺失部分。参考答案:(1)汇编指令注释如下:1movl8(%ebp),%edx//R[edx|<-M[R[ebp]+8],将x送EDX2movl12(%ebp),%ecx〃R[ecx]—M(R[ebp]+12],将A送ECX3movl$255,%esi〃R[esi]-255,将255送ESI4movl$-2147483648,%edi〃R[edi]--2147483648,将0x80000000送EDI5.L3:6movl%edi,%eax//R[eaxl«-R[edi],将i送EAX7andl%edx,%eax//R[eax|<—R[eax]andR|edx],将iandx送EAX8xorl%eax,%esi//R[esi|<—R[esi]xorR[eax]>将valxor(iandx)送ESI9movl%ecx,%ebx//R[ebx|«-R[ecx],将A送ECX10shrl%bl,%edi〃R[edi]—R[edi]»R[bl],将i逻辑右移A位送EDI11testl%edi,%edi12jne.L3庙R[edi]#0,则转.L313movl%esi,%eax〃R[eax]—R[esi]x和A分别存放在EDX和ECX中。局部变量和i分别存放在ESI和EDI中。(3)局部变量和i的初始值分别是255和-2147483648。(4)循环终止条件为i等于0.循环控制变量i每次循环被逻辑右移A位。C代码中缺失部分填空如

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论