深入理解计算机系统 第7章 习题解析
这次更新第7章习题。
参考资料:
7.6
代码:
extern int buf[];
int *bufp0 = &buf[0];
static int *bufp1;
static void incr()
{
static int count = 0;
count++;
}
void swap()
{
int temp;
incr();
bufp1 = &buf[1];
temp = *bufp0;
*bufp0 =*bufp1;
*bufp1 = temp;
}
表格:
符号 | swap.o.symtab条目? | 符号类型 | 定义符号的模块 | 节 |
---|---|---|---|---|
buf | 是 | 外部 | m.o | .data |
bufp0 | 是 | 全局 | swap.o | .data |
bufp1 | 是 | 局部 | swap.o | .bss |
swap | 是 | 全局 | swap.o | .text |
temp | 否 | 无 | 无 | 无 |
incr | 是 | 局部 | swap.o | .text |
count | 是 | 局部 | swap.o | .bss |
7.7
将double x设置为static变量。
bar5.c:
/* $begin bar5 */
/* bar5.c */
static double x;
void f()
{
x = -0.0;
}
/* $end bar5 */
foo5.c:
/* $begin foo5 */
/* foo5.c */
#include <stdio.h>
void f(void);
int y = 15212;
int x = 15213;
int main()
{
f();
printf("x = 0x%x y = 0x%x \n",
x, y);
printf("x = %d y = %d \n",
x, y);
return 0;
}
/* $end foo5 */
编译:
gcc -Wall -Og -o foobar5 foo5.c bar5.c
运行:
x = 0x3b6d y = 0x3b6c
x = 15213 y = 15212
7.8
A
代码:
/* Module 1 */
int main()
{
}
/* Module 2*/
static int main = 1;
int p2()
{
}
- REF(main.1)->DEF(main.1)
- REF(main.2)->DEF(main.1)
原因:
main.1是强符号,main.2是弱符号。
B
代码:
/* Module 1 */
int x;
void main()
{
}
/* Module 2*/
double x;
int p2()
{
}
- REF(x.1)->未知
- REF(x.2)->未知
原因:
x.1和x.2都是弱符号。
C
/* Module 1 */
int x = 1;
void main()
{
}
/* Module 2*/
double x = 1.0;
int p2()
{
}
- REF(x.1)->错误
- REF(x.2)->错误
原因:
x.1和x.2都是弱符号。
7.9
根据规则2,如果有一个强符号和多个弱符号同名,那么选择强符号;此处main在foo6.c中已经定义为强符号。
编译:
gcc -Wall -Og -o foobar6 foo6.c bar6.c
运行结果:
$ ./foobar6
0x48
7.10
思路:保证文件的相对依赖顺序即可。
A
gcc p.o libx.a
B
gcc libx.a liby.a libx.a
C
gcc p.o libx.a liby.a libx.a libz.a
7.11
.bss段或者对齐。
7.12
R_X86_64_PC32
A
给定:
ADDR(s) = ADDR(.text) = 0x4004e0
ADDR(r.symbol) = ADDR(swap) = 0x4004f8
可得:
refaddr = ADDR(s) + r.offset
= 0x4004e0 + 0xa
= 0x4004ea
*refptr = (unsigned) (ADDR(r.symbol) + r.addend - refaddr)
= (unsigned) (0x4004f8 + (-4) - 0x4004ea)
= (unsigned) (0xa)
所以引用的值为0xa。
B
给定:
ADDR(s) = ADDR(.text) = 0x4004d0
ADDR(r.symbol) = ADDR(swap) = 0x400500
可得:
refaddr = ADDR(s) + r.offset
= 0x4004d0 + 0xa
= 0x4004da
*refptr = (unsigned) (ADDR(r.symbol) + r.addend - refaddr)
= (unsigned) (0x400500 + (-4) - 0x4004da)
= (unsigned) (0x22)
所以引用的值为0x22。
7.13
参考资料:
https://www.runoob.com/linux/linux-comm-ar.html
A
libm.a:
$ whereis libm.a
libm: /usr/lib/x86_64-linux-gnu/libm.a /usr/lib/x86_64-linux-gnu/libm.so
$ ar t /usr/lib/x86_64-linux-gnu/libm.so
ar: /usr/lib/x86_64-linux-gnu/libm.so: File format not recognized
lib.c:
$ whereis lib.c
lib: /usr/local/lib /mnt/c/Program Files/Racket/lib
B
编译:
gcc -Og -o main1.out main.c
gcc -Og -g -o main2.out main.c
反汇编:
$ objdump -d main1.out > main1ass
$ objdump -d main2.out > main2ass
比较结果:
$ diff main1ass main2ass
2c2
< main1.out: file format elf64-x86-64
---
> main2.out: file format elf64-x86-64
所以对于此例,内容相同。
C
ldd main1.out
linux-vdso.so.1 (0x00007ffc905eb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fac69405000)
/lib64/ld-linux-x86-64.so.2 (0x00007fac699f8000
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Doraemonzzz!
评论
ValineLivere