• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

20145208蔡野

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

上一届家庭作业重点笔记

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>\n",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"">\r\n",body);
    sprintf(body, "%s%s: %s\r\n",body,errnum,shortmsg);
    sprintf(body, "%s<p>%s: %s\r\n", body, longmsg, cause);
    sprintf(body, "%s<hr><em>The Tiny Web Server</em><>\r\n",body);

    /*Print the HTTP response*/
    sprintf(buf, "HTTP/1.0 %s %s\r\n",errnum, shortmsg);
    Rio_writen(fd, buf, strlen(buf));
    sprintf(buf, "Content-type: text/html\r\n");
    Rio_writen(fd, buf, strlen(buf));
    sprintf(buf, "Content-length: %d\r\n\r\n",(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, "\r\n"))
    {
        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 = '\0';
        }
        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\r\n");
    sprintf(buf, "%sServer: Tiny Web Server\r\n", buf);
    sprintf(buf, "%sContent-lenght: %d\r\n", buf, filesize);
    sprintf(buf, "%sContent-type: %s\r\n\r\n", 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\r\n");
    Rio_writen(fd, buf,strlen(buf));
    sprintf(buf, "Server: Tiny Web Server\r\n");
    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)

posted on 2016-12-11 16:35  20145208蔡野  阅读(249)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3