CSAPP第7章家庭作业参考答案
7.6
buf 有 m.o 外部 .data
bufp0 有 swap.o 全局 .data
bufp1 有 swap.o 局部 .bss
incr 有 swap.o 局部 .text
count 有 swap.o 局部 .bss
swap 有 swap.o 全局 .text
temp 無
7.7
在bar5.c中聲明x的時候使用static ,使其鏈接為內部鏈接:
7.8
A.
(a) REF(main.1) --> DEF(main.1)
(b) REF(main.2) --> DEF(main.2)
B.
(a) REF(x.1) --> 未知
(b) REF(x.2) --> 未知
C.
(a) REF(x.1) --> 錯誤
(b) REF(x.2) --> 錯誤
7.9
foo6.c中main符號是一個函數名,是強符號;bar6.c中main是一個未初始化的全局變量,是若符號。兩者鏈接后鏈接器會選擇強符號,也就是foo6.c中的main,這個main代表main函數的起始地址,因此會打印這個地址的數據,也就是main函數中第一條指令的機器碼。
7.10
ld p.o libx.a p.o
ld p.o libx.a liby.a libx.a
ld p.o libx.a liby.a libx.a libz.a
7.11
未初始化的全局變量在可執行文件的數據段中不占用空間,但是當程序裝載到內存后會占用空間。因此多出的一個字節可能是全局變量占用的。
7.12
0x4004e0+0xa=0x4004ea
0x4004ea e8 00 00 00 00 callq e
0x4004ef …
因此執行callq時rip中的值為0x4004ef
所以call的偏移=0x4004f8-0x4004ef=0x9
上面是錯誤的做法!!
正確的做法是,利用下面的公式
首先,重定位類型中包含PC32,因此這個重定位采用PC相對尋址。
先計算出引用所在的內存地址:
refaddr = ADDR(.text) + r.offset = 0x4004e0 + 0xa = 0x4004ea
注意,上面這個refaddr并不是call指令所在的內存地址!
實際編譯后的代碼段是這樣的:
0x4004e9 e8 00 00 00 00 callq e
call指令機器碼的第一個字節的地址為0x4004e9,而它之后的一個字節(也就是"引用"的所在點)才是0x4004ea。也就是說,上面計算出的refaddr并不是call指令的操作碼所在地址,而是"操作數"所在的地址。這部分內容很難理解,也很容易出錯,但是只要按照上面的公式來計算就沒有問題。
然后計算偏移:
refptr = (unsigned)(ADDR(r.symbol) + r.addend - refaddr) = 0x4004f8 + (-4) - 0x4004ea = 0xa
因此第一問答案是0xa
同樣的方法計算第二問:
refaddr = 0x4004d0 + 0xa = 0x4004da
refptr = 0x400500 + (-4) - 0x4004da =0x22
7.13
不會
總結
以上是生活随笔為你收集整理的CSAPP第7章家庭作业参考答案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在C语言中巧妙地避免使用if语句?
- 下一篇: CSAPP第4章家庭作业参考答案