• 上一届家庭作业重点笔记


    2.68

    题目:构建函数int lower_bits(int n)将int 变量的低n位置1,其余位置0。

    • 思路:将~0左移n位与-1异或可得结果。

    • 函数代码:

    • 运行结果:

    3.67

    解析:

    • 联合体的所有成员相对于基地址的偏移量都为0;

    • 此结构空间要大到足够容纳最"宽"的成员

    • 其对其方式要适合其中所有成员(4字节补齐)

    • 对于2、3两点的解释:

    • 联合体所占的空间不仅取决于最宽成员,还跟所有成员有关系,即其大小必须满足两个条件:1)大小足够容纳最宽的成员;2)大小能被其包含的所有基本数据类型的大小所整除。

    • 具体例子:

    union U1 
    { 	
        char s[10]; 
        int n; 	
        double d; 	
    };
    
    • s占10字节,n占4字节,d占8字节,因此其至少需10字节的空间。然而其实际大小并不是10,用运算符sizeof测试其大小为16.这是因为这里存在字节对齐的问题,10既不能被4整除,也不能被8整除。因此补充字节到16,这样就符合所有成员的自身对齐了。

    答案

    A:

    • 根据联合体的所有成员相对于基地址的偏移量都为0这一点,加上int占有4个字节,而地址(*next)也占有四个字节,即可做出此题。
      • e1.p:0
      • e1.x:4
      • e2.y:0
      • e2.next:4

    B:

    • 根据联合体的字节补齐和其满足的两个条件即可做出此题。
      e1中int *p --4字节 int x---4字节 和为8字节
      e2中int y --4字节 union ele *next --4字节 和为8字节
      因为两个结构体所占有的字节大小均为8且符合字节补齐规则,所以该联合体结构总共需要8个字节。

    C:

    • 在做此题前先明确该联合体中,需要先访问成员才可以访问成员中的变量这一点,即你要获取x,必须要先获得e1,而后进入e1结构体访问x,最终形成e1.x。

    1.很明显的movl 8(%ebp),%edx 此语句作用为get up at %edx

    2.试着按顺序写出语句,但发现并不能确定每一个语句准确表示的是什么,所以就观察其中有特点的语句进行分析。

    3.发现语句中subl (%edx), %eax表示为%eax = eax - (%edx),(%edx)为整数,并且%edx保存的是up,满足条件且偏移量为0的情况只有e2.y即,减数为up->e2.y。同时可得被减数存储在%eax中。

    4.题目中有*(up->__)表示一个整数这个信息,再对应联合体结构中仅有int *p满足该条件,并且在汇编代码中,由上一步可知被减数存储在%eax中,可知movl (%eax), %eax是对被减数赋值的语句,可得在此语句之前%eax为地址,并且应该为up->e1.p,即被减数应该为up->e1.p。

    5.但再往上看发现第三行的%eax是由(%ecx)获得,并且%ecx由4(%edx)获得,但%edx指向了up->e2.y,所以被减数应该是有4的偏移量,明显的%ecx应该为up->e2.next,对应的%eax为up->e2.next->e1.p。

    6.最终只剩下得数的表示了,明显对应的是movl %eax,4(%ecx)这条语句,%ecx为up->e2.next,%ecx+4应该为up->e2.next->e1.x,即得数为up->e2.next->e1.x。

    • 最终的结果:
      up->e2.next->e1.x = *(up->e2.next->e1.p) - up->e2.y

    4.47题:

    • leave指令等价于如下代码序列:
    rrmovl  %ebp,%esp
    popl    %ebp
    
    • 也就是说它要执行的动作是,将帧指针ebp的内容赋给栈指针esp,然后弹出ebp,栈指针+4,结果是消灭这个栈。

    • 参照pop指令的格式,可以得出如下的过程:

    取指阶段 icode:ifun<--M1[PC] = D:0

        valP <= PC + 1  ;下一条指令地址
    

    译码阶段 valB <= R[%ebp] ;得到ebp的值,这个值就是新的栈指针esp的值

    执行阶段 valE <= valB + 4 ;栈指针的值+4

    访存阶段 valM <= M4[valB] ;读ebp中的值

    写回阶段 R[%esp] <= valE ;把更新后的指针赋值给esp
    R[%ebp] <= valM ;弹出的ebp的值

    6.31

    A.E=4,B=4,S=8

    所以C=EBS=128

    B.

    家庭作业7.11

    题目

    解答:

    • 3、4行是数据段,开始于存储器地址0x08049448的位置,总的存储器大小是0x194字节,从文件偏移的0x448处开始的0xe8个字节初始化。
    • 在加载之前,未初始化的全局变量不会在目标文件中分配存储空间,但是在加载之后,像.bss中的符号等数据需要占用空间,所以剩下的字节对应运行时将被初始化为0的.bss数据。

    8.10

    答案:

    A. 调用一次,返回两次: fork

    B. 调用一次,从不返回: execve, longjmp

    C. 调用一次,返回一次或者多次: setjmp

    9.13

    A.虚拟地址:0x0040

    13 12 11 10 9 8 7 6 5 4 3 2 1 0

    0 0 0 0 0 0 0 1 0 0 0 0 0 0

    B.地址翻译

    参数 值

    VPN 0x01

    TLB索引 0x01

    TLB标记 0x00

    TLB命中 No

    缺页 Yes

    PPN -

    家庭作业10.6

    题目:

    解答:

    分析:

    每一步输出。
    1.打开文件一;2.打开文件二;3.关闭文件二;4.打开文件二

    Unix外壳创建每个进程开始时都有三个打开的文件:

    • 0:标准输入
    • 1:标准输出
    • 2:标准错误
      打开fd1时描述符为3,打开fd2时描述符为4,关闭fd2之后再打开还是4。

    第十一章家庭作业 11.7

    11.7 拓展TINY,使它可以提供MPG视频文件。用一个真正的浏览器来检验你的工作。

    • 答:在get_filetype函数里面添加:
    else if(strstr(filename, ".mpg") || strstr(filename, ".mp4"))
    strcpy(filetype, "video/mpg");
    

    源代码:

    #include "csapp.h"
    
    void doit(int fd);
    void read_requesthdrs(rio_t *rp);
    int parse_uri(char *uri, char *filename, char *cgiargs);
    void serve_static(int fd, char *filename, int filesize);
    void get_filetype(char *filename, char *filetype);
    void serve_dynamic(int fd, char *filename, char *cgiargs);
    void clienterror(int fd, char *cause, char *errnum,
                    char *shorting,char *longmsg);
    
    int main(int argc,char *argv[])
    {
        int listenfd,connfd,port,clientlen;
        struct sockaddr_in clientaddr;
    
        if(argc != 2)
        {
            fprintf(stderr,"usage: %s <port>
    ",argv[0]);
            exit(0);
        }
    
        port = atoi(argv[1]);
    
        listenfd = Open_listenfd(port);
        while(1)
        {
            clientlen = sizeof(clientaddr);
            connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
            doit(connfd);
            Close(connfd);
        }
    }
    void doit(int fd)
    {
        int is_static;
        struct stat sbuf;
        char buf[MAXLINE], method[MAXLINE],uri[MAXLINE],version[MAXLINE];
        char filename[MAXLINE],cgiargs[MAXLINE];
        rio_t rio;
    
        /*read request line and headers*/
        Rio_readinitb(&rio, fd);
        Rio_readlineb(&rio, buf, MAXLINE);
        sscanf(buf, "%s %s %s", method, uri, version);
        if(strcasecmp(method,"GET"))
        {
            clienterror(fd, method, "501","Not Implemented",
                "Tiny does not implement this method");
            return;
        }
        read_requesthdrs(&rio);
    
        /*prase URI from GET request*/
        is_static = parse_uri(uri, filename, cgiargs);
        if(stat(filename, &sbuf) < 0)
        {
            clienterror(fd, filename, "404","Not Found",
                "Tiny couldn't find this file");
            return;
        }
        if(is_static)//server static content
        {
            if(!(S_ISREG(sbuf.st_mode) || !(S_IRUSR & sbuf.st_mode)))
            {
                clienterror(fd, filename, "403","Forbidden",
                    "Tiny couldn't read the file");
                return;
            }
            serve_static(fd, filename, sbuf.st_size);
        }
        else//server dynamic content
        {
            if(!(S_ISREG(sbuf.st_mode) || !(S_IXUSR & sbuf.st_mode)))
            {
                clienterror(fd, filename, "403","Forbidden",
                    "Tiny couldn't run the CGI program");
                return;
            }
            serve_dynamic(fd, filename, cgiargs);   
        }
    }
    void clienterror(int fd, char *cause, char *errnum,
                    char *shortmsg, char *longmsg)
    {
        char buf[MAXLINE], body[MAXBUF];
    
        /*Build the HTTP response body*/
        sprintf(body, "<html><title>Tiny Error</title>");
        sprintf(body, "%s<body bgcolor=""ffffff"">
    ",body);
        sprintf(body, "%s%s: %s
    ",body,errnum,shortmsg);
        sprintf(body, "%s<p>%s: %s
    ", body, longmsg, cause);
        sprintf(body, "%s<hr><em>The Tiny Web Server</em><>
    ",body);
    
        /*Print the HTTP response*/
        sprintf(buf, "HTTP/1.0 %s %s
    ",errnum, shortmsg);
        Rio_writen(fd, buf, strlen(buf));
        sprintf(buf, "Content-type: text/html
    ");
        Rio_writen(fd, buf, strlen(buf));
        sprintf(buf, "Content-length: %d
    
    ",(int)strlen(body));
        Rio_writen(fd, buf, strlen(buf));
        Rio_writen(fd, body, strlen(body));
    }
    //read_requesthdrs()来跳过请求报头的信息,直到遇见表示报头结束的空文本行。
    
    void read_requesthdrs(rio_t *rp)
    {
        char buf[MAXLINE];
    
        Rio_readlineb(rp, buf, MAXLINE);
        while(strcmp(buf, "
    "))
        {
            Rio_readlineb(rp, buf, MAXLINE);
            printf("%s", buf);
        }
        return;
    }
    
    int parse_uri(char *uri, char *filename, char *cgiargs)
    {
        char *ptr;
    
        if(!strstr(uri, "cgi-bin"))//static content
        {
            strcpy(cgiargs, "");
            strcpy(filename, ".");
            strcat(filename, uri);
            if(uri[strlen(uri)-1] == '/')
                strcat(uri, "home.html");
            return 1;
        }
        else
        {
            ptr = index(uri, '?');
            if(ptr)
            {
                strcpy(cgiargs, ptr+1);
                *ptr = '';
            }
            else
                strcpy(cgiargs, "");
            strcpy(filename, ".");
            strcat(filename, uri);
            return 0;
        }
    }
    
    void serve_static(int fd, char *filename, int filesize)
    {
        int srcfd;
        char *srcp, filetype[MAXLINE], buf[MAXBUF];
    
        /*Send response headers to client*/
        get_filetype(filename,filetype);
        sprintf(buf, "HTTP/1.0 200 OK
    ");
        sprintf(buf, "%sServer: Tiny Web Server
    ", buf);
        sprintf(buf, "%sContent-lenght: %d
    ", buf, filesize);
        sprintf(buf, "%sContent-type: %s
    
    ", buf, filetype);
        Rio_writen(fd, buf, strlen(buf));
        /*Send response body to client*/
        srcfd = Open(filename, O_RDONLY, 0);
        srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE,srcfd,0);
        close(srcfd);
        Rio_writen(fd, srcp, filesize);
        Munmap(srcp, filesize);
    }
    
    void get_filetype(char *filename, char *filetype)
    {
        if(strstr(filename, ".html"))
            strcpy(filetype, "text/html");
        else if(strstr(filename, ".gif"))
            strcpy(filetype, "image/gif");
        else if(strstr(filename, ".jpg"))
            strcpy(filetype, "image/jpeg");
        else 
            strcpy(filetype, "text/plain");
    }
    
    void serve_dynamic(int fd, char *filename, char *cgiargs)
    {
        char buf[MAXLINE], *emptylist[]={NULL};
    
        /*Return first part of HTTP response*/
        sprintf(buf, "HTTP/1.0 200 OK
    ");
        Rio_writen(fd, buf,strlen(buf));
        sprintf(buf, "Server: Tiny Web Server
    ");
        Rio_writen(fd, buf,strlen(buf));
    
        if(Fork()==0)
        {
            setenv("QUERY_STRING", cgiargs, 1);
            Dup2(fd, STDOUT_FILENO);
            Execve(filename, emptylist,environ);
        }
        Wait(NULL);
    }
    

    12.18

    A.(F)
    B.(T)
    C.(F)

  • 相关阅读:
    前端chrome浏览器调试总结
    this指南——绑定了谁?
    轮播图终极版
    一个后台项目的总结
    h5 websocket 断开重新连接
    ios手机键盘拉起之后页面不会回退的问题
    promise 的串行执行
    js中对小数的计算
    对问卷项目的优化
    禁止eslint对指定代码检测
  • 原文地址:https://www.cnblogs.com/20145208cy/p/6159819.html
Copyright © 2020-2023  润新知