CSAPP第三章宿題参考解答

2909 ワード

(CSAPP第3版シリーズ)ナビゲーション編転送ゲート
3.58等価なdecode 2のCコードを書き出します.
/*rdi,rsi,rdx*/
long decode2(long x,long y,long z)
{
    y = y - z;
    x = x * y;
    y = (y << 63) >> 63;
    return x ^ y;
}

3.60 
A. x:%rdi  n:%rsi(%cl)  result:%rax  mask:%rdx
B.初期値:result=0;  mask = 1;
C.maskの試験条件:mask!=0;
D.maskの修正:mask=mask<E.resultの修正:result|=x&mask;F.Cコード記入
long loop(long x,int n)
{
    long result = 0;
    long mask;
    for(mask = 1;mask != 0;mask = mask << n)
        result |= x & mask;
    return result;
}

3.62 Cコードを記入する
typedef enum{MODE_A,MODE_B,MODE_C,MODE_D,MODE_E}mode_t;

long switch3(long *p1,long *p2,mode_t action)
{
    long result = 0;
    switch(action)
    {
    case MODE_A:
        result = *p2;
        *p2 = *p1;
        break;
    case MODE_B:
        result = *p1 + *p2;
        *p1 = result;
        break;
    case MODE_C:
        *p1 = 59;
        result = *p2;
        break;
    case MODE_D:
        *p1 = *p2;    // MODE_E
    case MDOE_E:
        result = 27;
        break;
    defult:
        result = 12;
    }
    return result;
}

3.64
A.配列A[R][S][T]における配列要素A[i][j][k]の位置の式.
&A[i][j][k]=Xa+L(i*S*T+j*T+k)で、Lはデータ型のバイト単位のサイズである.
B.R、S、Tの値を決定する.
アセンブリコードから、R*S*T*8=3640が得られる(条件1)
アセンブラコード,A[i][j][k]の位置の式はA+(65 i+13 j+k)*8であり,第1問から得られた式と照らし合わせると,T=13 S*T=65(条件2)の総合条件1,2が得られ,R=7 S=5 T=13が算出できる.
3.66逆工程技術を用いて、NRとNCの定義を確定する
アセンブラコードを解析することにより,このサイクルのサイクル数は,%rcx+%r 8のサイクル毎に,NR(n)=3*nNC(n)=4*n+1のNR(n)=3*nNC(n)=4*n+1であることが分かった.
したがって、マクロ表現は、#define NR(n)3*(n)#defineNC(n)4*(n)+1
3.68 AとBの値はいくらですか?
アセンブラコードおよびデータ配置規則による:
q->t=8(%rsi)、すなわちstr 2のtは8ビット目から8ビットでsizeof(array[B])が8以下、下辺のtはintタイプが4バイトを占めるのでsizeof(array[B])が4より大きく、4が得られる
q->u=32(%rsi)、すなわちstr 2のuは32ビット目からsが20バイトを占めsizeof(s[A])<=20となり、下辺のuはlongタイプが8バイトを占めるのでsizeof(s[A])が20-8=12より大きく6が得られる
p->y=184(%rdi)、すなわちstr 1のyは184ビットから始まるので184-8
以上の3つの制約条件から,A=9 B=5を解いた.
3.70
A.フィールドのオフセット量を求める:
e1.p  0
e1.y  8
e2.x  0
e2.next  8
B.この構造は全部で16バイト必要です.
C.procコードを記入する
ポインタの指向を明らかにするだけで、このCコードが得られます.
void proc(union ele *up)
{
    up->e2.x = *(up->e2.next->e1.p) - up->e2.next->e1.y;
}

3.72
A.5行目のleaq命令は値8 n+30を計算し、6行目のandq命令は最も近い16の倍数に切り捨てます.nが奇数の場合、結果値は8 n+24、nが偶数の場合、結果値は8 n+16となり、s 1からこの値を減算するとs 2となる.
B.8-9行目の2つの命令はs 2を最も近い16の倍数に切り上げ、オフセットとシフトの組み合わせを利用して、この値をpとする.
C.e 1の値を最小にするには、e 1+e 2を最小にしながらe 2を最大にする必要がある.nが偶数である場合、e 1+e 2=16が最小となる.s 1%16=1の場合、e 2=15が最大となります.
すなわち、nは偶数であり、s 1%16=1でe 1が最小である.
e 1の値を最大にするには、e 1+e 2を最大にし、e 2を最小にする必要があります.nが奇数である場合、e 1+e 2=24が最大となる.s 1%16=0の場合、e 2=0が最小となる.
すなわち、nが奇数であり、s 1%16=0のときe 1が最大となる.
D.s 2は、配列pを収容するのに十分な空間であり、最小の16の倍数であることを保証する.
Pは16の倍数で整列する.