深入理解计算机系统 csapp 家庭作业(第二章完整版) 您所在的位置:网站首页 昭阳e42-80笔记本电脑参数 深入理解计算机系统 csapp 家庭作业(第二章完整版)

深入理解计算机系统 csapp 家庭作业(第二章完整版)

2023-08-11 05:01| 来源: 网络整理| 查看: 265

文章目录 第二章2.552.562.572.582.592.602.612.622.632.642.652.662.672.682.692.702.712.722.732.742.752.762.772.782.792.802.812.822.832.842.852.862.872.882.892.902.912.922.932.942.952.962.97

第二章 2.55

代码示例:`

#include typedef unsigned char *byte_pointer; void show_bytes(byte_pointer start, size_t len) { size_t i; for (i = 0; i show_bytes((byte_pointer) &x, sizeof(float)); } void show_pointer(void *x){ show_bytes((byte_pointer) &x, sizeof(void *)); } void test_show_bytes(int val){ int ival=val; float fval=(float)ival; int *pval=&ival; show_int(ival); show_float(fval); show_pointer(pval); } int main(){ int val=12345; test_show_bytes(val); return 0; }`

运行结果: 39300000 00e44046 f4fe20effe7f0000 使用的机器采用小端法存储

2.56

同上

2.57 #include typedef unsigned char *byte_pointer; void show_bytes(byte_pointer start, size_t len) { size_t i; for (i = 0; i show_bytes((byte_pointer) &x, sizeof(long)); } void show_double(double x){ show_bytes((byte_pointer) &x, sizeof(double)); } void test_show_bytes(int val){ short sval=(short)val; long lval=(long)val; double dval=(double)val; show_short(sval); show_long(lval); show_double(dval); } int main(){ int val=12345; test_show_bytes(val); return 0; }

运行结果: 3930 3930000000000000 00000000801cc840

2.58

由2.55可知,12345的16位小端法表示为39300000,因此判断数据存储为大端法还是小端法,只需要判断第一个字节是否为39即可

#include typedef unsigned char *byte_pointer; int is_little_endian(){ int test=12345; byte_pointer p=(byte_pointer)&test; return p[0]==0x39; } int main(){ if(is_little_endian()) printf("the machine is little endian\n"); else printf("the machine is big endian\n"); } 2.59

使用位运算和掩码结合字节

#include typedef unsigned char *byte_pointer; size_t combine(size_t x,size_t y){ size_t mask=0xff; return ((x&mask)|(y&~mask)); } int main(){ size_t x=0x89abcdef,y=0x765432ef; printf("%#x\n",combine(x,y)); } 2.60 #include typedef unsigned char* byte_pointer; size_t replace_byte(unsigned x,int i,unsigned char b){ size_t mask=((unsigned)0xff) int x=-1; return x==x>>3; } int main(){ printf("%d\n",int_shifts_are_arithmetic()); } 2.63 #include unsigned srl(unsigned x,int k){ unsigned xsra = (int) x>>k; int w =sizeof(int) unsigned testu = 0x12345678; int testi = 0x12345678; printf("%x\n",srl(testu,2)); printf("%x\n",sra(testi,2)); } 2.64

当 x 的任何奇数位等于 1 时返回 1;否则为 0。

#include int any_odd_one(unsigned x){ return !!(0xAAAAAAAA&x); } int main(){ int a = 0x0111; printf("%d",any_odd_one(a)); } 2.65

当 x 包含奇数个1 时,返回 1;否则为 0。

#include int odd_ones(unsigned x){ x^=x>>16; x^=x>>8; x^=x>>4; x^=x>>2; x^=x>>1; return x&1; } int main(){ int a = 0x0101; printf("%d",odd_ones(a)); } 2.66 #include int leftmost_one(unsigned x) { x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; return (x >> 1) + (x && 1); //(x && 1)用来解决x=0x时的情况 } int main() { printf("%x\n",leftmost_one(0x6600)); return 0; } 2.67

A.32位机器,最多只能移动31位,这个代码超出了机器能移动的位数,超出位无定义。 B.

#include int int_size_is_32() { int set_msb=1 int set_msb=1 int w = sizeof(int) (w-n); } int main(){ printf("%#x",lower_one_mask(17)); } 2.69 #include unsigned rotate_left(unsigned x, int n) { unsigned w1=x((sizeof(int) int w=sizeof(int) return ((int)(word if(maxbytes>=sizeof(val)) //将maxbytes也改为unsigned类型,比较两个unsigned值的大小 memcpy(buf,(void*)&val,sizeof(val)); } int main(){ int max = 100; void *buff = malloc(max); copy_int(100,&buff,200); } 2.73 #include #include int saturating_add(int x, int y) { int sum=x+y; int sig_mask=INT_MIN; int pos_over=!(x & sig_mask) && !(y & sig_mask) && (sum & sig_mask);//x>0,y>0,正溢出 int neg_over=(x & sig_mask) && (y & sig_mask) && !(sum & sig_mask);//x int res = 1; (y == INT_MIN) && (res = 0);// 如果y == INT_MIN,则res = 0(一定溢出); int sub = x - y; int pos_over = x > 0 && y int64_t high_prod = (int64_t)x * y; return high_prod >> 32; //计算(x * y) / 2^w } unsigned unsigned_high_prod(unsigned x, unsigned y) { int bit_x = x>>31; //bit_x表示 x_{w-1} int bit_y = y>>31; //bit_y表示 y_{w-1} int sig_high = signed_high_prod(x, y); return sig_high + x * bit_y + y * bit_x; //计算(x' * y') / 2^w } unsigned test(unsigned x, unsigned y) { //验证结果是否正确 uint64_t high_prod = (uint64_t)x * y; return high_prod >> 32; } int main() { unsigned x = 0xffffffff; unsigned y = 0x12345678; printf("%.8x\n", unsigned_high_prod(x, y)); printf("%.8x\n", test(x, y)); return 0; } 2.76

(本题用了if和乘除法,没有想到怎么用位运算实现)

#include #include #include #include void *calloc(size_t nmemb, size_t size) { if (!(nmemb & size)) { return NULL; } size_t buf_size = nmemb * size; if (nmemb == buf_size / size) { void* ptr = malloc(buf_size); if(ptr != NULL) { memset(ptr, 0, buf_size); } return ptr; } return NULL; } int main(){ printf("%d\n", calloc(INT_MAX, INT_MAX)); } 2.77 A.(x printf("%d\n",divide_power2(-9,2)); } 2.79 #include int mul3div4(int x){ x = (x x=(x+((1 return *(unsigned*)&x; } int float_le(float x,float y){ unsigned ux = f2u(x); unsigned uy = f2u(y); unsigned sx = ux>>31; unsigned sy = uy>>31; return!(ux= uy); /* x < 0 and y < 0 */ } int main(){ printf("%d\n",float_le(-0,+0)); printf("%d\n",float_le(+0,-0)); } 2.85

注:C最小的规格化数是0 00…01 00…00,其值为 2 1 − ( 2 ( k − 1 ) − 1 ) 2^{1- (2^{(k-1)}-1)} 21−(2(k−1)−1)= 2 2 − 2 k − 1 2^{2-2^{k-1}} 22−2k−1 倒数为 2 2 k − 1 − 2 2^{2^{k-1}-2} 22k−1−2,位表示为0 11…101 00000…

ABC阶码2n 2 k − 1 − 2 2^{k-1}-2 2k−1−2尾数1.111.11…11.0小数0.110.11…10.0值7.0 2 n + 1 2^{n+1} 2n+1-1 2 2 k − 1 − 2 2^{2^{k-1}-2} 22k−1−2位表示0 1…0 1 11…00 bias+n 11…10 1…01 00…0 2.86 描述值十进制最小的正非规格化数 2 − 63 ∗ 2 1 − ( 2 14 − 1 ) 2^{-63}*2^{1-(2^{14}-1)} 2−63∗21−(214−1)= 2 − 63 ∗ 2 2 − 2 14 2^{-63}*2^{2-2^{14}} 2−63∗22−214= 2 − 61 − 2 14 2^{-61-2^{14}} 2−61−2143.6452e-4951最小的正规格化数 2 1 − ( 2 14 − 1 ) 2^{1-(2^{14}-1)} 21−(214−1)= 2 2 − 2 14 2^{2-2^{14}} 22−2143.3621e-4932最大的规格化数 2 2 15 − 1 − ( 2 14 − 1 ) ∗ ( 1 + ( 1 − 2 − 63 ) ) = 2 2 14 − 1 ( 2 − 2 − 63 ) 2^{2^{15}-1-({2^{14}-1})}*(1+(1-2^{-63}))=2^{2^{14}-1}(2-2^{-63}) 2215−1−(214−1)∗(1+(1−2−63))=2214−1(2−2−63)1.1897e+4932 2.87

bias= 2 5 − 1 2^{5-1} 25−1-1=15

描述HexMEVD-01000 0000 0000 0000=0x800000-0-0.0最小的>2的值0100 0000 0000 0001=0x4001 1 + 2 − 10 1+2^{-10} 1+2−101 ( 1 + 2 − 10 ) ∗ 2 (1+2^{-10})*2 (1+2−10)∗22.0019531255120110 0000 0000 0000=0x600019512512.0最大非规格化数0000 0011 1111 1111=0x03ff 1 − 2 − 10 1-2^{-10} 1−2−10-14 ( 1 − 2 − 10 ) ∗ 2 − 14 (1-2^{-10})*2^{-14} (1−2−10)∗2−146.09755516e-5-oo1111 1100 0000 0000=0xfc00---oo-oo0x3BB00011 1011 1011 0000=0x3bb0 123 / 64 123/64 123/64-1 123 / 128 123/128 123/1280.9609375 2.88 A位A值B位B值1 01110 001-9/161 0110 0010-9/160 10110 10113*2^40 1110 101013*2^41 00111 110-7/2^101 0000 0111-7/2^100 00000 1015/2^170 0000 00011/2^101 11011 000-2^121 1110 1111-31*2^30 11000 1003*2^80 1111 0000+oo 2.89

A.正确 B.错误,当y为INT_MIN时,x-y溢出 C.正确 D.错误,当x、y、z较大时,32位乘法可能导致结果超出2^53,会导致舍入 E.错误,dx、dz可能为0

2.90 float u2f(unsigned u) { return *(float *) &u; } float fpwr2(int x) { unsigned exp, frac; unsigned u; // 小于最小的非规格化数 if (x exp = 0; frac = 1 exp = 255; frac = 0; } u = exp return f; } return ~sign return f; } return 0 //*2后为无穷 exp = 0xFF; frac = 0; } else //规格化数 exp+=1; return sign 0,只 >>110 => 1,只 >>111 => 1,>>1后加1 #include typedef unsigned float_bits; float_bits float_half(float_bits f) { unsigned sign = f >> 31; unsigned exp = f >> 23 & 0xFF; unsigned frac = f & 0x7FFFFF; unsigned rest = f & 0x7FFFFFFF; if (exp == 0xFF) { //如果f为NAN或无穷,直接返回 return f; } int addition = (frac & 0x3) == 0x3; //向偶数舍入偏置 if (exp == 0) { //非规格化数,= 1; frac += addition; } else if (exp == 1) { //规格化数变为非规格化数 rest >>= 1; rest += addition; exp = rest >> 23 & 0xFF; frac = rest & 0x7FFFFF; } else { //规格化数 exp -= 1; } return sign //小于1,向0舍入 num = 0; } else if (exp >= 31 + bias) { //溢出或(int)f == INT_MIN num = 0x80000000; } else { //向0舍入 E = exp - bias; M = frac | 0x800000; if (E > 23) { num = M if ((i & INT_MIN) != 0) { return 32; } unsigned u = (unsigned)i; int length = 0; while (u >= (1 return (unsigned) -1 >> (32-l); } /*计算float*/ float_bits float_i2f(int i) { unsigned sign, exp, frac, rest, exp_sign , round_part; unsigned bits, fbits; unsigned bias = 0x7F; if (i == 0) { sign = 0; exp = 0; frac = 0; return sign sign = 1; i = -i; } bits = bits_length(i); //计算i的位数 fbits = bits - 1; //尾数位数 exp = bias + fbits; rest = i & bits_mask(fbits); if (fbits //fbits > 23 int offset = fbits - 23; int round_mid = 1 offset; exp_sign = exp //是否舍入位是11 exp_sign += 1; //11…->100… } else { //round_part == round_mid,是否舍入位是10 if ((frac & 0x1) == 1) { exp_sign += 1; //10…1->10…0 } } } return sign


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有