深入理解計算機系統 第三版 第三章 家庭作業 答案
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,程式碼如下:
3.62long cread_alt(long *xp) { long x = 0; long *p = xp?xp:&x; return *p; }
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返回虛部.