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