• 信息安全系统设计基础作业—20135227黄晓妍


    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             #将计算出来的值复制到寄存器中

    更新PC:PC<----valP            #下一条指令的地址

    思路:前提: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 ",
                        pid, WEXITSTATUS(status));
            else if(WIFSIGNALED(status))
            {
                //为什么只在写只读文本时才报错?下面的程序对所有异常退出都会提示
                printf("child %d 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.

  • 相关阅读:
    老李分享:《Linux Shell脚本攻略》 要点(四)
    老李分享:《Linux Shell脚本攻略》 要点(三)
    老李分享:《Linux Shell脚本攻略》 要点(二)
    老李分享:《Linux Shell脚本攻略》 要点(一)
    持续集成:TestNG组织如何测试用例
    Linux安装Redis
    Linux安装JDK
    Redis主从复制
    MySQL主从同步
    Spring 事务
  • 原文地址:https://www.cnblogs.com/angelahxy/p/4915693.html
Copyright © 2020-2023  润新知