《计算机系统第三章答案》由会员分享,可在线阅读,更多相关《计算机系统第三章答案(9页珍藏版)》请在金锄头文库上搜索。
1、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
2、)源操作数寄存器与目操作数寄存器长度不一致(7)不存在 ESX 寄存器(8)源操作数地址中缺少变址寄存器5参考答案:表表 题题 5 5 用表用表src_typecharintintshortunsigned charcharintdst_typeintcharunsignedintunsignedunsignedint机器级表示movsbl %al, (%edx)movb %al, (%edx)movl %eax, (%edx)movswl %ax, (%edx)movzbl %al, (%edx)movsbl %al, (%edx)movl %eax, (%edx)6参考答案:(1)xptr
3、、yptr 和 zptr 对应实参所存放的存储单元地址分别为:Rebp+8、Rebp+12、Rebp+16。(2)函数 func 的 C 语言代码如下: void func(int *xptr, int *yptr, int *zptr)int tempx=*xptr;int tempy=*yptr;int tempz=*zptr;*yptr=tempx;*zptr = tempy;*xptr = tempz;7参考答案:(1)Redx=x(2)Redx=x+y+4(3)Redx=x+8*y(4)Redx=y+2*x+12(5)Redx=4*y(6)Redx=x+y8参考答案:(1)指令功能为
4、:RedxRedx+MReax=0x00000080+M0x8049300,寄存器 EDX 中内容改变。改变后的内容为以下运算的结果:00000080H+FFFFFFF0H0000 0000 0000 0000 0000 0000 1000 0000+ 1111 1111 1111 1111 1111 1111 1111 00001 0000 0000 0000 0000 0000 0000 0111 0000因此,EDX 中的内容改变为 0x00000070。根据表可知, 加法指令会影响 OF、SF、ZF 和 CF 标志。OF=0,ZF=0,SF=0,CF=1。(2)指令功能为:RecxRe
5、cx-MReax+Rebx=0x00000010+M0x8049400, 寄存器 ECX 中内容改变。改变后的内容为以下运算的结果:00000010H-H0000 0000 0000 0000 0000 0000 0001 0000+ 0111 1111 1111 1111 1111 1111 1111 10000 1000 0000 0000 0000 0000 0000 0000 1000因此,ECX 中的内容改为 0x。根据表可知,减法指令会影响 OF、SF、ZF 和 CF 标志。OF=1,ZF=0,SF=1,CF=10=1。(3)指令功能为:RbxRbx or MReax+Recx*8
6、+4,寄存器 BX 中内容改变。改变后的内容为以下运算的结果:0x0100 or M0x8049384=0100H or FF00H0000 0001 0000 0000o1111 1111 0000 0000 1111 1111 0000 0000因此,BX 中的内容改为 0xFF00。由节可知,OR 指令执行后 OF=CF=0;因为结果不为0,故 ZF=0;因为最高位为 1,故 SF=1。(4)test 指令不改变任何通用寄存器,但根据以下“与”操作改变标志:Rdl and 0x801000 0000and 1000 0000 1000 0000由节可知,TEST 指令执行后 OF=CF=
7、0;因为结果不为 0,故 ZF=0;因为最高位为 1,故 SF=1。(5)指令功能为:MReax+RedxMReax+Redx*32,即存储单元 0x8049380 中的内容改变为以下运算的结果:M0x8049380*32=0x908f12a8*32,也即只要将 0x908f12a8 左移 5 位即可得到结果。 1001 0000 1000 1111 0001 0010 1010 10005=0001 0001 1110 0010 0101 0101 0000 0000因此,指令执行后,单元0x8049380 中的内容改变为 0x11e25500。显然,这个结果是溢出的。但是,根据表可知,乘法
8、指令不影响标志位,也即并不会使OF=1。(6)指令功能为:Rcx Rcx-1,即 CX 寄存器的内容减一。0000 0000 0001 0000+1111 1111 1111 11111 0000 0000 0000 1111因此,指令执行后 CX 中的内容从 0x0010 变为 0x000F。由表可知,DEC 指令会影响 OF、ZF、SF,根据上述运算结果,得到 OF=0,ZF=0,SF=0。9参考答案:movl12(%ebp), %ecx11 执行5 testb $0x80, %dl 11 执行7 addb %dl, (%eax)1:因为 C 语言 if 语句中的条件表达式可以对多个条件进
9、行逻辑运算,而汇编代码中一条指令只能进行一种逻辑运算,并且在每条逻辑运算指令生成的标志都是存放在同一个EFLAGS 寄存器中,所以,最好在一条逻辑指令后跟一条条件转移指令,把EFLAGS 中标志用完,然后再执行另一次逻辑判断并根据条件进行转移的操作。(2)按照书中图给出的“if () goto ”语句形式写出汇编代码对应的C 语言代码如下:1 void comp(char x, int *p)2 3 if (p!=0)4 if (x0)5*p += x;6 13参考答案:1 int func(int x, int y)2 3int z = x*y ;4if ( xx )6z = x+y ;7e
10、lse8z = x-y ;9 else if (x=16 )10 z =x &y ;11return z;12 14参考答案:(1)每个入口参数都要按4 字节边界对齐,因此,参数x、y和k入栈时都占 4 个字节。1 movw8(%ebp), %bx1:5 movw %si, %dx2213 cmpw %cx, %si1115 .L2:16 movswl %bx, %eax & 0x1,因此 f1 用于检测 x 的奇偶性,当 x 中有奇数个 1,则返回为 1,否则返回 0。16参考答案:函数 sw 只有一个入口参数x,根据汇编代码的第25 行指令知,当x+37 时转标号.L7 处执行,否则,按照
11、跳转表中的地址转移执行,x与跳转目标处标号的关系如下:x+3=0:.L7x+3=1:.L2 x+3=2:.L2x+3=3:.L3x+3=4:.L4x+3=5:.L5x+3=6:.L7x+3=7:.L6由此可知,switch (x) 中省略的处理部分结构如下:case -2:case -1:2 标号处指令序列对应的语句break;case 0:3 标号处指令序列对应的语句break;case 1:.4 标号处指令序列对应的语句break;case 2:5 标号处指令序列对应的语句 break;case 4:6 标号处指令序列对应的语句break;default:7 标号处指令序列对应的语句17参
12、考答案:根据第 2、3 行指令可知,参数a 是 char 型,参数p 是指向 short 型变量的指针;根据第4、5 行指令可知,参数 b 和 c 都是 unsigned short 型,根据第 6 行指令可知,test 的返回参数类型为 unsigned int。因此,test的原型为: unsigned int test(char a, unsigned short b, unsigned short c, short *p);18参考答案:每次执行 pushl 指令后,Resp=Resp-4,因此,第 2 行指令执行后 Resp=0xbc00001c。(1)执行第 3 行指令后,Rebp
13、=Resp=0xbc00001c。到第 12 条指令执行结束都没有改变 EBP 的内容,因而执行第 10 行指令后, EBP 的内容还是为0xbc00001c。 执行第 13 行指令后, EBP 的内容恢复为进入函数funct时的值 0xbc000030。( 2 ) 执 行 第3行 指 令 后 , Resp=0xbc00001c 。 执 行 第4行 指 令 后Resp=Resp-40=0xbc00001c-0x28=0xbbfffff4。因而执行第 10 行指令后,未跳转到 scanf 函数执行时,ESP中的内容为 0xbbfffff4-4=0xbbfffff0;在从 scanf 函数返回后
14、ESP 中的内容为 0xbbfffff4。执行第 13行指令后,ESP 的内容恢复为进入函数 funct 时的旧值,即 Resp=0xbc000020。(3)第5、6 两行指令将 scanf 的第三个参数&y 入栈,入栈的内容为Rebp-8=0xbc000014;第7、8 两行指令将 scanf 的第二个参数&x 入栈,入栈的内容为 Rebp-4=0xbc000018。故 x 和 y 所在的地址分别为0xbc000018 和 0xbc000014。(4)执行第 10 行指令后,funct 栈帧的地址范围及其内容如下:0xbc00001c0xbc0000180xbc0000140xbc00001
15、00xbc00000c0xbc0000080xbc0000040xbc0000000xbbfffff0xbbfffff0xbbfffff0xbbfffff0xbc0000140xbc0000180x804c000从 scanf 返回的地ESP0xbc000030x=15EBP栈帧底部y=2019参考答案:第 1 行汇编指令说明参数x存放在 EBX 中,根据第 4 行判断x=0 则转.L2,否则继续执行第 510 行指令。根据第 5、6、7 行指令可知,入栈参数nx的计算公式为x1;根据第 9、10、11 行指令可知,返回值为(x&1)+rv。由此推断出 C 缺失部分如下:1int refunc
16、(unsigned x) 2if ( x=0 )3return 0 ;4unsigned nx = x1 ;5int rv = refunc(nx) ;6return (x & 0x1) + rv; 7该函数的功能为计算x的各个数位中 1 的个数。20参考答案:在 IA-32 中,GCC 为数据类型 long double 型变量分配 12 字节空间,实际上只占用10 个字节。数组char A10int B100shortshortlongE10long*F10double440&F0&F0+4i *C5 *D6double元素大小(B)数组大小(B)144412104002024120起始地
17、址&A0&B0&C0&D0&E0元素i的地址&A0+i&B0+4i&C0+4i&D0+4i&E0+12i21参考答案:表达式SS+iSi&S10类型short *short *shortshort *值汇编代码leal (%edx), %eaxleal (%edx, %ecx, 2), %eaxmovw (%edx, %ecx, 2), %axleal 20(%edx), %eaxASAS+2*iMAS+2*iAS+20&Si+2&Si-SS4*i+4*(S+i-2)short *intshortshortAS+2*i+4(AS+2*i-As)/2=iMAS+2*(4*i+4)MAS+2*(i
18、-2)leal 4(%edx, %ecx, 2), %eaxmovl %ecx, %eaxmovw 8(%edx, %ecx, 8), %axmovw -4(%edx, %ecx, 2), %ax22参考答案:根据汇编指令功能可以推断最终在EAX 中返回的值为:Ma+28*i+4*j+Mb+20*j+4*i,因为数组 a 和 b 都是 int 型,每个数组元素占 4B,因此,M=5, N=7。23参考答案:执行第 11 行指令后,aijk的地址为 a+4*(63*i+9*j+k),所以,可以推断出M=9,N=63/9=7。根据第12 行指令,可知数组 a 的大小为 4536 字节,故 L=45
19、36/(4*L*M)=18。24参考答案:(1)常数 M=76/4=19,存放在 EDI 中,变量j存放在 ECX 中。(2)上述优化汇编代码对应的函数trans_matrix 的 C 代码如下:1void trans_matrix(int aMM) 2int i, j, t, *p;3int c=(M2);3for (i = 0; i M; i+) 4p=&a0i;5for (j = 0; j = np- ;np-p = &(np- ;np-next= np ;26参考答案:表达式 EXPRuptr-uptr-&uptr-uptr-uptr-uptr-TYPE 类型intshortshort
20、 *short *short汇编指令序列movl (%eax), %eaxmovl %eax, (%edx)movw 4(%eax), %axmovw %ax, (%edx)leal 6(%eax), %eaxmovw %eax, (%edx)movl %eax, (%edx)movl 4(%eax), %ecxmovl (%eax, %ecx, 2), %eax*uptr-charmovl %eax, (%edx)movl 8(%eax), %eaxmovb (%eax), %almovb %al, (%edx)27参考答案:(1)S1: s cid 0248总共 12 字节,按 4 字节边
21、界对齐(2)S2: i scd 0467总共 8 字节,按 4 字节边界对齐(3)S3: c sid 0248总共 12 字节,按 4 字节边界对齐(4)S4: s c 06总共 8 字节,按 2 字节边界对齐(5)S5: c side 04812 16总共 24 字节,按 4 字节边界对齐(Linux 下 double 型按 4 字节对齐)(6)S6: c sd 036 40总共 44 字节,按 4 字节边界对齐28参考答案:Windows 平台要求不同的基本类型按照其数据长度进行对齐。每个成员的偏移量如下:c d i s p l g v0 816 20 24 2832 40结构总大小为 4
22、8 字节,因为其中的 d 和 g 必须是按 8 字节边界对齐,所以,必须在末尾再加上4 个字节,即 44+4=48 字节。变量长度按照从大到小顺序排列,可以使得结构所占空间最小,因此调整顺序后的结构定义如下:struct doubled;long longg;inti;char*p;longl;void*v;shorts;charc; test;d g i p l v s c0 816 20 24 2832 34结构总大小为 34+6=40 字节。29参考答案:(1)执行第 7 行和第 10 行指令后栈中的信息存放情况如下图所示。其中gets 函数的入口参数为 buf 数组首地址,应等于 ge
23、tline 函数的栈帧底部指针 EBP 的内容减 0x14,而 getline 函数的栈帧底部指针 EBP的内容应等于执行完 getline 中第 2 行指令(push %ebp)后 ESP 的内容,此时, Resp=0xbffc07f0-4=0xbffc07ec,故buf数组首地址为Rebp-0x14=Resp-0x14=0xbffc07ec-0x14=0xbffc07d8 。EBP08 04 85 c8返回 P 的地址bf fc 08 00 EBP 在 P 中旧值00 00 00 0800 00 00 1000 00 00 05被调用者保存寄存器在P 中的旧值buf7buf4buf3buf
24、0EBP08 41 39 38返回 P 的地址37 36 35 34 EBP 在 P 中旧值被调用者保46 45 44 43存寄存器在42 41 39 38P 中的旧值37 36 35 34 buf733 32 31 30buf4buf3buf033 32 31 30ESPa) 执行第 7 行后的栈ESPbf fc 07 d8 gets 入口参数b) 执行第 10 行后的栈(2)当执行到 getline 的 ret 指令时,假如程序不发生段错误,则正确的返回地址应该是 0x80485c8,发生段错误是因为执行 getline 的 ret 指令时得到的返回地址为 0x8413938,这个地址所在
25、存储段可能是不可执行的数据段,因而发生了段错误(segmentation fault)。(3)执行完第 10 行汇编指令后,被调用者保存寄存器EBX、ESI 和 EDI 在 P 中的内容已被破坏,同时还破坏了 EBP 在 P 中的内容。(4)getline 的 C 代码中 malloc 函数的参数应该为strlen(buf)+1,此外,应该检查malloc 函数的返回值是否为 NULL。30参考答案: x86-64 过程调用时参数传递是通过通用寄存器进行的,前三个参数所用寄存器顺序为RDI、RSI、RDX。abc 的 4 种合理的函数原型为: viod abc(int c, long *a,
26、int *b); viod abc(unsigned c, long *a, int *b); viod abc(long c, long *a, int *b); viod abc(unsigned long c, long *a, int *b);根据第 3、4 行指令可知,参数 b 肯定指向一个 32 位带符号整数类型;根据第 5 行指令可知,参数 a 指向64 位带符号整数类型;而参数c 可以是 32 位,也可以是64 位,因为*b 为 32 位,所以取RDI 中的低 32 位Redi(截断为 32 位),再和*b 相加。同时,参数c 可以是带符号整数类型,也可以是无符号整数类型,因为
27、第 2 行加法指令 addl 的执行结果对于带符号整数和无符号整数都一样。31参考答案:(1)汇编指令注释如下:1movl8(%ebp), %edx3:6movl%edi, %eax3313movl%esi, %eaxnext-n1. ptr ) uptr-n2. data2 ;34参考答案:(1)函数 trace 的入口参数 tptr 通过 RDI 寄存器传递。(2)函数 trace 完整的 C 语言代码如下:long trace( tree_ptr tptr)long ret_val=0; tree_ptr p=tptr;while (p!=0) ret_val=p-val;p=p-left;return ret_val;(3)函数 trace 的功能是:返回二叉树中最左边叶子节点中的值val。