4.43
A:沒有,其實這段代碼中REG能代替除了棧指針%esp以外的寄存器,但是%esp不行。這相當于将%esp先減去4,再将這個減去4的值壓入棧。和pushl %esp直接将其 壓入棧的情況不相符。
B:movl REG,%edx;
subl $4,%esp;
movl %edx,(%esp) ;
4.44
A:沒有,當REG指的是%esp時,這段代碼相當于将%esp裡的值複制到%esp裡,再将%esp加4,但是并沒有将原來的棧頂的結果儲存到%esp裡。和popl %esp的情況不符合。
B:movl (%esp), %edx;
addl $4,%esp;
movl (%esp),REG;
4.47
取值:icode:ifun<-----M1[pc]=D:0 #題目中的已知條件
valP<-----pc+1 #這個指令隻有表明指令類型的一個位元組,是以下一條指令的位址隻需要加上1.
譯碼:valA<----R[%ebp] #因為本條leave指令相當于 rrmovl %ebp,%esp;popl %esp;是以讀取%ebp的位址值是必須的。
valB<----R[%esp] #因為popl %esp;是以讀取%esp的位址值是必須的。
執行:valE<-----valB+4 #彈棧需要将棧頂指針%esp增加4.
訪存:valM<----M4[valA] #将%ebp的值讀入存儲器
寫回:R[%esp]<----valE #棧頂指針下移
R[%ebp]<----valM #将棧頂的值放入%esp中
更新PC:PC<----valP #下一條指令的位址
思路:前提:leave相當于rrmovl %ebp,%esp;popl %ebp;參照了書上popl指令在順序中的計
算。在這道題中思考明白了一個問題,就是rrmovl rA,%esp;與pushl rA;的差別。前者是将rA的位址複制到棧頂指針指向的位置,指針并不移動,後者是将rA的位址壓入棧,指針位址值減去4,指針上移。
4.48
取值:icode:ifun<-----M1[pc]=C:0 #題目中的已知條件
rA:rB<----M1[pc+1] #指令類型一個位元組,是以寄存器辨別符的起始位址隻需要+1
vlaC<-----M4[pc+2] #指令類型+寄存器辨別符=2個位元組,是以常數字的起始位址隻需要pc+2
valP<-----pc+6 #指令類型+寄存器标示符+常數字=1+1+4=6位元組,是以下一條指令的位址需要加上6.
譯碼:valA<----R[rB] #因為将一個常數字與寄存器的值相加并複制到寄存器,需要讀取寄存器中的值
執行:valE<-----valA+valC #計算寄存器和常數字之和的值.
Set CC #辨別标志位
訪存:
寫回:R[rB]<----valE #将計算出來的值複制到寄存器中
思路:前提:iaddl V,rB;相當于将兩者值相加,并把值移動到寄存器rB中。參照了irmovl和opl的順序計算。
8.23
原因是因為在第一個信号發給父程序之後,父程序進入handler,并且阻塞了SIGUSR2,第二個信号依然可以發送,然而,之後的3個信号便會被抛棄了。因為是連續發送,是以很可能是沒等上下文切換,這5個信号就同時發送了。是以隻有2個信号被接收。
8.24
#include "csapp.h"
#define N
2
int main()
{
int status, i;
pid_t pid;
char errorInfo[128];
/* 建立N個子程序 */
for(i=0;i<N;i++)
if ((pid = Fork()) == 0) //子程序
exit(100+i);
/* 不按照特定順序 */
while ((pid = waitpid(-1, &status, 0)) > 0) {
if (WIFEXITED(status))
printf("child %d
terminated normally with exit status=%d\n",
pid, WEXITSTATUS(status));
else if(WIFSIGNALED(status))
{
//為什麼隻在寫隻讀文本時才報錯?下面的程式對所有異常退出都會提示
terminated by signal %d: ",
pid, WTERMSIG(status) );
psignal(WTERMSIG(status), errorInfo); //psignal會列印sig的資訊
}
}
/* The only normal termination is if there are no more children */
if (errno != ECHILD)
unix_error("waitpid
error");
exit(0);
}
12.24 不是。調用了标準I/O函數的都不是可重入函數。
12.25 不是線程安全。不是可重入函數。因為使用了全局變量。
12.29不會發生死鎖。無論是線程一先執行還是線程2先執行,都能順利地執行完。因為對于a.b.c來說在每一個線程中,P,V都是一一對應的。
具體分析:如果先執行線程一:a=0;b=0;b=1;c=0;c=1;a=1;線程1結束,開始執行線程2;c=0;b=0;b=1;c=1.
如果先執行線程二:c=0;b=0;b=1;c=1;線程2結束,執行線程1;a=0;b=0;b=1;c=0;c=1;a=1.