2017-2018-1 20152515 《信息安全系统设计基础》第14周学习总结

2017-2018-1 学号 《信息安全系统设计基础》第14周学习总结

教材学习内容总结

这本书中第四章的内容感觉对我来说有点抽象,比如SEQ,比如流水线,觉得自己似懂非懂。所以我今天重新学习这一章。


Y86-64指令

  • movq 前面的两个字母是在显式的指定源操作数和目的操作数的格式,第一位是源操作数,第二位是目的操作数。

    • irmovq
    • rrmovq
    • mrmovq
    • rmmovq
  • 整数操作指令:它们只对寄存器数据进行操作(IA32允许对存储器数据进行这些操作)。这些指令会设置三个条件码:ZF-零 SF-符号 OF-溢出

    • addq
    • subq
    • andq
    • xorq
  • 跳转指令:根据分支指令的类型和条件码的设置来选择分支,分支条件和IA32一样。
    - jmp
    - jle
    - jl
    - je
    - jne

    • jg
  • 条件传送指令: 这些指令的格式与寄存器-寄存器传送指令rrmovl一样,只有当条件码满足所需要的约束时,才会更新目的寄存器的值。

    • cmovle
    • cmovl
    • cmove
    • cmovne
    • cmovge
    • cmovg
  • call指令:call指令将返回地址入栈,然后跳到目的地址,ret 从这样的过程调用中返回。

  • ret指令:从这样的过程调用中返回。

  • pushq/popq:实现入栈和出栈

  • halt指令: 停止指令的执行,执行此指令会导致处理器停止,并将状态码设置为HLT。

SEQ抽象视图

  • 硬件结构

Y86异常

名字 含义
1 AOK 正常操作(除此之外的任何状态都会使得处理器停止执行指令)
2 HLT 处理器执行halt指令
3 ADR 遇到非法地址
4 INS 遇到非法指令

新的收获

流水线冒险

关于异常处理的细节问题:

  • 三个问题
  • 如何通过程序来判断

练习

  • 确定下面的Y86指令序列的字节编码。.pos 0x100表明这段代码的起始地址应该是0x100
irmovl $15,%ebx
rrmovl %ebx,%ecx
loop:
rmmovl %ecx,-3(%ebx)
addl %ebx,%ecx
jmp loop

解答:

irmovl $15,%ebx ##30f30f000000
rrmovl %ebx,%ecx ##2031
loop:
rmmovl %ecx,-3(%ebx) ##4013fdffffff
addl %ebx,%ecx ##6031
jmp loop ##7008010000

注意最后一个指令:第一条指令需要6个字节,而第二条指令需要2个字节,因此,循环的目标地址为0x00000108.以反向顺序来写就是08 01 00 00.

  • 确定下列每一个字节序列所编码的Y86指令序列。如果有不合法字节,指出其位置。

A.

0x100:30f3fcffffff    ##irmovl $-4,%ebx
0x106:406300080000    ##rmmovl %esi,0x800(%ebx)
0x10c:00              ##halt

B.

0x200:a06f           ##pushl %esi
0x202:8008020000     ##call proc
0x207:00             ##halt
0x208:               ##proc:
0x208:30f30a000000   ##irmovl $10,%ebx
0x20e:90             ##ret

C.

0x300:505407000000  ##mrmovl 0x7(%esp),%ebp
0x306:10            ##nop
0x307:f0            ##非法
0x308:b01f          ##popl %ecx
  • 修改P238图4-6中的Y86代码,使其能计算一个数组的绝对值的和。内循环中使用条件传送。

源代码:

int Sum(int *Start,int Count)
{
    int sum = 0;
    while(Count)
    {
        sum+=*Start;
        Start++;
        Count--;
    }
    return sum;
}

改动之后:

loop:
mrmovl (%ecx),%esi
irmovl $0,%edi
subl %esi,%edi
cmovg %edi,%esi   
addl %esi,%eax
irmovl $4,%ebx
addl %ebx,%ecx
irmovl $-1,%ebx
addl %ebx,%edx
jne loop

家庭作业

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.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.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; 
         ];

结对及互评

本周结对学习情况

其他(感悟、思考等,可选)

认真回顾自己这一个学期来在这门课上的学习,就会发现,其实有很多需要补充的地方。老师让我们完成一个最差的一章的学习总结,通过这篇博客我们完成了,但是并不意味着我们的学习就没有学的不好的部分了,我们还需要一直地去反思和复习,才能够不断查缺补漏,取得更好的成绩。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时

| 第四周 | 300/1300 | 2/9 | 30/90 | |

尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。

参考:软件工程软件的估计为什么这么难软件工程 估计方法

  • 计划学习时间:XX小时

  • 实际学习时间:XX小时

  • 改进情况:

(有空多看看现代软件工程 课件
软件工程师能力自我评价表
)

参考资料

posted @ 2017-12-24 15:33  xuanyan  阅读(631)  评论(1编辑  收藏  举报