深入理解计算机系统家庭作业第三章
来源:互联网 发布:v2视频会议软件下载 编辑:程序博客网 时间:2024/04/29 03:09
***3.54
***写出decode2的原型
*/
int decode2(int x ,int y, int z){int a = z - y;int b = (a << 15) >> 15;return (x ^ a) * b;}
/*
***3.55
*/
typedef long long ll_t;
void store_prod(ll_t *dest, ll_t x, int y){
*dest = x*y;
}
// dest at %ebp+8, x at %ebp + 12, y at %ebp + 20movl 12(%ebp), %esi //将x的低位存到%esimovl 20(%ebp), %eax //将y存到%eaxmovl %eax, %edx sarl $31, %edx //将(y >> 31)存到%edxmovl %edx, %ecximull %esi, %ecx //计算x_low * (y >> 31)存到%ecxmovl 16(%ebp), %ebx //将x的高位存到%ebpimull %eax, %ebx //计算x_high * yaddl %ebx, %ecx //计算 x_high * y + x_low * (y >> 31) 存到%ecxmull %esi //计算y * x_low 的无符号64位乘积leal (%ecx, %edx), %edx //将64位乘积的高位与x_high * y + x_low * (y >> 31)得到最终结果的高位movl 8(%ebp), %ecxmovl %eax, (%ecx)movl %edx, 4(%ecx) //将结果写入目的内存地址
说明:
该汇编代码其实是y扩展至64位再进行两个64位数的乘积然后进行截断得到的。
事实上有:
y *{signed} x =
(y_high * 2^32 + y_low) *{signed} (x_high * 2^32 + x_low) =
y_high *{signed} x_high * 2^64 +
y_high *{signed} x_low * 2^32 +
y_low *{signed} x_high * 2^32 +
y_low *{signed} x_low(有符号的x_low与无符号的x_low相等,故可用mull指令)
而y_high *{signed} x_high由于乘以2^64,所以对结果不会产生影响。
/*
***3.56写出loop函数原型
*/
int loop(int x, int n){int result = 0x55555555;int mask;for(mask = 0x80000000;mask !=0; mask = (unsigned)mask >> (n & 0xFF)){result ^= x & mask;}return result;}
/*
***3.57用条件传送指令写函数cread_alt
*/
int cread_alt(int *xp){ int a = 0; return *(xp ? xp : &t);}
思路:原来函数中的错误就是无论xp是否为NULL,都对其发生了间接引用。将引用符号放在最外面,那么当xp为NULL时,
条件传送指令将临时变量a的地址传送至%eax,故不会产生对xp的间接引用。下面贴上产生的汇编代码:
subl$16, %esp.cfi_def_cfa_offset 20movl20(%esp), %eaxmovl$0, 12(%esp)leal12(%esp), %edxtestl%eax, %eaxcmove%edx, %eaxmovl(%eax), %eaxaddl$16, %esp.cfi_def_cfa_offset 4 ret
/*
***3.58
*/
int switch3(int *p1,int *p2,mode_t action){int result = 0;switch(action){case MODE_A:result = *p1;*p1 = *p2;break;case MODE_B:result = *p1 + *p2;*p2 = result;break;case MODE_C:*p2 = 15;result = *p1;break;case MODE_D:*p2 = *p1;result = 17;break;case MODE_E:result = 17;break;default:result = -1;break;}return result;}
/*
***3.59根据反汇编代码补全c语言代码
*/
int switch_prob(int x,int n){int result = x;switch(n){case 40:case 42:result <<=3;break;case 43:result >>=3break;case 44:result = (result<<3) - result;case 45:result *= result;result += 17;break;default:result += 17;break;}return result;}
/*
***3.60
*/
A. &A[i][j][k] = Xa + L(i * S*T + j * T + K)
B. 根据汇编代码可得,9*j存在寄存器%eax中,63*i存在寄存器%edx中,对照公式可得S=7,T=9;
最后一句movl $2772 %eax 可知R = 2772/S/T/4 = 11
/*
***循环中的值的数量从6个减少到5个
*/
int car_prod_ele(int n,int A[n][n],int B[n][n],int i,int k){int j;int result = 0;int *ap = A[i];int *bp = &B[0][k];for(j = 0; j < n; j++){result += *ap * *bp;ap++;bp += n;}return result;}
这题没有想到很好的解法,以上代码经测试是将4n放到寄存器%ebp当中,实际上并没有减少循环值的数量,望高人指点。
/*
***3.62
*/
A. M的值为19
B. %edi保存i,%ecx保存j
C.
void transpose(int A[M][M]){int i,j;for(i = 0;i < M;i++){int *p1 = &A[0][i];for(j = 0;j < i;j++){int *p2 = &A[i][0];int t = *p1; //交换对称的两个值*p1 = *p2;*p2 = t;p1 += M; //改变两个元素的指针p2 += 1;}}}
/*
***3.63
*/
E1 = 3n
E2 = 2n - 1
说明:%esi中存放的值为3n,再对照18行可知E1 = 3n;
每次指针的值变化为8n - 4,可知E2 = 2n - 1。
/*
***3.64
*/
A. 8(%ebp)存放返回值result的地址;12(%ebp)存放s1.p;16(%ebp)存放s1.v。
B. 从高到低依次为s2.sum,s2.prod,s1.v,s1.p,&s2
C. 传递结构体参数时,结构体各参数从高到低依次压入栈中
D. 在8(%ebp)处有一个指向返回值结构体的指针,指针的值作为返回地址,根据返回地址写入值
/*
***3.65
*/
A=3
B=7
首先分析B,t的首地址和u的首地址相差20个字节,t本身占4字节,所以short数组s[B]占16个字节,根据四字节对齐的原则,可知B=7或8;
short x[A][B]占44个字节,当B=8时,A无解,当B=7时,可得A=3.
/*
***3.66
*/
A. CNT = 7;
B. struct a_struct{
int idx;
int x[6];
}
这个题最难的地方是汇编代码的第十行,对照汇编代码和C代码可知,汇编代码的第十二行对应C代码的第九行,汇编代码的十三行对应C代码的十一行。
经过分析(事实上带有一些猜测),第十行add的第一个操作数就是ap->idx的值,加上7i的原因是a_struct中有7个整型变量(这与我们计算ap->idx的地址
为bp + 28i + 4)也是吻合的;然后我们分析汇编代码的十三行,前面的0x8应该看做0x4 + 0x4,第一个0x4是b_struct中left占的字节数,第二个0x4是a_struct
中idx占的字节数,所以可知idx是结构体第一个变量,另外,x是长度为6的数组。
/*
***3.67
*/
A. 下列字段的偏移量值是多少(以字节为单位)
e1.p: 0
e1.x: 4
e2.y: 0
e2.next: 4
B. 这个结构总共需要8个字节
C.
void proc (union ele *up){up->e2.next->e1.x = *(up->e2.next->e1.p) - up->e2.y;}
/*
***3.68写一个good_echo函数,对任意长度的输入行都能工作(即时超过了缓冲区)
*/
#define N 50void good_echo(){char buf[N];while(fgets(buf,N,stdin) != NULL){for(int i = 0;i < N;i++){if(buf[i] == '1')return;if(buf[i] == '\0')break;putchar(buf[i]);}}}
/*
***3.69写出函数trace
*/
A. 给出该函数的C版本,使用while循环
long trace(tree_ptr tr){long result = 0;while(tp){result = tp->val;tp = tp->left;}return result;}
B. 该函数得到最左边叶子的val值。
/*
***3.70
*/
A. 生成这个函数的C版本
long traverse(tree_ptr tp){if(!tp)return 0x7fffffffffffffff;long min_left = traverse(tp ->left);long min_right = traverse(tp ->right);long min = min_left < min_right ? min_left : min_right;min = min < (tp ->val)? min : (tp ->val);return min;}
B. 这个函数是求树中val的最小值,若为空树,则返回0x7fffffffffffffff;
- 深入理解计算机系统家庭作业第三章
- 《深入理解计算机系统第三版》第三章家庭作业参考答案
- 深入理解计算机系统(第二版) 家庭作业 第三章
- 深入理解计算机系统家庭作业第五章
- 深入理解计算机系统家庭作业第六章
- 《深入理解计算机系统》家庭作业
- 《深入理解计算机系统》(原书第三版)家庭作业第三章(3.59)解答
- 《深入理解计算机系统》(原书第三版)家庭作业第三章(3.63)解答
- 《深入理解计算机系统》(原书第三版)家庭作业第三章(3.68)解答
- 《深入理解计算机系统》(原书第三版)家庭作业第三章(3.69)解答
- CSAPP(深入理解计算机系统)第二版家庭作业答案-第三章
- 深入理解计算机系统(第二版) 家庭作业 第四章
- 深入理解计算机系统(第二版) 家庭作业 第五章
- 深入理解计算机系统(第二版) 家庭作业 第六章
- 深入理解计算机系统(第二版) 家庭作业 第七章
- 深入理解计算机系统(第二版) 家庭作业 第八章
- 深入理解计算机系统(第二版) 家庭作业 第九章
- 深入理解计算机系统(第二版) 家庭作业 第十章
- 股票
- [小技巧] svn 里误添加文件后的恢复
- ActivityNotFoundException: Unable to find explicit activity class
- Java判断中文乱码
- 机房收费系统——报表(2)
- 深入理解计算机系统家庭作业第三章
- 策略中学习【LSM】编写规则
- 由height数组构造lcp(i,j)
- Linux视频设备驱动常用控制命令使用说明
- 关于 ubantu与 linux arm开发板的 tcp soket 通信
- MySQL正则表达式
- What's a doctype do?
- qemu中的临时快照(-snapshot)
- MyEclipse + Maven开发Web工程的详细配置过程