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 | /* bar5.c */ |
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)指令(如 subq 或 pushq)通常以十六进制 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