深入理解计算机操作系统第三章家庭作业

3.58

y=y-z;
x=x*y;
return x ^ (y<<63>>63);

3.59

无符号64位,ux 和 uy
有符号64位,x 和 y
设 x 和 ux 具有相同的位,y 和 uy 具有相同的位,
ux = x + Sx*2^64
ux = y + Sy*2^64
ux * uy = (x + Sx * 2^64) * (y + Sy * 2^64)
ux * uy = x*y + (Sx*y + Sy*x)*2^64 + Sx*Sy*2^128
ux * uy = x*y + (Sx*y + Sy*x)*2^64
x*y = ux * uy - (Sx*y + Sy*x)*2^64


movq    %rdx, %rax         rax 存有 y
cqto                       rdx 存有 -Sy (存的位要么是全 1,要么全 0)
movq    %rsi, %rcx         rcx 存有 x
sarq    $63, %rcx          rcx 存有 -Sx
imulq   %rax, %rcx         rcx 存有 -Sx * y (注意,imul 不分有符号乘法还是无符号乘法,只保留低 64 位,这边不可能溢出,因为 Sx 要么 1 要么 0)
imulq   %rsi, %rdx         rdx 存有 -Sy * x
addq    %rdx, %rcx         rcx 存有 -Sx*y + -Sy*x
mulq    %rsi               rax 存有 ux * uy 低 64 位, rdx 存有积的高 64 位
addq    %rcx, %rdx         rdx 存有 (ux * uy)/2^64 - (Sx*y + Sy*x)
movq    %rax, (%rdi)       低 64 位
movq    %rdx, 8(%rdi)      高 64 位
ret

3.60

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

3.61

long cread(long *xp) {
    return (xp ? *xp : 0);
}

long cread_alt(long *xp) {
    return (!xp ? 0 : *xp);
}

// 现在的编译器比较智能,已经不会像书中一样编译这段代码了。

3.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 = *p1;
            break;
        case MODE_B:
            result = *p1 + *p2;
            *p1 = result;
            break;
        case MODE_C:
            *p1 = 59;
            result = *p2;
            break;
        case MODE_D:
            *p1 = *p2;
        case MODE_E:
            result = 27;
            break;
        default:
            result = 12;
            break;
    }
    return result;
}

3.63

long switch_prob(long x, long n) {
    long result = x;
    switch (n) {

        case 60:
        case 62:
            result = 8 * x;
            break;
        case 63:
            result = x >> 3;
            break;
        case 64:
            result = x * 15;
            x = result;
        case 65:
            x = x * x;
        case 61:
        default:
            result = 75 + x;
    }
    return result;
}

3.64

&D[i][j][k] = D + (S*T*i + T*j + k) * L

R = 7
S = 5
T = 13

3.65

A.
&A[i][j] in %rdx

B.
&A[j][i] in %rax

C.
M = 15

3.66

NR(n) == 3*n
NC(n) == n*4 + 1

3.67

A.

104  +------------------+
     |                  |
     |                  |
     |                  |
     |                  |
     |                  |
     |                  |
     |                  |
     |                  |
 64  +------------------+ <-- %rdi
     |                  |
     |                  |
     |                  |
     |                  |
     |                  |
     |                  |
 32  +------------------+
     |         z        |
 24  +------------------+
     |        &z        |
 16  +------------------+
     |         y        |
  8  +------------------+
     |         x        |
  0  +------------------+ <-- %rsp

B.
eval 传了一个新地址给 process ,新地址是 %rsp+64

C.
process 通过栈指针来访问 s,而不是通过 %rdi

D.
process 将参数 %rsp+64 设置为起点,将 r 的成员设置进来,并在最后返回 r 的指针。

E.

104  +------------------+
     |                  |
     |                  |
     |                  |
     |                  |
     |                  |
     |                  |
 88  +------------------+
     |        z         |
 80  +------------------+
     |        x         |
 72  +------------------+
     |        y         |
 64  +------------------+ <-- %rdi(eval pass in)
     |                  |  \
     |                  |   -- %rax(process pass out)
     |                  |
     |                  |
     |                  |
     |                  |
 32  +------------------+
     |         z        |
 24  +------------------+
     |        &z        |
 16  +------------------+
     |         y        |
  8  +------------------+
     |         x        |
  0  +------------------+ <-- %rsp in eval
     |                  |
 -8  +------------------+ <-- %rsp in process

F.
调用者设置一个地址给被调用者作为起点存储成员数据,被调用者最后返回这个地址。

3.68

提示:考虑对齐产生的空隙,所以最后产生的一个范围
4 < B <= 8
6 < A <= 10
44 < A*B <= 46

得:A=9, B=5

3.69

A.
CNT = 7

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

3.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;
}

3.71

#include <stdio.h>
#include <assert.h>

#define BUF_SIZE 12

void good_echo(void) {
    char buf[BUF_SIZE];
    while (1) {
        /* function fgets is interesting */
        char *p = fgets(buf, BUF_SIZE, stdin);
        if (p == NULL) {
            break;
        }
        printf("%s", p);
    }
    return;
}

int main(int argc, char *argv[]) {
    good_echo();
    return 0;
}

3.72

A.
n 是奇数时:
s_2 = s_1 - (n * 8 + 24)
n 是偶数时:
s_2 = s_1 - (n * 8 + 16) s

B.
p 是 16 位的倍数

C.

-- e1 n s1
最小 1 偶数 n%16==1
最大 24 奇数 n%16==0

D.
p 按 16 字节对齐,
s2 十六的倍数,并且至少有 8*n 的空间。

3.73

#include <stdio.h>
#include <assert.h>

typedef enum {
    NEG, ZERO, POS, OTHER
} range_t;

range_t find_range(float x) {
    __asm__(
    "vxorps %xmm1, %xmm1, %xmm1\n\t"
    "vucomiss %xmm1, %xmm0\n\t"
    "jp .P\n\t"
    "ja .A\n\t"
    "jb .B\n\t"
    "je .E\n\t"
    ".A:\n\t"
    "movl $2, %eax\n\t"
    "ret\n\t"
    ".B:\n\t"
    "movl $0, %eax\n\t"
    "ret\n\t"
    ".E:\n\t"
    "movl $1, %eax\n\t"
    "ret\n\t"
    ".P:\n\t"
    "movl $3, %eax\n\t"
    "ret\n\t"
    );
}

int main(int argc, char *argv[]) {
    range_t n = NEG, z = ZERO, p = POS, o = OTHER;
    assert(o == find_range(0.0 / 0.0));
    assert(n == find_range(-2.3));
    assert(z == find_range(0.0));
    assert(p == find_range(3.33));
    return 0;
}

3.74

#include <stdio.h>
#include <assert.h>

typedef enum {
    NEG, ZERO, POS, OTHER
} range_t;

range_t find_range(float x) {
    __asm__(
    "vxorps %xmm1, %xmm1, %xmm1\n\t"
    "movq $1, %rax\n\t"
    "movq $2, %r8\n\t"
    "movq $0, %r9\n\t"
    "movq $3, %r10\n\t"
    "vucomiss %xmm1, %xmm0\n\t"
    "cmovaq %r8, %rax\n\t"
    "cmovbq %r9, %rax\n\t"
    "cmovpq %r10, %rax\n\t"
    );
}

int main(int argc, char *argv[]) {
    range_t n = NEG, z = ZERO, p = POS, o = OTHER;
    assert(o == find_range(0.0 / 0.0));
    assert(n == find_range(-2.3));
    assert(z == find_range(0.0));
    assert(p == find_range(3.33));
    return 0;
}