HW1:2.61、2.62、2.65
A:!(x^(-1)). //异或运算:a^b,当a==b的时候返回0,其他时候返回非0,再取非即可
B: !x.
C: !((x&0x0f)^(0x0f)). //先用 & 0x0f把最低位有效字节取出来,(其余位得0),然后用A的方法
D: !((-1<<28)&x).
bool int_shifts_are_arithmetic(){
return !((-1>>1)^(-1));
}
int odd_ones(unsigned x){//Assume w=32
x=x^(x>>1);//拿第一位和第二位做异或,得1说明第一位和第二位的1的数目为基数个,得0说明为偶数个,第一位、第三位、第五位……第31位同理
x=x^(x>>2);//拿上一步得到的第一位和第三位做异或,得1说明基数个,得0说明偶数个
x=x^(x>>4);//同理
x=x^(x>>8);
x=x^(x>>16);
x=x&1;//最后得到的第一位的信息就是整个的奇偶信息,再取出来就可以了
return x;
}
第一题:A、B正确,C、D有误
第二题:正确
第三题:正确
HW2 2.88、2.92、2.96
格式A | —— | 格式B | —— |
---|---|---|---|
位 | 值 | 位 | 值 |
1 01110 001 | -9/16 | 1 0110 0010 | -9/16 |
0 10110 101 | 832 | 0 1111 0000 | +∞ |
1 00111 110 | -7/2^10 | 1 0000 0111 | -7/2^10 |
0 00000 101 | 5/2^-17 | 0 0000 0000 | +0.0 |
1 11011 000 | -4096 | 1 1111 0000 | -∞ |
0 11000 100 | 768 | 0 1111 0000 | +∞ |
/*Compute -f. If f is NaN, then return f.*/
float_bits float_negate(float_bits f){
int sign = f & 0x80000000;
int exp = f & 0x7f800000;
int frac = f & 0x7fffff;
if (exp == 0x7f800000 && frac)
return f;
else
return (sign ^ 0x80000000) | exp | frac;
}
/*
* Compute (int) f.
* If conversion causes overflow or f is NaN, return 0x80000000
*/
int float_f2i(float_bits f){
int sign = f & 0x80000000;
int exp = (f >> 23) & 0xff;
int frac = f & 0x7fffff;
int result;
int sh1ft;
if (exp < 0x7f)
return 0;
else if (exp > 157)//127+30
return 0x80000000;
if ( (exp == 0x7f800000 && frac) || (Em > 31) )
return 0x80000000;
r = 0x40000000 + (frac << 7);//1+frac,23+7=30,留下一位给符号
shi1f = 157 - exp;
r = r >> sh1ft;
if (sign)
return ~ r + 1;
else
return r;
return 0;
}
第一题:有4个错误
第二题:正确
第三题:有误(请写完后自己测试一下,语法错误希望不要再有)
HW3 3.60 3.62 3.64
A
%rdi保存x;%rsi、%rcx保存n;%rax保存result;%rdx保存mask
B 初始值 result=0;mask=1
C 测试条件 mask!=0
D mask算数左移n位
E result|(x&mask)
F
long loop(long x, int n){
long result = 0;
long mask;
for(mask = 1; mask != 0; mask = mask << n){
result |= (x & mask);
}
return result;
}
/* Enumerated type creates set of constants numbered 0 and upward */
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:
val = *p2;
*p2 = *p1;
break;
case MODE_B:
val = *p1 + *p2;
*p1 = val;
break;
case MODE_C:
*p1 = 59;
val = *p2;
break;
case MODE_D:
*p1 = *p2;
val = 27;
break;
case MODE_E:
val = 27;
break;
default:
val = 12;
}
return result;
}
A
&A[i][j][k]= x_A + L(S*T*i+T*j+k)
其中,L=8
B
R=7 S=5 T=13
第一题:正确
第二题:有一点小问题(val应为result)
第三题:正确
HW4: 3.68 3.69 3.70
A = 5,B = 9
CNT = 7
typedef struct{
long idx;
long x[4];
}a_struct;
A:
e1.p 0
e1.y 8
e2.x 0
e2.next 8
B 16
C.
void proc(union ele *up){
up->e2.x = *(up->e2.next->e1.p) - up->e2.next->e1.y;
}
第一题:有误(仔细啊!)
第二题:正确
第三题:正确
HW 4.47 4.56 5.13 5.14
A:
/* Bubble sort: Pointer version */
void bubble_a(long *data, long count){
long *point;
long* last = data + count - 1;
long swap;
while (last != data){
for (point = data; point != last; ++point){
if (*point > *(point+1)){
swap = *(point+1);
*(point + 1) = *point;
*point = swap;
}
}
last--;
}
}
B:
# void bubble_a(long *data, long count)
# code edited according to mac_gcc's output
_bubble_a:
pushl %ebp
rrmovl %esp, %ebp
subl $20, %esp
mrmovl 12(%ebp), %eax ## -4(%ebp) = data
mrmovl 8(%ebp), %ecx ## -8(%ebp) = count
rmmovl %ecx, -4(%ebp) ## -12(%ebp) = point
rmmovl %eax, -8(%ebp) ## -16(%ebp) = last
mrmovl -4(%ebp), %eax ## -20(%ebp) = swap
mrmovl -8(%ebp), %ecx
multl $4, %eax
addl %ecx, %eax
addl $-4, %eax
rmmovl %eax, -16(%ebp)
LBB0_1:
mrmovl -16(%ebp), %eax
mrmovl -4(%ebp),%ecx
subl %eax, %ecx
je LBB0_9 ## if last == data, break
## BB#2:
mrmovl -4(%ebp), %eax
rmmovl %eax, -12(%ebp) ## point = data
LBB0_3:
mrmovl -12(%ebp), %eax
mrmovl -16(%ebp), %ecx
subl %ecx, %eax
je LBB0_8
## BB#4:
mrmovl -12(%ebp), %eax
rmmovl (%eax), %eax ## %eax = *point
mrmovl -12(%ebp), %ecx
mrmovl 4(%ecx), %ecx ## %ecx = *(point+1)
subl %ecx, %eax ## if *point - *(point + 1) <= 0
jle LBB0_6
## BB#5:
mrmovl -12(%ebp), %eax
mrmovl 4(%eax), %eax
rmmovl %eax, -20(%ebp) ## swap = *(point + 1)
mrmovl -12(%ebp), %eax
mrmovl (%eax), %eax ## eax = *point
mrmovl -12(%ebp), %ecx
rmmovl %eax, 4(%ecx) ## *(point + 1) = *point
mrmovl -20(%ebp), %eax
mrmovl -12(%ebp), %ecx
rmmovl %eax, (%ecx) ## *point = swap
LBB0_6:
jmp LBB0_7
LBB0_7:
mrmovl -12(%ebp), %eax
addl $4, %eax
rmmovl %eax, -12(%ebp) ## point ++
jmp LBB0_3
LBB0_8:
mrmovl -16(%ebp), %eax
addl $-4, %eax
rmmovl %eax, -16(%ebp) ## last--
jmp LBB0_1
LBB0_9:
addl $20, %esp
popl %ebp
ret
# Predict next value of PC
int f_predPC = [
# BBTFNT: This is where you'll change the branch prediction rule
f_icode == ICALL : f_valC;
f_icode == IJXX && f_ifun == UNCOND : f_valC;
f_icode == IJXX && f_valC < f_valP : f_valC;
1 : f_valP;
];
关键路径:%xmm0->add->%xmm0
CPE下界:浮点数加法=3.0
整数加法:CPE下界:1.0
因为乘法之间不构成数据依赖,而浮点加法之间存在数据依赖
因为数据读取需要CPE=1.0
因为只有两个浮点数处理单元,一个用于浮点加法,一个浮点乘法,没有更多的资源用于运算
第一题:Y86有点小问题
第二题:有误
第三题:少画了个图
第四题:写的代码呢??
HW 7.6,7.7,7.12,7.13
符号 | swap.o.symtab条目? | 符号类型 | 定义符号的模块 | 节 |
---|---|---|---|---|
buf | Y | extern | main.o | .data |
bufp0 | N | -- | -- | -- |
bufp1 | Y | local | swap.o | .bss |
swap | Y | global | swap.o | .text |
temp | N | -- | -- | -- |
incr | Y | local | swap.o | .text |
count | Y | local | swap.o | .bss |
/* bar5.c */
static double x;
void f(){
x = -0.0;
}
/* foo5.c */
#include <stdio.h>
void f(void);
int y = 15212;
int x = 15213;
int main(){
f();
printf("x = 0x%x y = 0x%x \n", x, y);
return 0;
}
A. 0xa
B. 0x22
A.
locate:/usr/lib/x86_64-linux-gnu
C standard lib:libc.a
:包含1605个不同的目标文件
C math lib:libm.a
:包含439个不同的目标文件
B.
gcc -Og -g
产生的可执行二进制文件多出了.debug_aranges
, .debug_info
, .debug_abbrev
, .debug_line
, .debug_str
, .debug_loc
部分
C.
共享库版本:x86_64-linux-gnu
:GNU C11 (Ubuntu 5.4.0-6ubuntu1~16.04.4) version 5.4.0 20160609 (x86_64-linux-gnu)
(使用-v选项显示gcc运行中间步骤)
第一题:有两处错误
第二题:正确
第三题:正确
第四题:正确
HW. 8.9,8.18,8.24,10.6,10.9
进程对 | 并发? |
---|---|
AB | N |
AC | Y |
AD | Y |
BC | Y |
BD | Y |
CD | Y |
A、C、E都是可能的
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
char cmd[50]= "test";
char temp[20];
void test(){
char m[] = "man";
char *p = m;
sprintf(temp,"test reached\n");
sprintf(temp,"%x\n", test);
sprintf(temp,"%lx\n", p);
for(int i = 0; i < 1000; ++i){
*p = 'a';
p++;
}
return;
}
int main(){
int status = 0;
char m[3];
char * p = m;
pid_t pid;
if ((pid = fork()) == 0)//child
{
test();
}
else{//parent
waitpid(pid, &status, 0);
if(WIFSIGNALED(status)){
sprintf(cmd, "child %d terminated by signal %d", pid, status);
psignal(status, cmd);
}
if ((pid = fork()) == 0)//child
{
test();
}
else{
waitpid(pid, &status, 0);
if(WIFSIGNALED(status)){
sprintf(cmd, "child %d terminated by signal %d", pid, status);
psignal(status, cmd);
}
}
}
return 0;
}
//main.c
测试效果:
linux> gcc -Og main.c -o main
linux> ./main
child 14624 terminated by signal 11: Segmentation fault
child 14625 terminated by signal 11: Segmentation fault
linux>
fd2 = 4
linux> fstatcheck 3 < foo.txt
if(Fork() == 0){/* child */
int fd = open("foo.txt", O_RDONLY, 0);
dup2(fd, STDIN_FILENO);
Execve("fstatcheck", argv, envp);
}
//注释:直接用 < 会将文件描述符重定向到STDIN_FILENO,而如果要作为单独的描述符存在,可以这样做:
//注释:直接用 < 会将文件描述符重定向到STDIN_FILENO,而如果要作为单独的描述符存在,可以这样做:
linux> fstatcheck 3< foo.txt
第一题:正确
第二题:正确
第三题:正确
第四题:正确
第五题:close(fd)
VM作业:编写虚页页号遍历程序,该程序打印出本进程所能够访问的所有虚页页号
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main(int argc, char * const argv[]){
pid_t pid = getpid();
int fd_file;
char filename[50];
char buf[257];
unsigned long start, end;
char flag[5];
unsigned int length;
char unknown1[6];
unsigned int unknown2;
char pwd[255];
sprintf(filename, "/proc/%d/maps", pid);
fd_file = open(filename, O_RDONLY, 0);
dup2(fd_file, STDIN_FILENO);
while(fgets(buf, 256, stdin) > 0){
sscanf(buf, "%lx-%lx %s %x %s %d %s\n", &start, &end, flag, &length, unknown1, &unknown2, pwd);
start >>= 12;
end >>= 12;
for(unsigned long i = start; i <= end; ++i){
printf("0x%lx\n", i);
}
}
close(fd_file);
return 0;
}
//showVM.c
运行效果:
huangyong@ubuntu:~/test$ gcc -Og showVM.c -o showVM
huangyong@ubuntu:~/test$ ./showVM
0x400
0x401
0x600
0x601
0x601
0x602
0x219b
0x219c
0x219d
...
0x7ffd88a69
0x7ffd88a6a
0x7ffd88a6b
0xffffffffff600
0xffffffffff601
HW9: 11.8 11.9
添加信号处理函数:
void sigchld_handler(int sig){//added
int olderrno = errno;
while(waitpid(-1, NULL, WNOHANG | WUNTRACED) > 0);
errno = olderrno;
return;
}
main函数修改:
int main(int argc, char **argv)
{
int listenfd, connfd;
char hostname[MAXLINE], port[MAXLINE];
socklen_t clientlen;
struct sockaddr_storage clientaddr;
/* Check command line args */
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
/*******ADDED***********/
Signal(SIGCHLD, sigchld_handler);
/*******ADDED***********/
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
}
}
serve_dynamic函数修改:
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) { /* Child */ //line:netp:servedynamic:fork
/* Real server would set all CGI vars here */
setenv("QUERY_STRING", cgiargs, 1); //line:netp:servedynamic:setenv
Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */
//line:netp:servedynamic:dup2
Execve(filename, emptylist, environ); /* Run CGI program */
//line:netp:servedynamic:execve
}
/*******DELETED*********/
//Wait(NULL); /* Parent waits for and reaps child */ //line:netp:servedynamic:wait
/*******DELETED*********/
}
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 = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);//line:netp:servestatic:mmap
void * srcp = malloc(filesize + 1);
Rio_readn(srcfd, srcp, filesize);
Close(srcfd); //line:netp:servestatic:close
Rio_writen(fd, srcp, filesize); //line:netp:servestatic:write
// Munmap(srcp, filesize); //line:netp:servestatic:munmap
free(srcp);
}
第一题:正确
第二题:正确