好文档 - 专业文书写作范文服务资料分享网站

计算机系统第三章答案

天下 分享 时间: 加入收藏 我要投稿 点赞

.

……

break; case 1: …….

break; case 2: …… break; case 4: ……

break; default: ……

// .L3标号处指令序列对应的语句

// .L4标号处指令序列对应的语句 // .L5标号处指令序列对应的语句

// .L6标号处指令序列对应的语句

// .L7标号处指令序列对应的语句

17.参考答案: 根据第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指令后,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。

(4)执行第10行指令后,funct栈帧的地址范围及其内容如下:

0xbc00001c 0xbc000018 0xbc000014 0xbc000010 0xbc00000c 0xbc000008 0xbc000004 0xbc000000 0xbbfffffc 0xbbfffff8 0xbbfffff4 0xbbfffff0

0xbc000014 0xbc000018 0x804c000 从scanf返回的地址 ESP 0xbc000030 x=15 EBP 栈帧底部

y=20 19.参考答案:

第1行汇编指令说明参数x存放在EBX中,根据第4行判断x=0则转.L2,否则继续执行第5~10行指令。根据第5、6、7行指令可知,入栈参数nx的计算公式为x>>1;根据第9、10、11行指令可知,返回值为(x&1)+rv。由此

6 / 11

. 推断出C缺失部分如下:

1 2 3 4 5 6

int refunc(unsigned x) { if ( x==0 ) return 0 ; unsigned nx = x>>1 ; int rv = refunc(nx) ; return (x & 0x1) + rv ;

7 }

该函数的功能为计算x的各个数位中1的个数。 20.参考答案:

在IA-32中,GCC为数据类型long double型变量分配12字节空间,实际上只占用10个字节。

数组 char A[10] int B[100] short *C[5] short **D[6] long double E[10] long double *F[10] 元素大小(B) 数组大小(B) 1 4 4 4 12 4 10 400 20 24 120 40 起始地址 &A[0] &B[0] &C[0] &D[0] &E[0] &F[0] 元素i的地址 &A[0]+i &B[0]+4i &C[0]+4i &D[0]+4i &E[0]+12i &F[0]+4i 21.参考答案: 表达式 S S+i S[i] &S[10] &S[i+2] &S[i]-S S[4*i+4] *(S+i-2) 类型 short * short * short short * short * int short short 值 AS AS+2*i M[AS+2*i] AS+20 AS+2*i+4 (AS+2*i-As)/2=i M[AS+2*(4*i+4)] M[AS+2*(i-2)] 汇编代码 leal (íx), êx leal (íx, ìx, 2), êx movw (íx, ìx, 2), %ax leal 20(íx), êx leal 4(íx, ìx, 2), êx movl ìx, êx movw 8(íx, ìx, 8), %ax movw -4(íx, ìx, 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代码如下: 1 void trans_matrix(int a[M][M]) { 2 int i, j, t, *p; 3 int c=(M<<2); 3 for (i = 0; i < M; i++) { 4 p=&a[0][i]; 5 for (j = 0; j < M; j++) {

7 / 11

.

6 t=*p; 7 *p = a[i][j]; 8 a[i][j] = t; 9 p += 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中缺失的表达式如下:

void np_init(struct node *np) { np->s.x = np->s.y ;

np->p = &(np->s.x) ; np->next= np ; }

26.参考答案: 表达式EXPR uptr->s1.x uptr->s1.y &uptr->s1.z uptr->s2.a uptr->s2.a[uptr->s2.b] TYPE类型 int short short * short * short 汇编指令序列 movl (êx), êx movl êx, (íx) movw 4(êx), %ax movw %ax, (íx) leal 6(êx), êx movw êx, (íx) movl êx, (íx) movl 4(êx), ìx movl (êx, ìx, 2), êx movl êx, (íx) movl 8(êx), êx movb (êx), %al movb %al, (íx) *uptr->s2.p char 27.参考答案: (1)S1: s c i d

0 2 4 8 总共12字节,按4字节边界对齐 (2)S2: i s c d

0 4 6 7 总共8字节,按4字节边界对齐 (3)S3: c s i d

0 2 4 8 总共12字节,按4字节边界对齐 (4)S4: s c

0 6 总共8字节,按2字节边界对齐 (5)S5: c s i d e

0 4 8 12 16 总共24字节,按4字节边界对齐(Linux下double型按4字节对齐) (6)S6: c s d

0 36 40 总共44字节,按4字节边界对齐 28.参考答案:

Windows平台要求不同的基本类型按照其数据长度进行对齐。每个成员的偏移量如下:

c d i s p l g v 0 8 16 20 24 28 32 40

8 / 11

. 结构总大小为48字节,因为其中的d和g必须是按8字节边界对齐,所以,必须在末尾再加上4个字节,即44+4=48字节。变量长度按照从大到小顺序排列,可以使得结构所占空间最小,因此调整顺序后的结构定义如下:

double d; long long g; int i; char *p;

long l; void *v;

short s; char c;

} test;

d g i p l v s c

0 8 16 20 24 28 32 34 结构总大小为34+6=40字节。 29.参考答案:

(1)执行第7行和第10行指令后栈中的信息存放情况如下图所示。其中gets函数的入口参数为buf数组首

地址,应等于getline函数的栈帧底部指针EBP的内容减0x14,而getline函数的栈帧底部指针EBP的内容应等于执行完getline中第2行指令(push ?p)后ESP的内容,此时,R[esp]= =0xbffc07f0-4=0xbffc07ec,故buf数组首地址为R[ebp]-0x14= R[esp]-0x14=0xbffc07ec-0x14=0xbffc07d8。

08 04 85 c8 返回P的地址

bf fc 08 00 EBP在P中旧值 00 00 00 08 00 00 00 10 00 00 00 05 被调用者保存寄存器在P中的旧值 buf[7]~ buf[4] buf[3]~ buf[0]

08 41 39 38 返回P的地址 37 36 35 34 EBP在P中旧值 33 32 31 30 46 45 44 43 42 41 39 38 37 36 35 34 buf[7]~ buf[4] 33 32 31 30 buf[3]~ buf[0]

被调用者保存寄存器在P中的旧值

struct {

EBP EBP ESP a) 执行第7行后的栈

ESP bf fc 07 d8 gets入口参数

b) 执行第10行后的栈

(2)当执行到getline的ret指令时,假如程序不发生段错误,则正确的返回地址应该是0x80485c8,发生段

错误是因为执行getline的ret指令时得到的返回地址为0x8413938,这个地址所在存储段可能是不可执行的数据段,因而发生了段错误(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, int *b);

② viod abc(unsigned c, long *a, int *b);

9 / 11

. ③ 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位R[edi](截断为32位),再和*b相加。同时,参数c可以是带符号整数类型,也可以是无符号整数类型,因为第2行加法指令addl的执行结果对于带符号整数和无符号整数都一样。 31.参考答案:

(1)汇编指令注释如下: 1 movl 8(?p), íx //R[edx]←M[R[ebp]+8],将x送EDX 2 movl 12(?p), ìx //R[ecx]←M[R[ebp]+12],将k送ECX 3 movl $255, %esi //R[esi]←255,将255送ESI 4 movl $-2147483648, íi //R[edi]←-2147483648,将0x80000000送EDI

5 .L3: 6 movl 7 andl 8 xorl 9 movl 10 shrl 11 testl 12 jne

íi, êx íx, êx êx, %esi ìx, ?x %bl, íi íi, íi .L3

//R[eax]←R[edi],将i送EAX

//R[eax]←R[eax] and R[edx],将i and x送EAX

//R[esi]←R[esi] xor R[eax],将val xor (i and x)送ESI //R[ebx]←R[ecx],将k送ECX

//R[edi]←R[edi] >> R[bl],将i逻辑右移k位送EDI

//若R[edi]≠0,则转.L3

13 movl %esi, êx //R[eax]←R[esi]

(2)x和k分别存放在EDX和ECX中。局部变量val和i分别存放在ESI和EDI中。 (3)局部变量val和i的初始值分别是255和-2147483648。

(4)循环终止条件为i等于0。循环控制变量i每次循环被逻辑右移k位。 (5)C代码中缺失部分填空如下,注意:对无符号整数进行的是逻辑右移。

1 2 3 4 5 6 7 8

int {

lproc(int x, int k)

int val = 255 ; int i;

for (i= -2147483648 ; i != 0 ; i= (unsigned) i >> k ) { val ^= (i & x) ; }

return val;

9 }

32.参考答案:

从第5行指令可知,i在EAX中;从第6行指令可知,sptr在ECX中。由第7行指令可知,i*28在EBX

中。由第8、9和10行指令可猜出,x的每个数组元素占28B,并且xptr->idx的地址为sptr+i*28+4,故在line_struct中的第一个分量为idx,因而后面的24B为6个数组元素a[0]~a[5],类型与val变量的类型相同,即unsigned int。 line_struct结构类型的定义如下:

typedef struct { int idx; unsigned a[6]; } line_struct;

10 / 11

. 由第11、12行指令可知,x数组所占空间为0xc8-4=200-4=196B,所以LEN=196/28=7。 33.参考答案:

(1)n1.ptr、n1.data1、n2.data2、n2.next的偏移量分别是0、4、0和4。 (2)node类型总大小占8字节。 (3)chain_proc的C代码中缺失的表达式如下: uptr-> n2.next ->n1.data1 = *(uptr->n2. next->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。

11 / 11

计算机系统第三章答案

.……break;case1:…….break;case2:……break;case4:……break;default:……<
推荐度:
点击下载文档文档为doc格式
55d4k1jma77yqpo85se79mzf00wron00iy8
领取福利

微信扫码领取福利

微信扫码分享