关于csapp第三章的一个问题

    最近在读csapp第三章的时候,习题3.49中有一段汇编代码让我十分费解。具体汇编代码如下:

看了许久我始终不明白为什么第五行中计算数组大小时采用8n + 22。毕竟按照我的理解只需要8n就够了。

然后按照题目中的提示,回忆了一下第二章中计算右移时的操作。通常会在右移时加上对应的偏移量。于是我似乎明白了点什么。原来右移的时候为了避免在负数进行右移的时候因为符号位的关系导致右移结果错误,于是通常会加上对应的数据类型的偏移量。由于后面进行了右移的操作故数组大小从8n变成8n+7。那多出来的15又是怎么来的呢 ?仔细看了看第六行的操作。%rax中的值会跟-16进行与操作。这一步是为了对数组大小进行所占字节进行对齐操作。从汇编代码中可以发现,当前对齐的位数应该为16.故为了在进行与操作时避免负数的符号位造成错误,故也需要给对应的值添加上偏移量15.这样一来数组大小所需要的空间就变成了8n+22。所以当我把动态创建的数组类型分别修改为int,short,char时,所需要的数组大小分别为4n+18,2n+16,n+15。简单的一个创建数组,却包含了第二章中的位运算技巧和第三章中提到的对齐策略。微小的地方总是蕴含着很多细节呢!


### CSAPP 第三章 课后习题解答与分析 #### 函数 `aframe` 的栈帧结构解析 在讨论函数 `aframe` 的实现时,注意到此函数调用了库函数 `alloca` 动态分配局部数组 `p` 所需的空间。这种动态内存分配方式使得编译器无法提前知晓所需的具体空间大小,因此引入了变长栈桢的概念来处理这种情况。 当执行到第4行代码时,栈指针被设定为值 \(s_1\);而在第7行处再次调整至新的位置 \(s_2\)。此时,在这两个地址间可能存在一段未使用的额外空间 \(e_1\)。到了第9行,则正式将变量 `p` 指向这段由 `alloca` 分配出来的缓冲区首部[^2]。 ```c void aframe(int n) { int *p; // ... p = (int *)alloca(n * sizeof(int)); } ``` #### 数据成员偏移量计算实例 对于联合体(union)类型的元素访问操作而言,由于其内部各字段共享同一块存储区域,所以不同字段之间的相对位移关系变得尤为重要。例如给定如下定义: ```c typedef union { struct { long y; char z[8]; } e1; struct { short x; long next;} e2; } ele_t; ``` 针对上述数据结构,可以得出以下结论: - 成员 `e1.p` 和 `e1.y` 的字节偏移分别为0和8; - 同样地,`e2.x` 及 `e2.next` 则分别位于偏移0以及8的位置上[^3]。 #### 进一步探讨过程间的参数传递机制 考虑这样一个场景——通过指针间接修改另一个对象的内容。具体来说就是下面这个名为 `proc` 的C语言子程序,它接收一个指向联合体类型 `ele` 的指针作为输入,并利用箭头运算符完成特定逻辑的操作。 ```c void proc(ele_t *up) { up->e2.x = *(up->e2.next->e1.p) - up->e2.next->e1.y; } ``` 在这个例子中,假设传入的对象已经初始化完毕并含有有效数值,那么该语句的作用即是从指定路径读取两个整数相减的结果赋值给目标域 `x`。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值