深入理解計(jì)算機(jī)系統(tǒng)(第二版)-家庭作業(yè)答案_第1頁(yè)
深入理解計(jì)算機(jī)系統(tǒng)(第二版)-家庭作業(yè)答案_第2頁(yè)
深入理解計(jì)算機(jī)系統(tǒng)(第二版)-家庭作業(yè)答案_第3頁(yè)
深入理解計(jì)算機(jī)系統(tǒng)(第二版)-家庭作業(yè)答案_第4頁(yè)
深入理解計(jì)算機(jī)系統(tǒng)(第二版)-家庭作業(yè)答案_第5頁(yè)
已閱讀5頁(yè),還剩90頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、深入理解計(jì)算機(jī)系統(tǒng)(第二版) 家庭作業(yè) 第二章 2.55-2.57 略2.58int is_little_endian()    int a = 1;    return *(char*)&a);2.59(x&0xFF) | (y&0xFF)2.60unsigned replace_byte(unsigned x, unsigned char b, int i) 

2、   return (x & (0xFF<<(i<<3) | (b << (i<<3);2.61A. !xB. !xC. !(x>>(sizeof(int)-1)<<3)D. !(x&0xFF)注意,英文版中C是最低字節(jié),D是最高字節(jié)。中文版恰好反過來了。這里是按中文版來做的。2.62這里我感覺應(yīng)該是英文版對(duì)的,int_shifts_are_arithmetic()int int_shifts_ar

3、e_arithmetic()    int x = -1;    return (x>>1) = -1;2.63對(duì)于sra,主要的工作是將xrsl的第w-k-1位擴(kuò)展到前面的高位。這個(gè)可以利用取反加1來實(shí)現(xiàn),不過這里的加1是加1<<(w-k-1)。如果x的第w-k-1位為0,取反加1后,前面位全為0,如果為1,取反加1后就全是1。最后再使用相應(yīng)的掩碼得到結(jié)果。對(duì)于srl,注意工作就是將前面的高位清0,即xsra & (1<<

4、;(w-k) - 1)。額外注意k=0時(shí),不能使用1<<(w-k),于是改用2<<(w-k-1)。 int sra(int x, int k)    int xsrl = (unsigned) x >> k;    int w = sizeof(int) << 3;    unsigned z = 1

5、 << (w-k-1);    unsigned mask = z - 1;    unsigned right = mask & xsrl;    unsigned left = mask & (z&xsrl) + z);    return left | ri

6、ght;int srl(unsigned x, int k)    int xsra = (int) x >> k;    int w = sizeof(int)*8;    unsigned z = 2 << (w-k-1);    return (z -

7、0;1) & xsra;2.64int any_even_one(unsigned x)    return !(x & (0x55555555);2.65int even_ones(unsigned x)    x = (x >> 16);    x = (x >> 8);   

8、; x = (x >> 4);    x = (x >> 2);    x = (x >> 1);    return !(x&1); x的每個(gè)位進(jìn)行異或,如果為0就說明是偶數(shù)個(gè)1,如果為1就是奇數(shù)個(gè)1。那么可以想到折半縮小規(guī)模。最后一句也可以是 return (x1)&12.66根據(jù)提示想到利用或運(yùn)算,將

9、最高位的1或到比它低的每一位上,忽然想如果x就是10000000.該如何讓每一位都為1。于是便想到了二進(jìn)擴(kuò)展。先是x右移1位再和原x進(jìn)行或,變成1100000.,再讓結(jié)果右移2位和原結(jié)果或,變成11110000.,最后到16位,變成11111111.。int leftmost_one(unsigned x)    x |= (x >> 1);    x |= (x >> 2);  &

10、#160; x |= (x >> 4);    x |= (x >> 8);    x |= (x >> 16);    return x(x>>1);2.67A.32位機(jī)器上沒有定義移位32次。B.beyond_msb變?yōu)?2<<31。C.定義 a = 1<<15;

11、 a<<=15; set_msb = a<<1; beyond_msb = a<<2;2.68感覺中文版有點(diǎn)問題,注釋和函數(shù)有點(diǎn)對(duì)應(yīng)不上,于是用英文版的了。個(gè)人猜想應(yīng)該是讓x的最低n位變1。int lower_one_mask(int n)    return (2<<(n-1) - 1;2.69unsigned rotate_right(unsigned x, int n)    int

12、 w = sizeof(unsigned)*8;    return (x>>n) | (x<<(w-n-1)<<1);2.70這一題是看x的值是否在 - 2(n-1) 到 2(n-1) - 1之間。如果x滿足這個(gè)條件,則其第n-1位就是符號(hào)位。如果該位為0,則前面的w-n位均為0,如果該位為1,則前面的w-n位均為1。所以本質(zhì)是判斷,x的高w-n+1位是否為0或者為-1。int fits_bits(int x, int n)&#

13、160;   x >>= (n-1);    return !x | !(x);2.71A.得到的結(jié)果是unsigned,而并非擴(kuò)展為signed的結(jié)果。B.使用int,將待抽取字節(jié)左移到最高字節(jié),再右移到最低字節(jié)即可。int xbyte(unsigned word, int bytenum)    int ret = word << (3 -

14、 bytenum)<<3);    return ret >> 24;2.72A.size_t是無符號(hào)整數(shù),因此左邊都會(huì)先轉(zhuǎn)換為無符號(hào)整數(shù),它肯定是大于等于0的。B.判斷條件改為if(maxbytes > 0 && maxbytes >= sizeof(val)2.73請(qǐng)先參考2.74題??芍簍 = a + b時(shí),如果a,b異號(hào)(或者存在0),則肯定不會(huì)溢出。如果a,b均大于等于0,則t<0就是正溢出,如果a,b均小于0,則t>=0就是負(fù)溢出。于是,

15、可以利用三個(gè)變量來表示是正溢出,負(fù)溢出還是無溢出。int saturating_add(int x, int y)    int w = sizeof(int)<<3;    int t = x + y;    int ans = x + y;    x>>=(w-1);  

16、  y>>=(w-1);    t>>=(w-1);    int pos_ovf = x&y&t;    int neg_ovf = x&y&t;    int novf = (pos_ovf|neg_ovf);    return (pos_ovf &

17、 INT_MAX) | (novf & ans) | (neg_ovf & INT_MIN); 2.74對(duì)于有符號(hào)整數(shù)相減,溢出的規(guī)則可以總結(jié)為:t = a-b;如果a, b 同號(hào),則肯定不會(huì)溢出。如果a>=0 && b<0,則只有當(dāng)t<=0時(shí)才算溢出。如果a<0 && b>=0,則只有當(dāng)t>=0時(shí)才算溢出。不過,上述t肯定不會(huì)等于0,因?yàn)楫?dāng)a,b不同號(hào)時(shí):1) a!=b,因此a-b不會(huì)等于0。2) a-b <= abs(a) + abs(b) <=

18、 abs(TMax) + abs(TMin)=(2w - 1)所以,a,b異號(hào),t,b同號(hào)即可判定為溢出。int tsub_ovf(int x, int y)    int w = sizeof(int)<<3;    int t = x - y;    x>>=(w-1);    y>>=(w-1); 

19、;   t>>=(w-1);    return (x != y) && (y = t);順便整理一下匯編中CF,OF的設(shè)定規(guī)則(個(gè)人總結(jié),如有不對(duì)之處,歡迎指正)。t = a + b;CF: (unsigned t) < (unsigned a) 進(jìn)位標(biāo)志OF: (a<0 = b<0) && (t<0 != a<0)t = a - b;CF: (a<0 && b>=0) | (a<0 = b<

20、;0) && t<0) 退位標(biāo)志OF: (a<0 != b<0) && (b<0 = t<0)匯編中,無符號(hào)和有符號(hào)運(yùn)算對(duì)條件碼(標(biāo)志位)的設(shè)定應(yīng)該是相同的,但是對(duì)于無符號(hào)比較和有符號(hào)比較,其返回值是根據(jù)不同的標(biāo)志位進(jìn)行的。詳情可以參考第三章3.6.2節(jié)。2.75根據(jù)2-18,不難推導(dǎo), (x'*y')_h = (x*y)_h + x(w-1)*y + y(w-1)*x。unsigned unsigned_high_prod(unsigned x, unsigned y)  &

21、#160; int w = sizeof(int)<<3;    return signed_high_prod(x, y) + (x>>(w-1)*y + x*(y>>(w-1);當(dāng)然,這里用了乘法,不屬于整數(shù)位級(jí)編碼規(guī)則,聰明的辦法是使用int進(jìn)行移位,并使用與運(yùn)算。即 (int)x>>(w-1) & y 和 (int)y>>(w-1) & x。注:不使用long long來實(shí)現(xiàn)sign

22、ed_high_prod(int x, int y)是一件比較復(fù)雜的工作,而且我不會(huì)只使用整數(shù)位級(jí)編碼規(guī)則來實(shí)現(xiàn),因?yàn)樾枰褂醚h(huán)和條件判斷。下面的代碼是計(jì)算兩個(gè)整數(shù)相乘得到的高位和低位。int uadd_ok(unsigned x, unsigned y)    return x + y >= x;void signed_prod_result(int x, int y, int &h, int &a

23、mp;l)    int w = sizeof(int)<<3;    h = 0;    l = (y&1)?x:0;    for(int i=1; i<w; i+)        if( (y>>i)&1 ) 

24、;            h += (unsigned)x>>(w-i);            if(!uadd_ok(l, x<<i) h+;            l&#

25、160;+= (x<<i);                h = h + (x>>(w-1)*y) + (y>>(w-1)*x);最后一步計(jì)算之前的h即為unsigned相乘得到的高位。sign_h = unsign_h - (x>>(w-1) & y) - (y>>(w-1) & x);sign_h = un

26、sign_h + (x>>(w-1) * y) + (y>>(w-1) * x);2.76A. K=5: (x<<2) + xB. K=9: (x<<3) + xC. K=30: (x<<5) - (x<<1)D. K=-56: (x<<3) - (x<<6)2.77先計(jì)算x>>k,再考慮舍入。舍入的條件是x<0&&x的最后k位不為0。int divide_power2(int x, int k)  

27、60; int ans = x>>k;    int w = sizeof(int)<<3;    ans += (x>>(w-1) && (x&(1<<k)-1);    return ans; 2.78這相當(dāng)于計(jì)算(x<<2) + x) >> 3,當(dāng)然,需要考慮x為負(fù)數(shù)時(shí)的舍入。

28、先看上述表達(dá)式,假設(shè)x的位模式為b(w-1), b(w-2), . , b(0),那么我們需要計(jì)算:b(w-1),b(w-2),b(w-3),   .    ,b(0),  0,    0+             b(w-1),b(w-2),.,b(2),  b(1), b(0)最后需要右移3位。因此我們可以忽略下方的b(1),b(0)。于是就計(jì)算(x>>2) + x,再右移一位即是所求答案。不過考慮到(x>>2) + x可能也會(huì)

29、溢出,于是就計(jì)算(x>>3) + (x>>1),這個(gè)顯然是不會(huì)溢出的。再看看b(0)+b(2)會(huì)不會(huì)產(chǎn)生進(jìn)位,如果產(chǎn)生進(jìn)位,則再加一。最后考慮負(fù)數(shù)的舍入。負(fù)數(shù)向0舍入的條件是x<0 && (x<<2)+x 的后三位不全為0)。滿足舍入條件的話,結(jié)果再加1。容易證明,加法后三位不全為0可以等價(jià)為x后三位不全為0。    int mul5div8(int x)    int b0 = x&1, b2 = (x>

30、;>2)&1;    int ans = (x>>3) + (x>>1);    int w = sizeof(int)<<3;    ans += (b0&b2);    ans += (x>>(w-1) && (x&7);

31、    return ans; 2.79不懂題意,感覺就是2.78。2.80A. 1w-n0n:  (1<<n) - 1)B. 0w-n-m1n0m: (1<<n) - 1) << m2.81A. false,當(dāng)x=0,y=TMin時(shí),x > y,而-y依然是Tmin,所以-x > -y。B. true,補(bǔ)碼的加減乘和順序無關(guān)(如果是右移,則可能不同)。C. false,當(dāng)x=-1, y=1時(shí),x + y = 0xFFFFFFFE,而(x+y) = 0xFFFFFFFF。D.

32、true,無符號(hào)和有符號(hào)數(shù)的位級(jí)表示是相同的。E. true,最后一個(gè)bit清0,對(duì)于偶數(shù)是不變的,對(duì)于奇數(shù)相當(dāng)于-1,而TMin是偶數(shù),因此該減法不存在溢出情況。所以左邊總是<=x。2.82A. 令x為無窮序列表示的值,可以得到x*2k = Y + x。所以 x = Y/(2k - 1)。B. (a)1/7, (b)9/15 = 3/5, (c)7/63 = 1/92.83浮點(diǎn)數(shù)的一個(gè)特點(diǎn)就是,如果大于0,則可以按unsigned位表示的大小排序。如果小于0則相反。注意都為0的情況即可。所以條件是:(ux<<1)=0 && (uy<<1)=0)

33、| (!sx && sy) | (!sx && !sy && ux >= uy) |(sx && sy && ux <= uy);2.84A. 5.0,5表示為101,因此位數(shù)M就是1.01為1.25,小數(shù)f為0.01 = 0.25。指數(shù)部分應(yīng)該為E=2,所以其指數(shù)部分位表示為e=(2(k-1)-1) + 2 = 2(k-1)+1。位表示三個(gè)部分分別是s-e-f,為0-10.01-0100.0。B.能被準(zhǔn)確描述的最大奇數(shù),那么其M=1.111.1,故f部分全為1,E應(yīng)該為n。當(dāng)然,這

34、個(gè)假設(shè)在2(k-1)>=n的情況下才能成立。這時(shí),s=0,e=n+2(k-1)-1,f=11.1。值為2(n+1)-1。C.最小的規(guī)格化數(shù)為2(1-bias)即2(-2(k-1)+2),所以其倒數(shù)值V為2(2(k-1)-2),所以M為1.00000,f部分為全0,E=2(k-1)-2,e部分為2(k-1)-2 + bias = 2k - 3,即為11.101。位表示為0-11.101-00.0。2.85描述擴(kuò)展精度值十進(jìn)制最小的正非規(guī)格化數(shù)2(-63)*2(-214+2)3.6452e-4951最小的正規(guī)格化數(shù)2(-214+2)3.3621e-4932最大的規(guī)格化數(shù)(264-1)*2(2

35、14-1-63)1.1897e+49322.86描述HexMEV-00x80000-62-最小的值>10x3F01257/2560257*2(-8)2560x470018-最大的非規(guī)格化數(shù)0x00FF255/256-62255*2(-70)-inf0xFF00-Hex為0x3AA00x3AA0416/256-5416*2(-13)=13*2(-8)2.87格式A格式B位值位值1 01110 001-9/161 0110 0010-9/160 10110 1012080 1110 10102081 00111 110-7/10241 0000 0111-7/10240 00000 1016

36、/2170 0000 000001 11011 000-40961 1111 0000-inf0 11000 1007680 1111 0000inf沒有特別明白轉(zhuǎn)換成最接近的,然后又說向+inf舍入的含義。按理說,舍入到+inf就是向上舍入,而并不是找到最接近的。表格中是按最接近的進(jìn)行舍入,并且如果超出范圍則認(rèn)為是inf。如果都按+inf進(jìn)行舍入,那么第四行格式B將是0 0000 0001。2.88A. false,float只能精確表示最高位1和最低位的1的位數(shù)之差小于24的整數(shù)。所以當(dāng)x=TMAX時(shí),用float就無法精確表示,但double是可以精確表示所有32位整數(shù)的。B. fals

37、e,當(dāng)x+y越界時(shí),左邊不會(huì)越界,而右邊會(huì)越界。C. true,double可以精確表示所有正負(fù)253以內(nèi)的所有整數(shù)。所以三個(gè)數(shù)相加可以精確表示。D. false,double無法精確表示264以內(nèi)所有的數(shù),所以該表達(dá)式很有可能不會(huì)相等。雖然舉例子會(huì)比較復(fù)雜,但可以考慮比較大的值。E. false,0/0.0為NaN,(非0)/0.0為正負(fù)inf。同號(hào)inf相減為NaN,異號(hào)inf相減也為被減數(shù)的inf。2.89float的k=8, n=23。 bias = 27 - 1 = 127。最小的正非規(guī)格化數(shù)為2(1-bias-n) = 2-149。最小的規(guī)格化數(shù)為2(0-bias)*2 = 2-1

38、26。最大的規(guī)格化數(shù)(二的冪)為2(28-2 - bias) = 2127。因此按各種情況把區(qū)間分為TMin, -148 -149, -125 -126, 127 128, TMax。float fpwr2(int x)    /* Result exponent and fraction */    unsigned exp, frac;    unsigned u;    if (x 

39、;< -149)         /* Too small. Return 0.0 */        exp = 0;        frac = 0;     else if (x < -126)  &#

40、160;      /* Denormalized result */        exp = 0;        frac = 1<<(x+149);     else if (x < 128)    

41、60;    /* Normalized result. */        exp = x + 127;        frac = 0;     else         /* Too big. Return +oo */&#

42、160;       exp = 255;        frac = 0;        /* Pack exp and frac into 32 bits */    u = exp << 23 | frac;   

43、0;/* Return as float */    return u2f(u);2.90A.pi的二進(jìn)制數(shù)表示為:0 10000000 10010010000111111101011,E=128-127=1,它表示的二進(jìn)制小數(shù)值為:11.0010010000111111101011B.根據(jù)2.82,可知1/7的表示為0.001001001.,所以22/7為11.001001001001001001.C.從第9位開始不同。為了方便測(cè)試2.91-2.94,我寫了幾個(gè)公共函數(shù)。typedef unsigned float_bits;float

44、60;u2f(unsigned x)    return *(float*)&x);unsigned f2u(float f)    return *(unsigned*)&f);bool is_float_equal(float_bits f1, float f2)    return f2u(f2) = f1;bool is_nan(float_bits f

45、b)    unsigned sign = fb>>31;    unsigned exp = (fb>>23) & 0xFF;    unsigned frac = fb&0x7FFFFF;    return exp = 0xFF && frac != 0;bool is_inf

46、(float_bits fb)    unsigned sign = fb>>31;    unsigned exp = (fb>>23) & 0xFF;    unsigned frac = fb&0x7FFFFF;    return exp = 0xFF && frac = 0;int 

47、testFun( float_bits(*fun1)(float_bits),  float(*fun2)(float)    unsigned x = 0;    do /test for all 232 value        float_bits fb = fun1(x);        f

48、loat ff = fun2(u2f(x);        if(!is_float_equal(fb, ff)            printf("%x errorn", x);            return&

49、#160;0;                x+;    while(x!=0);    printf("Test OKn");     return 1;最后的testFun是用來測(cè)試fun1和fun2是否對(duì)每種可能的輸入都輸出相同的值,fun1為題中所要求的函數(shù),fun2為float版本。這個(gè)

50、函數(shù)大概會(huì)運(yùn)行2到3分鐘,也可以寫多線程,利用多核處理器求解。 2.91float_bits float_absval(float_bits f)    if(is_nan(f) return f;    else return f & 0x7FFFFFFF;float float_absval_f(float f)    if(is_nan(f2u(f) r

51、eturn f;    else return fabs(f);測(cè)試即調(diào)用testFun(float_absval, float_absval_f);在測(cè)試的時(shí)候發(fā)現(xiàn)0x7F800001的時(shí)候不對(duì)了。后來debug了一下,發(fā)現(xiàn)u2f的時(shí)候,會(huì)篡改原值。即令x = 0x7F800001。則f2u(u2f(x)會(huì)變成0x7FC00001。奇怪的nan,第22位一定是1。我將f2u和u2f里用memcpy也同樣是不行。所以,我將testFun中的一個(gè)條件變成了:if(!is_float_equal(fb, ff) &&am

52、p; !is_nan(fb)這個(gè)bug實(shí)在是不知道怎么回事。想了想,這和高位低位排列是無關(guān)的。這個(gè)bug還是之后再找吧。也有可能是硬件本身的原因了。注:C庫(kù)中也提供了isnan()函數(shù)。2.92float_bits float_negate(float_bits f)    if(is_nan(f) return f;    else return f0x80000000;float float_negate_f(float f)

53、60;   if(isnan(f) return f;    return -f;就是將最高位反位。2.93float_bits float_half(float_bits f)    unsigned sign = f>>31;    unsigned exp = (f>>23) & 0xFF;    u

54、nsigned frac = f&0x7FFFFF;    if(exp = 0) return sign<<31 | (frac>>1) + (frac&1)&&(frac>>1)&1);    else if(exp = 1) return sign<<31 | ( (1<<

55、22) | (frac>>1) + (frac&1)&&(frac>>1)&1)     else if(exp != 255) return sign<<31 | (exp-1) << 23 | frac;    else return f;float fl

56、oat_half_f(float f)    if(!isnan(f) return (float)0.5*f;    else return f;需要注意的是,舍入采用的是向偶數(shù)舍入。這也是我在測(cè)試的過程中發(fā)現(xiàn)的。(好吧,書上在浮點(diǎn)數(shù)位級(jí)編碼規(guī)則中說過了,眼殘沒看到)最后,非規(guī)格化的平滑效果讓exp=1時(shí)的程序變得比較簡(jiǎn)潔。2.94float_bits float_twice(float_bits f)    un

57、signed sign = f>>31;    unsigned exp = (f>>23) & 0xFF;    unsigned frac = f&0x7FFFFF;    if(exp = 0) return sign<<31 | frac<<1;    else if(exp&

58、#160;< 254) return sign<<31 | (exp+1)<<23 | frac;    else if(exp = 254) return sign<<31 | 0xFF<<23;    else return f;float float_twice_f(float f)

59、60;   if(!isnan(f) return (float)2*f;    else return f;比f(wàn)loat_half簡(jiǎn)單一些。對(duì)于非規(guī)格化的平滑,使用移位就可以了,對(duì)于規(guī)格化,只要exp+1即可,當(dāng)然,如果exp=254,就要返回inf了。2.95float_bits float_i2f(int i)    if(i = 0) return 0;   

60、 unsigned x = i>0?i:-i;    int sign = i>0?0:1;    int w = sizeof(int)<<3;    int j;    for(j=w-1; j>=0; j-) /找到最高位        if(

61、 (x>>j) & 1) break;        unsigned bias = 127;    unsigned exp, frac;    exp = bias + j;    if(j <= 23) frac = x<<(23-j);

62、0;   else         frac = x>>(j-23);        unsigned mask = (1<<(j-23) - 1;        if( (x&mask) > (1<<(j-2

63、4) ) frac+; /需要舍入到大值        else if( (x&mask) = 1<<(j-24)  &&  (frac&1) frac+; /舍入到偶數(shù)        if(frac = (1<<24) exp+;&

64、#160;/舍入到偶數(shù)超過(1<<24) - 1,指數(shù)需要再加1        return sign<<31 | exp<<23 | frac&0x7FFFFF;void test()    int x = 0;    do       

65、60;float_bits fb = float_i2f(x);        float ff = (float)x;        if(!is_float_equal(fb, ff)            printf("error in %d: 

66、60;%x %xn", x, fb, f2u(ff);            return;                x+;    while(x!=0);    printf("Te

67、st OKn");無恥地使用了循環(huán)。我也是一點(diǎn)一點(diǎn)測(cè)試修改,才通過的。不過好在大方向都知道,所以沒有花多少時(shí)間,主要糾結(jié)點(diǎn)還是在舍入那塊。需要特別注意。2.96int float_f2i(float_bits f)    unsigned sign = f>>31;    int exp = (f>>23) & 0xFF;    int frac = (f&

68、0x7FFFFF) | (1<<23);    exp -= 127;    if(exp < 0) return 0;    if(exp >= 31) return 0x80000000; /絕對(duì)值不大于231(1<<31)    if(exp >

69、60;23) frac <<= (exp - 23);    else frac >>= (23 - exp);    return sign? -frac : frac;void test2()    int x = 0;    do  

70、60;     int m = float_f2i(x);        int n = (int)u2f(x);        if(m != n)            printf("error in %

71、x:  %d %dn", x, m, n);            return;                x+;    while(x!=0);    printf(&qu

72、ot;Test OKn");在exp<0和>=31上犯了小錯(cuò)誤。開始寫成<=0和>=32了。其實(shí)1這個(gè)整數(shù)就是exp=0的。而int絕對(duì)值不會(huì)超過231-1,因此1.0000.小數(shù)點(diǎn)右移不會(huì)到超過30次(否則就越界了),所以exp<=30。而這里剛好用TMin來表示越界,因此不用關(guān)心TMin的表示。深入理解計(jì)算機(jī)系統(tǒng)(第二版) 家庭作業(yè) 第三章 3.54int decode2(int x, int y, int z)    int ret;

73、60;   z -= y; /line 2    ret = z; /line 3    ret <<= 15;/line 4    ret >>= 15;/line 5    return ret*(zx);3.55大概算法如下:x的高32位為xh,低32位為xl。y的符號(hào)位擴(kuò)展成32位之后為ys(ys

74、為0或者-1)。dest_h = (xl*ys)_l + (xh*y)_l + (xl*y)_hdest_l = (xl*y)_l注意,所有的乘法都是unsigned*unsigned。也就是說對(duì)于 1*(-1),如果存入兩個(gè)寄存器中,那么高32位是0,低32位是-1。 相當(dāng)于 1*(UNSIGNED_MAX)。3.56注意n在這里是一個(gè)很小的數(shù),用8位就能表示,也可以用n=n%256表示。寄存器 變量esi    xebx    nedi    resultedx    maskint loo

75、p(int x, int n)    int result = 1431655765;    int mask;    for(mask = 1<<31; mask != 0; mask = (unsigned)mask)>>n)        resul

76、t = (mask & x);        return result;3.57xp?*xp:0這個(gè)語(yǔ)句是不能被編譯成條件傳送語(yǔ)句的。因?yàn)槿绻菞l件傳送語(yǔ)句,那么不論xp為什么,*xp都會(huì)被計(jì)算。我們要寫一個(gè)和該功能完全一樣的能編譯成條件傳送語(yǔ)句的函數(shù)。于是,我們要想辦法不使用*xp,而使用一個(gè)替代的指向0的非空指針。int cread_alt(int *xp)    int t =&#

77、160;0;    int *p = xp?xp:&t;    return *p;3.58MODE_A: result = *p1; *p1 = *p2; break;MODE_B: result = *p1 + *p2; *p2 = result; break;MODE_C: result = *p1; *p2 = 15; break;MODE_D:

78、60;*p2 = *p1;MODE_E: result = 17; break;default: result = -1; break;3.59int switch_prob(int x, int n)    int result = x;    switch(n)            case&

79、#160;0x28:        case 0x2a:            result <<= 3; break;        case 0x2b:        

80、60;   result >>= 3; break;        case 0x2c:            result <<= 3;            &#

81、160;result -= x;        case 0x2d:            result *= result;        case 0x29: /也可以不要        

82、;default:            result += 0x11;                    return result;中間有一句話沒明白,匯編第12行 lea 0x0(%esi), %esi3.60對(duì)于ARST,Aijk 的位置

83、是 A(,i*S*T+j*T+k,4)。由匯編代碼可知:S*T = 63;T = 9;R*S*T = 2772/4;所以得 R=11, S=7, T=9。3.61感覺可以用-j,而不是比較j和 var_prod_ele(int n, int Ann, int Bnn, int i, int k)    int j = n-1;    int result = 0; &

84、#160;  for(; j!=-1; -j)        result += Aij * Bjk;    return result;但是這樣得到的結(jié)果仍然會(huì)使用到存儲(chǔ)器。按下面的代碼,循環(huán)里面貌似就沒有用到存儲(chǔ)器。但是用到了一個(gè)常量4,就是增加a的時(shí)候,會(huì)add 4。只需要result,a,e,b,4n這五個(gè)變量。int var_prod_ele(int n, 

85、int Ann, int Bnn, int i, int k)    int result = 0;    int *a = &Ai0;    int *b = &B0k;    int *e = &Ain;    for(;

86、a!=e;)            result += *a * *b;        b+=n;        a+;        return result;下面是其匯編代碼的循環(huán)部分

87、:edi是4*n,ebx和edx分別是b和a,esi是e,eax是result。ecx是用于存儲(chǔ)乘法的寄存器。L4:movl (%ebx), %ecximull (%edx), %ecxaddl %ecx, %eaxaddl %edi, %ebxaddl $4, %edxcmpl %edx, %esijneL4我怎么感覺前面那個(gè)程序,編譯器應(yīng)該也會(huì)自動(dòng)優(yōu)化。3.62M = 76/4 = 19;i在edi中,j在ecx中;int transpose(int M, int AMM) 

88、60;  int i,j;       for(i=0; i<M; +i)            int *a = &Ai0;        int *b = &A0i;     

89、;   for(j=0; j<i; +j)                    int t = *a;            *a = *b;    &

90、#160;       *b = t;            +a;            b += M;            3.63E1(n)在esi中,

91、esi = 3n。E2(n)在ebx中,ebx = 4*E2(n) = 4*(2n-1)。所以E2(n) = 2n-1。3.64這道題比較考驗(yàn)對(duì)知識(shí)的拓展應(yīng)用能力。根據(jù)簡(jiǎn)單的推測(cè),我們可以知道,imull的兩個(gè)對(duì)象是 ebx和edx,最后edx移動(dòng)到了(eax)中,所以ebx和edx一個(gè)是 *s1.p,一個(gè)是s1.v,并且word_sum的12行的eax是result的prod的地址,也就是result的地址。而eax只在第5行賦值,所以result的地址是在8(%ebp)中的。也就是說,結(jié)構(gòu)體返回值實(shí)際上是利用類似參數(shù)的變量進(jìn)行傳入(在8(%ebp)),而傳入的是返回結(jié)構(gòu)體變量的地址。所以:

92、A. 8(%ebp)為result的地址。12(%ebp)為s1.p。16(%ebp)為s1.v。B.棧中的內(nèi)容如下表,分配的20個(gè)字節(jié)用黃底展示(每一行為4個(gè)字節(jié))yx返回地址保存的ebp(也是當(dāng)前ebp的指向)ds1.vs1.p&s2 (word_sum的返回值地址)在匯編中,沒懂word_sum 15: ret $4以及diff 12: subl $4, %esp的意義何在??赡苁菫榱饲宄莻€(gè)result的返回地址。C.傳遞結(jié)構(gòu)體參數(shù)就像正常的傳值。結(jié)構(gòu)體的每一個(gè)變量可以看做是單獨(dú)的參數(shù)進(jìn)行傳入。D.返回結(jié)構(gòu)體的通用策略:將返回變量的地址看做第一

93、個(gè)參數(shù)傳入函數(shù)。而不是在函數(shù)中分配??臻g給一個(gè)臨時(shí)變量,因?yàn)閑ax確實(shí)存不下一個(gè)結(jié)構(gòu)體,eax充當(dāng)返回變量的指針的角色。3.65B取四的倍數(shù)的上整數(shù) = 8。8+4+ (B*2)取四的倍數(shù)的上整數(shù) = 28。所以B的可選值為8和7。2*A*B取四的上整數(shù)為44,所以A*B的可選值為21和22。所以 A=3, B=7。3.66我們用結(jié)構(gòu)體A表示a_struct。首先,根據(jù)第11和12行,可以得到 CNT*size(A) = 196。根據(jù)13行,知道 ecx + 4*edx + 8為 ap->xap->idx的地址。ecx存儲(chǔ)的是bp(地址)。ap的地址是 bp + 4 + i*size(A)我們知道,ap->x0 的地址是 bp + 4 + i*size(A) + pos(x),pos(x)為結(jié)構(gòu)體A中x的偏移。那么ap->xap->idx

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論