深入理解计算机系统 第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
