深入理解计算机系统 第三版 第三章 家庭作业 答案

3.58

long decode2(long x,long y,long z)
{
	int ret;
	y=y-z;
	x=x*y;
	ret=y;
	ret<<=63;
	ret>>=63;
    return ret^x;
}

算术左移63再右移63,得到的要么是全0,要么全1,取决于y的最低位

3.59

画了个简单的图便于理解,要不很难说明白,图中每个XY都是64位


现在分析汇编代码

movq rdx,rax    //rdx为x

cqto                //rdx被设置为rax的符号位扩展,也就是要么0要么-1(ffffffff),说白了现在rdx是x_h,rax是x_l

movq rsi,rcx    //rsi为y_l

sarq $63,rcx    //rcx为y_h,也是要么0要么-1

imulq rax,rcx    //rcx=y_h*x_l

imulq rsi,rdx    //rdx=x_h*y_l

addq rdx,rcx    //将前面两个结果相加

mulq rsi            //x_l*y_l,得到,rax为低64位结果,rdx为进位

addq rcx,rdx    //进位rdx的值加上之前计算得到的两个高位结果,得到最终的高64位

movq rax,(rdi)    //低64位结果赋给dest

movq rdx,8(rdi)    //高64位结果赋给dest+8开始地址

ret

3.60

long loop(long x,int n)
{
	long result=0;
	long mask;
	for(mask=1;maks!=0;mask=mask<<(n%256))
	{
		result|=(x+mask);
	}
	return result;
}

程序都写出来了,下面ABCDE是个问题就明了了,不再赘叙

3.61

搞清楚函数在干嘛就像简单呢,xp地址为空,就返回0,要么返回地址里面的值也就是*xp,但是xp有可能为空,那么用*xp就存在风险

所以,只能操作xp,不操作*xp,代码如下:

long cread_alt(long  *xp)
 {
     long x = 0;
     long *p = xp?xp:&x;
     return *p;
 }
3.62
MODE_A: result = *p2 ;*p2=*p1; break;
MODE_B: result = *p1 + *p2; *p1 = result; break;
MODE_C: *p1 = 59; result = *p2; break;
MODE_D: *p1 = *p2; result=27; break;
MODE_E: result = 27; break;
default: result = 12; break;

3.63

int switch_prob(int x, int n)
 {
     int result = x;
     switch(n)
     {
        case 60:
        case 62:
            result *= 8; break;
        case 63:
            result >>= 3; break;
        case 64:
            result <<= 4; 
            result -= x;
	    x=result;
        case 65:
            x *= x;
        case 61:
        default:
            result = x+0x4b; break;
     }
     return result;
 }

3.64

A:    &A[i}[j][k]=Xa+L(i*S*T+j*T+k)

B:可以很容易看出rdx=65i+13j+k,所以T=13;S=5,R=3640/(8*65)=7

3.65

A:rdx

B:rax

C:8M=120,M=15

3.66

NR(n)=3n

NC(n)=1+4n 不是1+4n再<<3这是乘以8是因为long每个8字节

3.67

A:调用process之前,栈结构:(调用进入时会多压入一个返回地址,要注意区别,rsp会减8)


B:结构体strA s

CDE,其实看图也看的出来,只是区别在于多压进去一个返回地址,所以图中的rsp都要少8,来访问

F:允许我略

3.68

这题关键在于理解数据对齐,这两个结构体都是8字节对齐

首先t偏移位8,知道1<=B<=8

然后u偏移32,知道32-8-4=20,头两个short(4字节)和int对齐8字节,剩下的16字节占了两排,7<=A<=10

最后184偏移是y,int两个两个占一排(一排8字节),最后一排可能满也可能缺一,所以可能有184/4=46,或45个int,那么结合前面的知道B=5,A=9;

3.69

注意还是8字节对齐

首先0x120=288,偏移位last

int first和浪费的4字节占一排,那么中间288-8=280字节位结构体数组a

然后bp+40*i+8为结构体的初始地址也就是ap的地址也是ap->idx的地址,这里的8是int first和4字节剩余的

这里我们知道了每个结构体是40字节,那么cnt=280/40=7

然后注意到movslq指令,猜测idx为int,x为long数组

最后0x10+rax+rdx*8这里乘8说明了是long型,变形一下,8+bp+40*i+8+rdx*8,这里rdx就是idx,8+bp+40*i什么意思上面已经解释了,再加8是假的int idx和剩余的4字节

那么long数组的个数是多少,40-8/8=4所以:

a_struct{int idx ; long x[4];}

3.70

A:0,8,0,8

B:16

void proc(union ele *up)
{
	up->e2.x=*(up->e2.next)-up->e1.y;
}

3.71

不可能申请一个无穷大的空间给你一次读进来,所以只能一次读有限个字节分多次读取,然后一个个输出

void good_echo()
 {
     const int BufferSize = 0x8;
     char buf[BufferSize];
     int i;
     while(fgets(buf, BufferSize, stdin)!=NULL)
     {
         for(i=0;buf[i];i++)
            putchar(buf[i]);
         if(i<BufferSize-1) break;
     }
     return;
 }

3.72

A:n为奇数的时候取8n+24,为偶数取8n+16,向16取整数倍

B:向上取16的整数倍

C:n=0,s1=16时候,e1最大为16

n=1,s1=1时候,e1最小为1

D:都是16对齐

3.73

vxorps xmm0,xmm0,xmm0
movl $3,eax
vucomiss xmm0,xmm1 	//cmp x:0
 ja .L1			//大于0
 je .L2			//等于0
 jb .L3			//小于0
 jp .L4
 .L3:
	subl $1,eax
 .L2:
	subl $1,eax
 .L1:
	subl $1,eax
 .L4:
	rep;ret

3.74

vxorps xmm0,xmm0,xmm0
movl $3,eax
movl $2,ebx
movl $1,ecx
movl $0,edx
vucomiss xmm0,xmm1 	//cmp x:0
cmova ebx,eax			//大于0
cmove ecx,eax			//等于0
cmovb edx,eax			//小于0
.L4:
	rep;ret

3.75

A:单个参数时候xmm0是实部,xmm1是虚部,两个时候第一个一样,第二个的实部在xmm2,虚部在xmm3

B:xmm0返回实部,xmm1返回虚部.

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值