计算机系统第三章答案教学提纲.docx
《计算机系统第三章答案教学提纲.docx》由会员分享,可在线阅读,更多相关《计算机系统第三章答案教学提纲.docx(22页珍藏版)》请在冰豆网上搜索。
计算机系统第三章答案教学提纲
计算机系统第三章答案
习题
3.参考答案:
(1)后缀:
w,源:
基址+比例变址+偏移,目:
寄存器
(2)后缀:
b,源:
寄存器,目:
基址+偏移
(3)后缀:
l,源:
比例变址,目:
寄存器
(4)后缀:
b,源:
基址,目:
寄存器
(5)后缀:
l,源:
立即数,目:
栈
(6)后缀:
l,源:
立即数,目:
寄存器
(7)后缀:
w,源:
寄存器,目:
寄存器
(8)后缀:
l,源:
基址+变址+偏移,目:
寄存器
4.参考答案:
(1)源操作数是立即数0xFF,需在前面加‘$’
(2)源操作数是16位,而长度后缀是字节‘b’,不一致
(3)目的操作数不能是立即数寻址
(4)操作数位数超过16位,而长度后缀为16位的‘w’
(5)不能用8位寄存器作为目的操作数地址所在寄存器
(6)源操作数寄存器与目操作数寄存器长度不一致
(7)不存在ESX寄存器
(8)源操作数地址中缺少变址寄存器
5.参考答案:
表3.12题5用表
src_type
dst_type
机器级表示
char
int
movsbl%al,(%edx)
int
char
movb%al,(%edx)
int
unsigned
movl%eax,(%edx)
short
int
movswl%ax,(%edx)
unsignedchar
unsigned
movzbl%al,(%edx)
char
unsigned
movsbl%al,(%edx)
int
int
movl%eax,(%edx)
6.参考答案:
(1)xptr、yptr和zptr对应实参所存放的存储单元地址分别为:
R[ebp]+8、R[ebp]+12、
R[ebp]+16。
(2)函数func的C语言代码如下:
voidfunc(int*xptr,int*yptr,int*zptr)
{
inttempx=*xptr;
inttempy=*yptr;
inttempz=*zptr;
*yptr=tempx;
*zptr=tempy;
*xptr=tempz;
}
7.参考答案:
(1)R[edx]=x
(2)R[edx]=x+y+4
(3)R[edx]=x+8*y
(4)R[edx]=y+2*x+12
(5)R[edx]=4*y
(6)R[edx]=x+y
8.参考答案:
(1)指令功能为:
R[edx]←R[edx]+M[R[eax]]=0x00000080+M[0x8049300],寄存器EDX中内容改变。
改变后的内容为以下运算的结果:
00000080H+FFFFFFF0H
因此,EDX中的内容改变为0x00000070。
根据表3.5可知,加法指令会影响OF、SF、ZF和CF标志。
OF=0,ZF=0,SF=0,CF=1。
(2)指令功能为:
R[ecx]←R[ecx]-M[R[eax]+R[ebx]]=0x00000010+M[0x8049400],寄存器ECX中内容改变。
改变后的内容为以下运算的结果:
00000010H-80000008H
因此,ECX中的内容改为0x80000008。
根据表3.5可知,减法指令会影响OF、SF、ZF和CF标志。
OF=1,ZF=0,SF=1,CF=1⊕0=1。
(3)指令功能为:
R[bx]←R[bx]orM[R[eax]+R[ecx]*8+4],寄存器BX中内容改变。
改变后的内容为以下运算的结果:
0x0100orM[0x8049384]=0100HorFF00H
因此,BX中的内容改为0xFF00。
由3.3.3节可知,OR指令执行后OF=CF=0;因为结果不为0,故ZF=0;因为最高位为1,故SF=1。
(4)test指令不改变任何通用寄存器,但根据以下“与”操作改变标志:
R[dl]and0x80
10000000
10000000
10000000
andd
由3.3.3节可知,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=0x908f12a8*32,也即只要将0x908f12a8左移5位即可得到结果。
10010000100011110001001010101000<<5
=00010001111000100101010100000000
因此,指令执行后,单元0x8049380中的内容改变为0x11e25500。
显然,这个结果是溢出的。
但是,根据表3.5可知,乘法指令不影响标志位,也即并不会使OF=1。
(6)指令功能为:
R[cx]←R[cx]-1,即CX寄存器的内容减一。
0000000000010000
1111111111111111
10000000000001111
+
因此,指令执行后CX中的内容从0x0010变为0x000F。
由表3.5可知,DEC指令会影响OF、ZF、SF,根据上述运算结果,得到OF=0,ZF=0,SF=0。
9.参考答案:
movl12(%ebp),%ecx//R[ecx]←M[R[ebp]+12],将y送ECX
sall$8,%ecx//R[ecx]←R[ecx]<<8,将y*256送ECX
movl8(%ebp),%eax//R[eax]←M[R[ebp]+8],将x送EAX
movl20(%ebp),%edx//R[edx]←M[R[ebp]+20],将k送EDX
imull%edx,%eax//R[eax]←R[eax]*R[edx],将x*k送EAX
movl16(%ebp),%edx//R[edx]←M[R[ebp]+16],将z送EDX
andl$65520,%edx//R[edx]←R[edx]and65520,将z&0xFFF0送EDX
addl%ecx,%edx//R[edx]←R[edx]+R[ecx],将z&0xFFF0+y*256送EDX
subl%edx,%eax//R[eax]←R[eax]-R[edx],将x*k-(z&0xFFF0+y*256)送EAX
根据以上分析可知,第3行缺失部分为:
3intv=x*k-(z&0xFFF0+y*256);
10.参考答案:
从汇编代码的第2行和第4行看,y应该是占8个字节,R[ebp]+20开始的4个字节为高32位字节,记为yh;R[ebp]+16开始的4个字节为低32位字节,记为yl。
根据第4行为无符号数乘法指令,得知y的数据类型num_type为unsignedlonglong。
movl12(%ebp),%eax//R[eax]←M[R[ebp]+12],将x送EAX
movl20(%ebp),%ecx//R[ecx]←M[R[ebp]+20],将yh送ECX
imull%eax,%ecx//R[ecx]←R[ecx]*R[eax],将yh*x的低32位送ECX
mull16(%ebp)//R[edx]R[eax]←M[R[ebp]+16]*R[eax],将yl*x送EDX-EAX
leal(%ecx,%edx),%edx
//R[edx]←R[ecx]+R[edx],将yl*x的高32位与yh*x的低32位相加后送EDX
movl8(%ebp),%ecx//R[ecx]←M[R[ebp]+8],将d送ECX
movl%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.参考答案:
根据第3.3.4节得知,条件转移指令都采用相对转移方式在段内直接转移,即条件转移指令的转移目标地址为:
(PC)+偏移量。
(1)因为je指令的操作码为01110100,所以机器代码7408H中的08H是偏移量,故转移目标地址为:
0x804838c+2+0x8=0x8048396。
call指令中的转移目标地址0x80483b1=0x804838e+5+0x1e,由此,可以看出,call指令机器代码中后面的4个字节是偏移量,因IA-32采用小端方式,故偏移量为0000001EH。
call指令机器代码共占5个字节,因此,下条指令的地址为当前指令地址0x804838e加5。
(2)jb指令中F6H是偏移量,故其转移目标地址为:
0x8048390+2+0xf6=0x8048488。
movl指令的机器代码有10个字节,前两个字节是操作码等,后面8个字节为两个立即数,因为是小端方式,所以,第一个立即数为0804A800H,即汇编指令中的目的地址0x804a800,最后4个字节为立即数00000001H,即汇编指令中的常数0x1。
(3)jle指令中的7EH为操作码,16H为偏移量,其汇编形式中的0x80492e0是转移目的地址,因此,假定后面的mov指令的地址为x,则x满足以下公式:
0x80492e0=x+0x16,故x=0x80492e0-0x16=0x80492ca。
(4)jmp指令中的E9H为操作码,后面4个字节为偏移量,因为是小端方式,故偏移量为FFFFFF00H,即-100H=-256。
后面的sub指令的地址为0x804829b,故jmp指令的转移目标地址为0x804829b+0xffffff00=0x804829b-0x100=0x804819b。
12.参考答案:
(1)汇编指令的注解说明如下:
1movb8(%ebp),%dl//R[dl]←M[R[ebp]+8],将x送DL
2movl12(%ebp),%eax//R[eax]←M[R[ebp]+12],将p送EAX
3testl%eax,%eax//R[eax]andR[eax],判断p是否为0
4je.L1//若p为0,则转.L1执行
5testb$0x80,%dl//R[dl]and80H,判断x的第一位是否为0
6je.L1//若x>=0,则转.L1执行
7addb%dl,(%eax)//M[R[eax]]←M[R[eax]]+R[dl],即*p+=x
8.L1:
因为C语言if语句中的条件表达式可以对多个条件进行逻辑运算,而汇编代码中一条指令只能进行一种逻辑运算,并且在每条逻辑运算指令生成的标志都是存放在同一个EFLAGS寄存器中,所以,最好在一条逻辑指令后跟一条条件转移指令,把EFLAGS中标志用完,然后再执行另一次逻辑判断并根据条件进行转移的操作。
(2)按照书中图3.22给出的“if()goto…”语句形式写出汇编代码对应的C语言代码如下:
1voidcomp(charx,int*p)
2{
3if(p!
=0)
4if(x<0)
5*p+=x;
6}
13.参考答案:
1intfunc(intx,inty)
2{
3intz=x*y;
4if(x<=-100){
5if(y>x)
6z=x+y;
7else
8z=x-y;
9}elseif(x>=16)
10z=x&y;
11returnz;
12}
14.参考答案:
(1)每个入口参数都要按4字节边界对齐,因此,参数x、y和k入栈时都占4个字节。
1movw8(%ebp),%bx//R[bx]←M[R[ebp]+8],将x送BX
2movw12(%ebp),%si//R[si]←M[R[ebp]+12],将y送SI
3movw16(%ebp),%cx//R[cx]←M[R[ebp]+16],将k送CX
4.L1:
5movw%si,%dx//R[dx]←R[si],将y送DX
6movw%dx,%ax//R[ax]←R[dx],将y送AX
7sarw$15,%dx//R[dx]←R[dx]>>15,将y的符号扩展16位送DX
8idiv%cx//R[dx]←R[dx-ax]÷R[cx]的余数,将y%k送DX
//R[ax]←R[dx-ax]÷R[cx]的商,将y/k送AX
9imulw%dx,%bx//R[bx]←R[bx]*R[dx],将x*(y%k)送BX
10decw%cx//R[cx]←R[cx]-1,将k-1送CX
11testw%cx,%cx//R[cx]andR[cx],得OF=CF=0,负数则SF=1,零则ZF=1
12jle.L2//若k小于等于0,则转.L2
13cmpw%cx,%si//R[si]-R[cx],将y与k相减得到各标志
14jg.L1//若y大于k,则转.L1
15.L2:
16movswl%bx,%eax//R[eax]←R[bx],将x*(y%k)送AX
(2)被调用者保存寄存器有BX、SI,调用者保存寄存器有AX、CX和DX。
在该函数过程体前面的准备阶段,被调用者保存的寄存器EBX和ESI必须保存到栈中。
(3)因为执行第8行除法指令前必须先将被除数扩展为32位,而这里是带符号数除法,因此,采用算术右移以扩展16位符号,放在高16位的DX中,低16位在AX中。
15.参考答案:
1intf1(unsignedx)
2{
3inty=0;
4while(x!
=0){
5y^=x;
6x>>=1;
7}
8returny&0x1;
9}
函数f1的功能返回:
(x^x>>1^x>>2^….)&0x1,因此f1用于检测x的奇偶性,当x中有奇数个1,则返回为1,否则返回0。
16.参考答案:
函数sw只有一个入口参数x,根据汇编代码的第2~5行指令知,当x+3>7时转标号.L7处执行,否则,按照跳转表中的地址转移执行,x与跳转目标处标号的关系如下:
x+3=0:
.L7
x+3=1:
.L2
x+3=2:
.L2
x+3=3:
.L3
x+3=4:
.L4
x+3=5:
.L5
x+3=6:
.L7
x+3=7:
.L6
由此可知,switch(x)中省略的处理部分结构如下:
case-2:
case-1:
……//.L2标号处指令序列对应的语句
break;
case0:
……//.L3标号处指令序列对应的语句
break;
case1:
…….//.L4标号处指令序列对应的语句
break;
case2:
……//.L5标号处指令序列对应的语句
break;
case4:
……//.L6标号处指令序列对应的语句
break;
default:
……//.L7标号处指令序列对应的语句
17.参考答案:
根据第2、3行指令可知,参数a是char型,参数p是指向short型变量的指针;根据第4、5行指令可知,参数b和c都是unsignedshort型,根据第6行指令可知,test的返回参数类型为unsignedint。
因此,test的原型为:
unsignedinttest(chara,unsignedshortb,unsignedshortc,short*p);
18.参考答案:
每次执行pushl指令后,R[esp]=R[esp]-4,因此,第2行指令执行后R[esp]=0xbc00001c。
(1)执行第3行指令后,R[ebp]=R[esp]=0xbc00001c。
到第12条指令执行结束都没有改变EBP的内容,因而执行第10行指令后,EBP的内容还是为0xbc00001c。
执行第13行指令后,EBP的内容恢复为进入函数funct时的值0xbc000030。
(2)执行第3行指令后,R[esp]=0xbc00001c。
执行第4行指令后R[esp]=R[esp]-40=0xbc00001c-0x28=0xbbfffff4。
因而执行第10行指令后,未跳转到scanf函数执行时,ESP中的内容为0xbbfffff4-4=0xbbfffff0;在从scanf函数返回后ESP中的内容为0xbbfffff4。
执行第13行指令后,ESP的内容恢复为进入函数funct时的旧值,即R[esp]=0xbc000020。
(3)第5、6两行指令将scanf的第三个参数&y入栈,入栈的内容为R[ebp]-8=0xbc000014;第7、8两行指令将scanf的第二个参数&x入栈,入栈的内容为R[ebp]-4=0xbc000018。
故x和y所在的地址分别为0xbc000018和0xbc000014。
ESP
从scanf返回的地址
0xbc00001c
0xbc000030
y=20
x=15
EBP
0xbc000018
0xbc000014
0xbc000010
0xbc00000c
0xbc000008
0xbc000004
0xbc000000
0xbbfffffc
0xbbfffff8
0xbbfffff4
0xbbfffff0
0xbc000014
0xbc000018
0x804c000
栈帧底部
(4)执行第10行指令后,funct栈帧的地址范围及其内容如下:
19.参考答案:
第1行汇编指令说明参数x存放在EBX中,根据第4行判断x=0则转.L2,否则继续执行第5~10行指令。
根据第5、6、7行指令可知,入栈参数nx的计算公式为x>>1;根据第9、10、11行指令可知,返回值为(x&1)+rv。
由此推断出C缺失部分如下:
1intrefunc(unsignedx){
2if(x==0)
3return0;
4unsignednx=x>>1;
5intrv=refunc(nx);
6return(x&0x1)+rv;
7}
该函数的功能为计算x的各个数位中1的个数。
20.参考答案:
在IA-32中,GCC为数据类型longdouble型变量分配12字节空间,实际上只占用10个字节。
数组
元素大小(B)
数组大小(B)
起始地址
元素i的地址
charA[10]
1
10
&A[0]
&A[0]+i
intB[100]
4
400
&B[0]
&B[0]+4i
short*C[5]
4
20
&C[0]
&C[0]+4i
short**D[6]
4
24
&D[0]
&D[0]+4i
longdoubleE[10]
12
120
&E[0]
&E[0]+12i
longdouble*F[10]
4
40
&F[0]
&F[0]+4i
21.参考答案:
表达式
类型
值
汇编代码
S
short*
AS
leal(%edx),%eax
S+i
short*
AS+2*i
leal(%edx,%ecx,2),%eax
S[i]
short
M[AS+2*i]
movw(%edx,%ecx,2),%ax
&S[10]
short*
AS+20
leal20(%edx),%eax
&S[i+2]
short*
AS+2*i+4
leal4(%edx,%ecx,2),%eax
&S[i]-S
int
(AS+2*i-As)/2=i
movl%ecx,%eax
S[4*i+4]
short
M[AS+2*(4*i+4)]
movw8(%edx,%ecx,8),%ax
*(S+i-2)
short
M[AS+2*(i-2)]
movw-4(%edx,%ecx,2),%ax
22.参考答案:
根据汇编指令功能可以推断最终在EAX中返回的值为:
M[a+28*i+4*j]+M[b+20*j+4*i],因为数组a和b都是int型,每个数组元素占4B,因此,M=5,N=7。
23.参考答案:
执行第11行指令后,a[i][j][k]的地址为a+4*(63*i+9*j+k),所以,可以推断出M=9,N=63/9=7。
根据第12行指令,可知数组a的大小为4536字节,故L=4536/(4*L*M)=18。
24.参考答案:
(1)常数M=76/4=19,存放在EDI中,变量j存放在ECX中。
(2)上述优化汇编代码对应的函数trans_matrix的C代码如下:
1voidtrans_matrix(inta[M][M]){
2inti,j,t,*p;
3intc=(M<<2);
3for(i=0;i4p=&a[0][i];
5for(j=0;j6t=*p;
7*p=a[i][j];
8a[i][j]=t;
9p+=c;
10}
11}
12}
25.参考答案:
(1)node所需存储空间需要4+(4+4)+4=16字节。
成员p、s.x、s.y和next的偏移地址分别为0、4、8和12。
(2)np_init中缺失的表达式如下:
voidnp_init(structnode*np)
{
np->s.x=np->s.y;
np->p=&(np->s.x);
np->next=np;
}
26.参考答案:
表达式EXPR
TYPE类型
汇编指令序列
uptr->s1.x
int
movl(%eax),%eax
movl%eax,(%edx)
uptr->s1.y
short
movw4(%eax),%ax
movw%ax,(%edx)
&uptr->s1.z
short*
leal6(%eax),%eax
movw%eax,(%edx)
uptr->s2.a
short*
movl%eax,(%edx)
uptr->s2.a[uptr->s2.b]
short
movl4(%eax),%ecx
movl(%eax,%ecx,2),%ea