深入理解计算机系统(第二版) 家庭作业 第四章
2013-06-23 22:53
459 查看
4.43
没有正确执行pushl %esp,pushl %esp是将esp当前的内容入栈。
如果REG是esp,那么代码是先减去了esp,然后将减了4以后的REG移入了esp。
修改:(我只能想到利用其它的寄存器)
movl REG, %eax
subl $4, %esp
movl %eax, (%esp)
4.44
也没有正确执行popl %esp,因为popl %esp是将当前栈顶的值放入esp。
如果REG是esp,那么最后得到esp是栈顶值减4之后的值。
movl (%esp), %eax
addl $4, %esp
movl %eax, REG
4.45
我没有按书上给的例子写,而是自己写了一个冒泡。
void bubble(int *data, int count)
{
if(count == 0) return;
int i, j;
int *p, *q;
for(i=count-1; i!=0; i--){
p = data, q = data + 1;
for(j=0; j!=i; ++j)
{
if( *p > *q )
{
int t = *p;
*p = *q;
*q = t;
}
p++, q++;
}
}
}
Y86:(movl就没有区分那么细了,因为太麻烦了。。。)
data:#(从地地址往高地址)
$5, $2, $7, $4, $3, $6, $1, $8
movl $8, %ecx
pushl %ecx #count = 8
movl data, %ecx
pushl %ecx #push data
call bubble
halt
bubble:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %ebx
pushl %edx
movl 8(%ebp), %edx #edx == data
movl 12(%ebp), %esi #esi == count
andl %esi, %esi
je bubbleEnd #count==0
movl $1, %eax
subl %eax, %esi #count--
je bubbleEnd #count==1
OuterLoop:
movl %edx, %ecx # p = data (ecx)
pushl %esi# to save one reg
InnerLoop:
movl (%ecx), %eax
movl 4(%ecx), %ebx
subl %eax, %ebx
movl 4(%ecx), %ebx
jg NoSwap
movl %eax, %ebx #swap, so ebx is greater
movl 4(%ecx), %eax
NoSwap:
movl %eax, (%ecx)
movl %ebx, 4(%ecx)
movl $4, %eax
addl %eax, %ecx
movl $1, %eax
subl%eax, %esi
jne InnerLoop
popl %esi
movl $1, %eax
subl %eax, %esi
jne OuterLoop
bubbleEnd:
popl %edx
popl %ebx
popl %esi
movl %ebp, %esp
popl %ebp
ret
4.46
InnerLoop内改成:(edx是循环利用)
movl (%ecx), %edx
InnerLoop:
movl %edx, %eax
movl 4(%ecx), %ebx
subl %ebx, %eax # compare *p and *(p+1)
cmovl %ebx, %edx #edx is max
movl (%ecx), %eax
cmovg %ebx, %eax #%eax is min
movl %edx, 4(%ecx)
movl %eax, (%ecx)
movl $4, %eax
addl %eax, %ecx
movl $1, %eax
subl %eax, %esi
jne InnerLoop
4.47
我们可以明确的是,这条指令完成的任务为,
ebp <- M4[cur_ebp]
esp <- cur_ebp + 4
取指阶段 icode:ifun = D:0
valP <= PC + 1
译码阶段 valB <= R[%ebp]
执行阶段 valE <= valB + 4
访存阶段 valM <= M4[valB]
写回阶段 R[%esp] <= valE
R[%ebp] <= valM
4.48
取指阶段 icode:ifun = M1[PC] = C:0
rA:rB <= M1[PC+1]
valC <= M4[PC+2]
valP <= PC + 6
译码阶段 valB <= R[rB]
执行阶段 valE <= valB + valC
SetCC
访存阶段
写回阶段 R[rB] <= valE
4.49
4.50
取指
bool need_regids =
icode in { IRRMOVL, IOPL, IPUSHL, IPOPL,
IIRMOVL, IRMMOVL, IMRMOVL, IADDL };
bool need_valC =
icode in { IIRMOVL, IRMMOVL, IMRMOVL, IJXX, ICALL, IADDL };
译码和写回
int srcA = [
icode in { IRRMOVL, IRMMOVL, IOPL, IPUSHL } : rA;
icode in { IPOPL, IRET } : RESP;
1 : RNONE; # Don’t need register
];
int srcB = [
icode in { IOPL, IRMMOVL, IMRMOVL, IADDL } : rB;
icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP;
icode in { ILEAVE } : REBP;
1 : RNONE; # Don’t need register
];
int dstE = [
icode in { IRRMOVL} && Cnd : rB;
icode in { IIRMOVL, IOPL, IADDL } : rB;
icode in { IPUSHL, IPOPL, ICALL, IRET, ILEAVE } : RESP;
1 : RNONE; # Don’t write any register
];
int dstM = [
icode in { IMRMOVL, IPOPL}:rA;
icode in { ILEAVE }: REBP;
1 : RNONE; # Don’t write any register
];
执行
int aluA = [
icode in { IRRMOVL, IOPL } : valA;
icode in { IIRMOVL, IRMMOVL, IMRMOVL, IADDL } : valC;
icode in { ICALL, IPUSHL}:-4;
icode in { IRET, IPOPL, ILEAVE}:4;
# Other instructions don’t need ALU
];
int aluB = [
icode in { IRMMOVL, IMRMOVL, IOPL, ICALL,
IPUSHL, IRET, IPOPL, ILEAVE, IADDL } : valB;
icode in { IRRMOVL, IIRMOVL}:0;
# Other instructions don’t need ALU
];
bool set_cc = icode in { IOPL, IADDL };
访存
int mem_addr = [
icode in { IRMMOVL, IPUSHL, ICALL, IMRMOVL } : valE;
icode in { IPOPL, IRET } : valA;
icode in { ILEAVE } : valB;
# Other instructions don’t need address
];
bool mem_read = icode in { IMRMOVL, IPOPL, IRET, ILEAVE };
4.51 -- 4.56
感觉蛮麻烦的,不想写啊。。。
4.57
A.
发现加载/使用冒险的逻辑公式:
( E_icode in {IMRMOVL, IPOPL} && E_dstM in {d_srcA, d_srcB})
&&
!(E_icode == IMRMOVL && D_icode == IPUSHL);
B.
e_valA = [ (E_icode==IPUSH) && (M_dstM==E_srcA) : m_valM;
1 : E_valA;
];
4.58
版本1,在预测正确的情况下执行7条指令,预测错误时执行9条指令并插入一个bubble。
版本2,执行8条指令,但是在外部循环需要多执行3条指令,否则就需要多用一个寄存器。
暂时没有想到好的办法。
光从内循环看来,版本2平均执行次数比版本1要少,因为可以假设预测错误的概率是50%。
没有正确执行pushl %esp,pushl %esp是将esp当前的内容入栈。
如果REG是esp,那么代码是先减去了esp,然后将减了4以后的REG移入了esp。
修改:(我只能想到利用其它的寄存器)
movl REG, %eax
subl $4, %esp
movl %eax, (%esp)
4.44
也没有正确执行popl %esp,因为popl %esp是将当前栈顶的值放入esp。
如果REG是esp,那么最后得到esp是栈顶值减4之后的值。
movl (%esp), %eax
addl $4, %esp
movl %eax, REG
4.45
我没有按书上给的例子写,而是自己写了一个冒泡。
void bubble(int *data, int count)
{
if(count == 0) return;
int i, j;
int *p, *q;
for(i=count-1; i!=0; i--){
p = data, q = data + 1;
for(j=0; j!=i; ++j)
{
if( *p > *q )
{
int t = *p;
*p = *q;
*q = t;
}
p++, q++;
}
}
}
Y86:(movl就没有区分那么细了,因为太麻烦了。。。)
data:#(从地地址往高地址)
$5, $2, $7, $4, $3, $6, $1, $8
movl $8, %ecx
pushl %ecx #count = 8
movl data, %ecx
pushl %ecx #push data
call bubble
halt
bubble:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %ebx
pushl %edx
movl 8(%ebp), %edx #edx == data
movl 12(%ebp), %esi #esi == count
andl %esi, %esi
je bubbleEnd #count==0
movl $1, %eax
subl %eax, %esi #count--
je bubbleEnd #count==1
OuterLoop:
movl %edx, %ecx # p = data (ecx)
pushl %esi# to save one reg
InnerLoop:
movl (%ecx), %eax
movl 4(%ecx), %ebx
subl %eax, %ebx
movl 4(%ecx), %ebx
jg NoSwap
movl %eax, %ebx #swap, so ebx is greater
movl 4(%ecx), %eax
NoSwap:
movl %eax, (%ecx)
movl %ebx, 4(%ecx)
movl $4, %eax
addl %eax, %ecx
movl $1, %eax
subl%eax, %esi
jne InnerLoop
popl %esi
movl $1, %eax
subl %eax, %esi
jne OuterLoop
bubbleEnd:
popl %edx
popl %ebx
popl %esi
movl %ebp, %esp
popl %ebp
ret
4.46
InnerLoop内改成:(edx是循环利用)
movl (%ecx), %edx
InnerLoop:
movl %edx, %eax
movl 4(%ecx), %ebx
subl %ebx, %eax # compare *p and *(p+1)
cmovl %ebx, %edx #edx is max
movl (%ecx), %eax
cmovg %ebx, %eax #%eax is min
movl %edx, 4(%ecx)
movl %eax, (%ecx)
movl $4, %eax
addl %eax, %ecx
movl $1, %eax
subl %eax, %esi
jne InnerLoop
4.47
我们可以明确的是,这条指令完成的任务为,
ebp <- M4[cur_ebp]
esp <- cur_ebp + 4
取指阶段 icode:ifun = D:0
valP <= PC + 1
译码阶段 valB <= R[%ebp]
执行阶段 valE <= valB + 4
访存阶段 valM <= M4[valB]
写回阶段 R[%esp] <= valE
R[%ebp] <= valM
4.48
取指阶段 icode:ifun = M1[PC] = C:0
rA:rB <= M1[PC+1]
valC <= M4[PC+2]
valP <= PC + 6
译码阶段 valB <= R[rB]
执行阶段 valE <= valB + valC
SetCC
访存阶段
写回阶段 R[rB] <= valE
4.49
4.50
取指
bool need_regids =
icode in { IRRMOVL, IOPL, IPUSHL, IPOPL,
IIRMOVL, IRMMOVL, IMRMOVL, IADDL };
bool need_valC =
icode in { IIRMOVL, IRMMOVL, IMRMOVL, IJXX, ICALL, IADDL };
译码和写回
int srcA = [
icode in { IRRMOVL, IRMMOVL, IOPL, IPUSHL } : rA;
icode in { IPOPL, IRET } : RESP;
1 : RNONE; # Don’t need register
];
int srcB = [
icode in { IOPL, IRMMOVL, IMRMOVL, IADDL } : rB;
icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP;
icode in { ILEAVE } : REBP;
1 : RNONE; # Don’t need register
];
int dstE = [
icode in { IRRMOVL} && Cnd : rB;
icode in { IIRMOVL, IOPL, IADDL } : rB;
icode in { IPUSHL, IPOPL, ICALL, IRET, ILEAVE } : RESP;
1 : RNONE; # Don’t write any register
];
int dstM = [
icode in { IMRMOVL, IPOPL}:rA;
icode in { ILEAVE }: REBP;
1 : RNONE; # Don’t write any register
];
执行
int aluA = [
icode in { IRRMOVL, IOPL } : valA;
icode in { IIRMOVL, IRMMOVL, IMRMOVL, IADDL } : valC;
icode in { ICALL, IPUSHL}:-4;
icode in { IRET, IPOPL, ILEAVE}:4;
# Other instructions don’t need ALU
];
int aluB = [
icode in { IRMMOVL, IMRMOVL, IOPL, ICALL,
IPUSHL, IRET, IPOPL, ILEAVE, IADDL } : valB;
icode in { IRRMOVL, IIRMOVL}:0;
# Other instructions don’t need ALU
];
bool set_cc = icode in { IOPL, IADDL };
访存
int mem_addr = [
icode in { IRMMOVL, IPUSHL, ICALL, IMRMOVL } : valE;
icode in { IPOPL, IRET } : valA;
icode in { ILEAVE } : valB;
# Other instructions don’t need address
];
bool mem_read = icode in { IMRMOVL, IPOPL, IRET, ILEAVE };
4.51 -- 4.56
感觉蛮麻烦的,不想写啊。。。
4.57
A.
发现加载/使用冒险的逻辑公式:
( E_icode in {IMRMOVL, IPOPL} && E_dstM in {d_srcA, d_srcB})
&&
!(E_icode == IMRMOVL && D_icode == IPUSHL);
B.
e_valA = [ (E_icode==IPUSH) && (M_dstM==E_srcA) : m_valM;
1 : E_valA;
];
4.58
版本1,在预测正确的情况下执行7条指令,预测错误时执行9条指令并插入一个bubble。
版本2,执行8条指令,但是在外部循环需要多执行3条指令,否则就需要多用一个寄存器。
暂时没有想到好的办法。
光从内循环看来,版本2平均执行次数比版本1要少,因为可以假设预测错误的概率是50%。
相关文章推荐
- 深入理解计算机系统(第二版) 家庭作业 第六章
- 深入理解计算机系统(第二版) 家庭作业 第七章
- 深入理解计算机系统(第二版) 家庭作业 第八章
- 深入理解计算机系统(第二版) 家庭作业 第二章
- 深入理解计算机系统(第二版) 家庭作业 第十一章
- 深入理解计算机系统家庭作业第四章(4.43-4.54)
- 深入理解计算机系统(第二版) 家庭作业 第五章
- CSAPP(深入理解计算机系统)第二版家庭作业答案-第三章
- CSAPP(深入理解计算机系统)第二版家庭作业答案-第二章
- 深入理解计算机系统(第二版) 家庭作业 第十章
- 深入理解计算机系统(第二版) 家庭作业 第三章
- 深入理解计算机系统(第二版)家庭作业解答
- 深入理解计算机系统_3e 第四章家庭作业(部分) CS:APP3e chapter 4 homework
- 深入理解计算机系统第二版家庭作业2.66
- 深入理解计算机系统 家庭作业 2.78
- 深入理解计算机系统 家庭作业 2.80
- 深入理解计算机操作系统(第二版) 读书笔记(第一章 计算机系统漫游)
- 深入理解计算机系统_3e 第二章家庭作业 CS:APP3e chapter 2 homework
- 深入理解计算机系统第二版习题解答CSAPP 2.18
- 深入理解计算机系统第二版习题解答CSAPP 2.5