CS:APP 第七章作业

CS:APP 第七章作业

7.6

符号 .symtab条目? 符号类型 定义符号的模块
buf 外部 (Global) m.o .data
bufp0 全局 (Global) swap.o .data
bufp1 局部 (Local) swap.o .bss
swap 全局 (Global) swap.o .text
temp - - -
incr 局部 (Local) swap.o .text
count 局部 (Local) swap.o .bss

7.7

为了避免 bar5.c 中的 x 覆盖 foo5.c 中的 y,需将 bar5.c 中的 x 声明为 static(使其成为模块局部变量,不参与外部链接)。

C

1
2
3
4
5
6
7
/* bar5.c */
static double x;

void f()
{
x = -0.0;
}

7.8

A.

(a) REF(main.1) $\rightarrow$ DEF(main.1)

(b) REF(main.2) $\rightarrow$ DEF(main.2)

解析:模块 2 的 main 是 static(局部),模块 1 是全局,两者不冲突。

B.

(a) 未知 (Unknown)

(b) 未知 (Unknown)

解:两个模块都定义了弱符号 x(未初始化),链接器可任意选择,行为不确定。

C.

(a) 错误 (Error)

(b) 错误 (Error)

解:两个模块都定义了强符号 x(已初始化),违反规则 1。


7.9

该现象由链接器的符号解析机制与C语言类型系统的弱一致性共同导致。在链接过程中,foo6.c 中定义的函数 main 属于强符号(Strong Symbol),而 bar6.c 中未初始化的变量 main 属于弱符号(Weak Symbol);根据链接器的解析规则(规则2),链接器会将符号引用解析为已定义的强符号,即 foo6.c 中的函数地址 1。尽管 bar6.c 此时将 main 视为 char 类型数据,但程序运行时实际上访问的是代码段中 main 函数的入口地址。因此,printf 语句读取并输出了该地址处的第一个字节,即 main 函数第一条机器指令的编码;在 x86-64 Linux 系统架构下,函数序言(Prologue)指令(如 subqpushq)通常以十六进制 0x48(REX 前缀)开头,从而导致程序最终输出字符串“0x48”。


7.10

根据依赖关系排序(定义在引用之后):

A. gcc p.o libx.a

B. gcc p.o libx.a liby.a libx.a

解:x 依赖 y,y 依赖 x,需再次搜索 x。

C. gcc p.o libx.a liby.a libz.a libx.a

解:链式依赖 x->y->z->x,需再次搜索 x 以解析 z 中的引用。


7.12

A.

Target (swap) = 0x4004f8

PC (next instruction) = 0x4004e0 (text start) + 0xe (offset of next inst) = 0x4004ee

Value = Target - PC = 0x4004f8 - 0x4004ee = 0xa (即 10)

机器码表示:0a 00 00 00

B.

Target (swap) = 0x400500

PC (next instruction) = 0x4004d0 + 0xe = 0x4004de

Value = Target - PC = 0x400500 - 0x4004de = 0x22 (即 34)

机器码表示:22 00 00 00