Skip to content
This repository has been archived by the owner on Oct 8, 2022. It is now read-only.

Latest commit

 

History

History
732 lines (612 loc) · 16.6 KB

1600012866.md

File metadata and controls

732 lines (612 loc) · 16.6 KB

第一次作业

Ex2.61

a = !(x + 1);
b = !x;
c = !((x & 0xff) ^ 0xff);
d = !(x >> ((sizeof(int) - 1) << 3) & 0xff);
// 暴力做法,每一次都假定x满足要求,然后把对应bit转化为0

Ex2.62

bool int_shifts_are_arithmetic(){
	return !!((-1 >> 1) ^ INT_MAX);
	// 逻辑右移的情况下,-1>>1是INT_MAX,与自身进行Xor操作得0
}

Ex2.65

/* Return 1 when x contains an odd number of 1s; 0 otherwise.
   Assume w=32. The function cantains less than 12 operations. */
int odd_ones(unsigned x){
	x ^= (x >> 16);
	x ^= (x >> 8);
	x ^= (x >> 4);
	x ^= (x >> 2);
	x ^= (x >> 1);
	return x & 1;
	// 由于Xor操作的性质,不会改变操作数的奇偶性
	// 用二分方法,每一次操作都把高(len/2)位的奇偶性加载到低(len/2)上
}

第一次作业反馈

第一题:A有一点小问题,其他正确
第二题:有误
第三题:正确

第二次作业

Ex2.88

第一行:208、0 1100 1110、208

第二行:-7/1024、1 0000 0111、-7/1024

第三行:5/131072、0 0000 0001、1/1024

第四行:-4096、1 1110 1111、-248

第五行:768、0 1111 0000、+INF

Ex2.92

float_bits float_negate(float_bits f){
    int exp = (f >> 23) & 0xff;
    int frac = f & 0x7fffff;
    if (!(exp ^ 0xff) && frac){
        return f;
    }
    return f ^ (1 << 31);
}

Ex2.96

int float_f2i(float_bits f){
    int sign = (f >> 31) & 1;
    int exp = (f >> 23) & 0xff - 127; // 计算2的幂指数部分
  	int frac = f & 0x7fffff;
    if (exp >= 32 || (exp == 31 && !frac)){ // INF的情况需要向0舍入
        return 0x80000000;
    }else if (exp < 0){
        return 0;
    }
  	frac += 0x800000; // 将尾数加上隐藏的1
    int frac = f & 0x7fffff + 0x800000; // 将尾数加上隐藏的1
    if (exp >= 23){
        if (sign)
            return -(frac << (exp - 23));
        else
            return (frac << (exp - 23));
    }else{
        if (sign)
            return -(frac >> (23 - exp)); //直接右移可以达到向0取整的目的
        else
            return (frac >> (exp - 23));
    }
}

第二次作业反馈

第一题:正确
第二题:正确
第三题:有一点小错误

第三次作业

Ex3.60

A. %rdi,%esi,%eax,%rdx

B.0,1

C.mask != 0

D.每一次左移n位

E.每一次或(mask & x)

long loop (long x, int n){
    long result = 0;
    long mask;
    for (mask = 1; mask != 0; mask = mask << n){
        result |= (mask & x);
    }
}

Ex3.62

typedef enum {MODE_A, MODE_B, MODE_C, MODE_D, MODE_E} mode_t;
long switch3(long *p1, long *p2, mode_t action){
    long result = 0;
    switch(action){
        case MODE_A:{
            result = *p2;
            *p2 = (long)action;
            return result;
        }
        case MODE_B:{
            result = *p1;
            result += *p2;
            *p1 = result;
            return result;
        }
        case MODE_C:{
            *p1 = 59;
            result = *p2;
            return result;
        }
        case MODE_D:{
            result = *p2;
            *p1 = result;
            result = 27;
            return result;
        }
        case MODE_E:
            return (result = 27);
        default:{
            return (result = 12);
        }
            
    }
}

Ex3.64

对于一个给定的三维数组A[R][C][H]:

A. &A[i][j][k] = x0 + L * ( i * C * H + j * H),其中x0为数组的起始地址,L为单位元素的字节长度。

B. R = 7; S = 5; T = 13;

第三次作业反馈

第一题:正确
第二题:MODE_A有误(另外,最好用break,代码最后有return result;)
第三题:A有误  

第四次作业

Ex3.68

A = 9; B = 5;

Ex3.69

A. CNT = 7;

B.

typedef struct{
    long idx;
    long x[4];
} a_struct;

Ex3.70

A. 0, 8, 0, 8;

B. 16;

C.

void proc(union ele *up){
    up->e2.x = *(up->e2.next->e1.p) - up->e2.next->e1.y;
}

第四次作业反馈

第一题:正确
第二题:正确
第三题:正确

第五次作业

Ex4.47

// C Code
#include <stdio.h>
int a[8] = {8, 7, 6, 5, 4, 3, 2, 1};
void bubble_a(int *data, int count){
    long i, last;
    for (last = count - 1; last > 0; last--){
        for (i = 0; i < last; i++){
            if (*(data + i + 1) < *(data + i)){
                int t = *(data + i + 1);
                *(data + i + 1) = *(data + i);
                *(data + i) = t;
            }
        }
    }
}
int main(){
    bubble_a(a, 8);
    return 0;
}
-----------------------------------------------
// Y86 code with sample data
# Execution begins at address 0
	.pos 0x0
	irmovl	stack,%esp
	irmovl	stack,%ebp
	call	main
	halt

main:
	pushl	%ebp
	rrmovl	%esp,%ebp
	irmovl	8,%eax
	pushl	%eax
	irmovl	0x194,%eax
	pushl	%eax
	call	bubble_a
	irmovl	$8,%ebx
	addl	%ebx,%esp
	irmovl	$0,%eax
	rrmovl	%ebp,%esp
	popl	%ebp
	ret

bubble_a:
	pushl	%ebp
	rrmovl	%esp,%ebp
	irmovl	$0x10,%eax
	subl	%eax,%esp
	mrmovl	12(%ebp),%eax
	irmovl	$1,%ebx
	subl	%ebx,%eax
	rmmovl	%eax,-8(%ebp)
	jmp		check1
loop1:	
	irmovl	$0,%ebx
	rmmovl	%ebx,-12(%ebp)
	jmp		check2
loop2:
	mrmovl	-12(%ebp),%eax
	irmovl	$1,%ebx
	addl	%ebx,%eax
	addl	%eax,%eax
	addl	%eax,%eax
	rrmovl	%eax,%edx
	mrmovl	8(%ebp),%eax
	addl	%edx,%eax
	mrmovl	(%eax),%edx
	mrmovl	-12(%ebp),%eax
	addl	%eax,%eax
	addl	%eax,%eax
	rrmovl	%eax,%ecx
	mrmovl	8(%ebp),%eax
	addl	%ecx,%eax
	mrmovl	(%eax),%eax
	rrmovl	%edx,%ebx
	subl	%eax,%ebx
	jge		check3
	mrmovl	-12(%ebp),%eax
	irmovl	$1,%ebx
	addl	%ebx,%eax
	addl	%eax,%eax
	addl	%eax,%eax
	rrmovl	%eax,%edx
	mrmovl	8(%ebp),%eax
	addl 	%edx,%eax
	mrmovl	(%eax),%eax
	rmmovl	%eax,-4(%ebp)
	mrmovl	-12(%ebp),%eax
	irmovl	$1,%ebx
	addl	%ebx,%eax
	addl	%eax,%eax
	addl	%eax,%eax
	rrmovl	%eax,%edx
	mrmovl	8(%ebp),%eax
	addl	%eax,%edx
	mrmovl	-12(%ebp),%eax
	addl	%eax,%eax
	addl	%eax,%eax
	rrmovl	%eax,%ecx
	mrmovl	8(%ebp),%eax
	addl	%ecx,%eax
	mrmovl	(%eax),%eax
	rmmovl	%eax,(%edx)
	mrmovl	-12(%ebp),%eax
	addl	%eax,%eax
	addl	%eax,%eax
	rrmovl	%eax,%edx
	mrmovl	8(%ebp),%eax
	addl	%eax,%edx
	mrmovl	-4(%ebp),%eax
	rmmovl	%eax,(%edx)
check3:
	irmovl	$1,%ebx
	mrmovl	-12(%ebp),%eax
	addl	%ebx,%eax
	rmmovl	%eax,-12(%ebp)
check2:
	mrmovl	-12(%ebp),%eax
	mrmovl	-8(%ebp),%ebx
	subl	%ebx,%eax
	jl		loop2
	irmovl	$1,%ebx
	mrmovl	-8(%ebp),%eax
	subl	%ebx,%eax
	rmmovl	%eax,-8(%ebp)
check1:
	mrmovl	-8(%ebp),%eax
	irmovl	$0,%ebx
	subl	%ebx,%eax
	jg		loop1
	nop
	rrmovl	%ebp,%esp
	popl	%ebp
	ret

	.align 4
data:
	.long 0x8
	.long 0x7
	.long 0x6
	.long 0x5
	.long 0x4
	.long 0x3
	.long 0x2
	.long 0x1

	.pos 1000
stack:

Ex4.56

// changes:
# Predict next value of PC
int f_predPC = [
	# BBTFNT: This is where you'll change the branch prediction rule
	f_icode == IJXX && f_ifun != UNCOND && f_valC < f_valP : f_valC;
	f_icode == IJXX && f_ifun == UNCOND : f_valC;
	f_icode == ICALL : f_valC;
	1 : f_valP;
];

## What address should instruction be fetched at
int f_pc = [
	# Mispredicted forward
	M_icode == IJXX && M_ifun != UNCOND && M_Cnd && M_valE >= M_valA: M_valE;
	# Mispredicted backward
	M_icode == IJXX && M_ifun != UNCOND && !M_Cnd && M_valE < M_valA: M_valA;
	# Completion of RET instruction.
	W_icode == IRET : W_valM;
	# Default: Use predicted value of PC
	1 : F_predPC;
];

# BBTFNT: When some branches are predicted as not-taken, you need some
# way to get valC into pipeline register M, so that
# you can correct for a mispredicted branch.

## Select input A to ALU
int aluA = [
	E_icode in { IRRMOVL, IOPL } : E_valA;
	E_icode in { IIRMOVL, IRMMOVL, IMRMOVL, IJXX } : E_valC;
	E_icode in { ICALL, IPUSHL } : -4;
	E_icode in { IRET, IPOPL } : 4;
	# Other instructions don't need ALU
];

## Select input B to ALU
int aluB = [
	E_icode in { IRMMOVL, IMRMOVL, IOPL, ICALL, 
		     IPUSHL, IRET, IPOPL } : E_valB;
	E_icode in { IRRMOVL, IIRMOVL, IJXX} : 0;
	# Other instructions don't need ALU
];

bool D_bubble =
	# Mispredicted branch
	(E_icode == IJXX && E_ifun != UNCOND && e_Cnd && e_valE >= E_valA) ||
	(E_icode == IJXX && E_ifun != UNCOND && !e_Cnd && e_valE < E_valA) ||
	# BBTFNT: This condition will change
	# Stalling at fetch while ret passes through pipeline
	# but not condition for a load/use hazard
	!(E_icode in { IMRMOVL, IPOPL } && E_dstM in { d_srcA, d_srcB }) &&
	  IRET in { D_icode, E_icode, M_icode };

# Should I stall or inject a bubble into Pipeline Register E?
# At most one of these can be true.
bool E_stall = 0;
bool E_bubble =
	# Mispredicted branch
	(E_icode == IJXX && E_ifun != UNCOND && e_Cnd && e_valE >= E_valA) ||
	(E_icode == IJXX && E_ifun != UNCOND && !e_Cnd && e_valE < E_valA) ||
	# BBTFNT: This condition will change
	# Conditions for a load/use hazard
	E_icode in { IMRMOVL, IPOPL } &&
	 E_dstM in { d_srcA, d_srcB};

Ex5.13

A.

// 内循环代码的图形化表示
%rbp  %rax  %xmm0  %rcx  %rbx                +----+
  +-----|-----|------|-----|---------------->|    |
  |     |     |      +-----|---------------->|load| // load udata
  |     |     |      |     |                 |    |--------------------+
  |     |     |      |     |                 +----+                    |
  |     +-----|------|-----|---------------->|    |                    |
  |     |     |      +-----|---------------->|load| // load vdata    [%xmm1]
  |     |     |      |     |                 |    |-------+            |
  |     |     |      |     |                 +----+    [unknown]       |
  |     |     |      |     |                 |    |<------+            |
  |     |     |      |     |                 |mul |<-------------------+
  |     |     |      |     |                 |    |-------+
  |     |     |      |     |                 +----+     [%xmm1]
  |     |     +------|-----|---------------->|    |       |
  |     |            |     |                 |add |<------+
  |     |     +------|-----|-----------------|    |
  |     |     |      |     |                 +----+
  |     |     |      +-----|---------------->|    |
  |     |     |            |                 |add |
  |     |     |      +-----|-----------------|    |  
  |     |     |      |     |                 +----+
  |     |     |      +-----|---------------->|    |
  |     |     |      |     +---------------->|cmp |
  |     |     |      |     |                 |    |-------+  
  |     |     |      |     |                 +----+   [unknown] 
  |     |     |      |     |                 |    |<------+ 
  |     |     |      |     |                 |jne |
  |     |     |      |     |                 |    |
  |     |     |      |     |                 +----+
 %rbp  %rax  %xmm0  %rcx  %rbx
 
 // 关键路径
%xmm              %rcx
 |                 |
 |[load1]<---------+
 |  |   [load1]<---+  
 |  |     |        |
 |  [ mul ]     [ add ]
 |     |           |
 [ add ]           |
 |                 |
%xmm0             %rcx

B. 这条关键路径的CPE下界为浮点类型add操作,CPE=3.0

C. 整数类型的关键路径的CPE下界为整数类型add操作,CPE=1.0

D. 浮点乘法不在关键路径上,不存在数据关联,因此可以做流水线处理,每个时钟周期发射一条

Ex5.14

A. 每一个元素对应两次load操作,三次整形add操作,由于能够进行load操作的只有两个功能单元。因此限制CPE不可能降低到1.0以下。

B. 浮点add操作具有数据相关性,会受到延迟界限(CPE=3.0)的限制。

第五次作业反馈

第一题:正确
第二题:正确
第三题:正确(画的很棒啊!!!)
第四题:代码呢??

第六次作业

Ex7.6

符号 swap.o.symtab条目? 符号类型 定义符号的模块
buf 外部 m.o .data
bufp0 全局 swap.o .data
bufp1 局部 swap.o .bss
swap 全局 swap.o .text
temp
incr 局部 swap.o .text
count 局部 swap.o .bss

Ex7.7

void f(){
	*(long*)(&x) = ((long)15212 << 32) + ((long)15213); 
}

Ex7.12

  1. 0x4004f8 + (-4) - (0x4004e0 + 0xa) = 0xa (0a 00 00 00)
  2. 0x400500 + (-4) - (0x4004d0 + 0xa) = 0x22 (22 00 00 00)

Ex7.13

  1. libc.a中一共有1649个.o文件,libm.a中一共有713个.o文件
  2. 是相同的(测试了一个简单的c代码)
  3. libc.so.6和ld-linux-x86-64.so.2

第六次作业反馈

第一题:有一处错误
第二题:正确
第三题:正确
第四题:正确

第七次作业

Ex8.9

进程对 并发地?
AB
AC
AD
BC
BD
CD

Ex8.18

ACE是可能的,进行两次fork,最后是4个进程输出,第一次fork得到的子进程的后代会在结束时输出“2”,因此一定有一个2前面有1,另一个2前面有0。

Ex8.24

#include "csapp.h"
#define N 2
#define MAXLEN 50

int main() 
{
    int status, i;
    pid_t pid;

    for (i = 0; i < N; i++)
	if ((pid = Fork()) == 0){
		char src = NULL;
		strcpy(src, "It's a joke.\n");
	}

    while ((pid = waitpid(-1, &status, 0)) > 0) {
		if (WIFSIGNALED(status)){
			char sbuf[MAXLEN];
			sprintf(sbuf, "child %d terminated by signal %d", pid, WTERMSIG(status));
			psignal(WTERMSIG(status), sbuf);
		}
    }

    if (errno != ECHILD)
		unix_error("waitpid error");

    exit(0);
}

Ex10.6

"fd2 = 4\n"

Ex10.9

if (Fork() == 0){
	fd = open("foo.txt", O_RDONLY, 0);
	dup2(fd, STDIN_FILENO);
	close(fd);
	Execve("fstatcheck", agrv, envp);
}

第七次作业反馈

第一题:正确
第二题:正确
第三题:正确
第四题:正确
第五题:错误

第八次作业

// 编写虚页页号打印程序,打印出本进程能够访问到的所有虚页页号
// VirtualPage.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define MAXLEN (1 << 10)
#define L (1 << 5)
int main(){
	pid_t pid = getpid();
	char addr[MAXLEN];
	sprintf(addr, "/proc/%d/maps", pid);	// get right address for file maps
	FILE* fp = fopen(addr, "r");		// /proc/<PID>/maps contains memory info
	char buf[MAXLEN];
	char tmp[L];
	long long last = -1;
	while(fgets(buf, MAXLEN - 1, fp) != NULL){	// read in single line
		long long begin,end;
		sscanf(buf, "%llx-%llx", &begin, &end);
		for(long long i = (begin >> 12); i <= (end >> 12); i++){// VP = addr/4KB
			if (last != i)
				printf("virtual page:0x%llx\n", i);
			last = i;	// avoid repeated output
		}
	}
	fclose(fp);
	return 0;
}

第九次作业

Ex11.8

void sigchld_hdlr(int sig);
void sigchld_hdlr(int sig){
	int olderrno = errno;
	while(waitpid(-1, NULL, WNOHANG) > 0){

	}
	errno = olderrno;
}
int main(int argc, char **argv) 
{
    int listenfd, connfd;
    char hostname[MAXLINE], port[MAXLINE];
    socklen_t clientlen;
    struct sockaddr_storage clientaddr;
    if (Signal(SIGCHLD, sigchld_hdlr) == SIG_ERR)
    	unix_error("signal error\n");

    /* Check command line args */
    if (argc != 2) {
	fprintf(stderr, "usage: %s <port>\n", argv[0]);
	exit(1);
    }

    listenfd = Open_listenfd(argv[1]);
    while (1) {
	clientlen = sizeof(clientaddr);
	connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); //line:netp:tiny:accept
        Getnameinfo((SA *) &clientaddr, clientlen, hostname, MAXLINE, 
                    port, MAXLINE, 0);
        printf("Accepted connection from (%s, %s)\n", hostname, port);
	doit(connfd);                                             //line:netp:tiny:doit
	Close(connfd);                                            //line:netp:tiny:close
    }
}

Ex11.9

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);       //line:netp:servestatic:getfiletype
    sprintf(buf, "HTTP/1.0 200 OK\r\n");    //line:netp:servestatic:beginserve
    sprintf(buf, "%sServer: Tiny Web Server\r\n", buf);
    sprintf(buf, "%sConnection: close\r\n", buf);
    sprintf(buf, "%sContent-length: %d\r\n", buf, filesize);
    sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype);
    Rio_writen(fd, buf, strlen(buf));       //line:netp:servestatic:endserve
    printf("Response headers:\n");
    printf("%s", buf);

    /* Send response body to client */
    srcfd = Open(filename, O_RDONLY, 0);    //line:netp:servestatic:open
    srcp = Malloc(filesize);
    Rio_readn(srcfd, srcp, filesize);
    Rio_writen(fd, srcp, filesize);         //line:netp:servestatic:write
    Close(srcfd);                           //line:netp:servestatic:close
    Free(srcp);
}

第九次作业反馈

第一题:有误
第二题:正确