CSAPP(深入理解计算机系统)第二版家庭作业答案-第三章

答案均由本人完成,并且实验或者调试,欢迎参考!

3.54
int decode2(int x,int y,int z)
{
	int t=z-y;
	int t2=t<<15;
	t2=t2>>15;
	return (x^t)*t2;
}

3.55
movl 12(%ebp),%esi  ;Get x的低位
movl 20(%ebp),%eax  ;Get y
movl %eax,%edx
sarl $31,%edx ;取y的符号位
movl %edx,%ecx
imull %esi,%ecx ;%ecx=x的低位*y的符号位(0或者-1)
movl 16(%ebp),%ebx;Get x的高位
imull %eax,%ebx ;%ebx=x的高位*y
addl %ebx,%ecx  ;%ecx=x的高位*y+x的低位*y的符号位(0或者-1)
mull %esi       ;%edx=(x的低位*y)的高位 %eax=(x的低位*y)的低位
leal (%ecx,%edx),%edx
movl 8(%ebp),%ecx
movl %eax,(%ecx)
movl %edx,4(%ecx)
(x的低位*y)的高位+x的高位*y+x的低位*y的符号位(0或者-1) 存储在高位
(x的低位*y)的低位 存储在低位
(xl*y)_h+xh*y+xl*-1
(x1*y)_l
xl=1000
xh=0000
y=1001
x*yi=x*(yu-16)=x*yu-16x
相当于高位=(x*yu)_h-x,低位=(x*yu)_l
因为这里是mull无符号乘法

3.56
A.
x:%esi,n:%ebx,result:%edi,mask:%edx
B.
result=0x55555555; //‭0101 0101 0101 0101 0101 0101 0101 0101‬
mask=0x80000000;
C.
mask!=0
D.
mask每次循环右移n位
E.
result每次循环和x&mask的值进行异或
F.
int loop(int x,int n)
{
	int result=0x55555555;
	int mask;
	for(mask=0x80000000;mask!=0;((unsigned)mask)>>n)//汇编中mask是逻辑右移,而mask是有符号整型应该先转成无符号整型才能保证C语言的右移操作符编译成汇编的逻辑右移
	{
		result^=x&mask;
	}
	return result;
}

3.57
int cread_alt(int *xp)
{
	int t=0;
	int *p=xp?xp:&t;
	return *p;
}

3.58
int switch3(int *p1,int *p2,mode_t action)
{
	int result=0;
	switch(action)
	{
		case MODE_A:
			result=*p1;
			*p1=*p2;
			break;
		case MODE_B:
			result=*p1+*p2;
			*p2=result;
			break;
		case MODE_C:
			*p2=15;
			result=*p1;
			break;
		case MODE_D:
			*p2=*p1;
		case MODE_E:
			result=17;
			break;
		default:
			result=-1;
			break;
	}
	return result;
}

3.59
int switch_prob(int x,int n)
{
	int result=x;
	switch(n)
	{
		case 40:
		case 42:
			result<<=3;
			break;
		case 43:
			result>>=3;
			break;
		case 44:
			result<<=3;
			result-=x;
		case 45:
			result*=result;
		case 41:  //可以不要
		default:
			result+=11;
			break;
	}
	return result;
}

3.60
A.
A[i][j][k]=A+((2^6-1)*i+9j+k)*4=A+(63i+9j+k)*4
B.
T=9
S*T=63
R*S*T=2772/4=693
R=11 S=7 T=9

3.61
int var_prod_ele(int n, int A[n][n], int B[n][n], int i, int k)
{
    int result = 0;
    int *a = &A[i][0];
    int *b = &B[0][k];
    int *e = &A[i][n];
    for(;a!=e;)
    {
        result += *a * *b;
        b+=n;
        a++;
    }
    return result;
}
下面是其汇编代码的循环部分:
edi是4*n,ebx和edx分别是b和a,esi是e,eax是result。
ecx是用于存储乘法的寄存器。
L4:
movl (%ebx), %ecx
imull (%edx), %ecx
addl %ecx, %eax
addl %edi, %ebx
addl $4, %edx
cmpl %edx, %esi
jne L4
result,Arow,Bcol,4*n这四个值耗费的存储器必不可少
n的值转变为e的值耗费一个寄存器
比较n和a的值,省掉了变量j,少用了一个寄存器

3.62
A.
M=76/4=19
B.
i:%edi,j:ecx
C.
void transpose(int A[M][M])
{
	for(int i=0;iidx=*(bp+1c*i+4)*4
ap->x[ap->idx]=(bp+4+28*i+4)+*(bp+0x1c*i+4)*4=bp+8+28i+*(bp+28i+4)*4=bp+8+4(7i+*(bp+28i+4))

3.67
A.
e1.p:0
e1.x:4
e2.y:0
e2.next:4
B.8
C.
void proc(union ele *up)
{
	up->e2.next->e1.x=*(up->e2.next->e1.p) - up->e2.y;
}

3.68
void good_echo()
{
    char c;
    int x = 0;
    while( x=getchar(), x!='\n' && x!=EOF)
    {
        putchar(x);
    }
}

3.69
A.
long trace(tree_ptr tp)
{
	long result=0;
	while(tp)
	{
		result=tp->val;
		tp=tp->left;
	}
	return result;
}
B.输出二叉树最左边节点的值

3.70
A.
long traverse(tree_ptr tp)
{
	if(!tp)
		return 9223372036854775807;//long.max
	long v=tp->val;
	long left=traverse(tp->left);
	long result=traverse(tp->right);
	if(leftv)
		result=v;
	return result;
}
B.求二叉树节点中最小的值


原创地址: http://blog.csdn.net/maidou0921/article/details/53907971

你可能感兴趣的:(技术交流)