CSAPP 第三版 第三章 家庭作业
自己做的 仅供参考 可能出现错误
注:3.60 3.67mark一下
3.58
long decode2(long x, long y, long z)
{
return (((y - z) << 63) >> 63) ^ (x * (y - z));
}
3.59
store_prod:
movq %rdx, %rax # %rax = y
cqto # 4字按符号位拓展到8字,%rdx = yh,%rax = yl
movq %rsi, %rcx # %rcx = x
sarq $63, %rcx # 将%rcx向右移63位,相当于做符号位扩展,%rcx = xh,%rsi = xl
imulq %rax, %rcx # %rcx = yl * xh
imulq %rsi, %rdx # %rdx = xl * yh
addq %rdx, %rcx # %rcx = yl * xh + xl * yh
mulq %rsi # 无符号计算 xl*yl,并将xl*yl的128位结果的高位放在%rdx,低位放在%rax
addq %rcx, %rdx # 将高位计算结果加到%rdx
movq %rax, (%rdi) # 将%rax的值放到dest的低位
movq %rdx, 8(%rdi)# 将%rdx的值放到dest的高位
ret
3.60
A. %rdi -> x;
%esi -> n;
%rax -> result;
%rdx -> mask;
B. result = 0;
mask = 1;
C. mask != 0;
D. mask = mask << (n % 64);
E. result |= (x & mask);
F.
long loop(long x, int n)
{
long result = 0;
long mask;
for (mask = 1; mask != 0; mask = mask << (n & 0x3F))
{
result |= (x & mask);
}
return result;
}
x86-64中,移位操作对w位长的数据值进行操作,移位量是由%cl寄存器的低m位决定的,这里2m=w。高位会被忽略。所以salb移位量由%cl低3位、salw移位量由%cl低4位、sall移位量由%cl低5位、salq移位量由%cl低6位决定。故
mask = mask << (n & 0x3F)
但是不取余(n % 64)也可以,因为编译器自己会处理
3.61
测试了各种,发现这种写法在-O1优化选项下没有跳转语句(有三目表达式)
long cread_alt1(long *xp)
{
long t = 0;
long *p = xp ? xp : &t;
return *p;
}
3.62
/* 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:
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;
result = 27;
break;
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 = x * 8;
break;
case 63:
result = result >> 3;
break;
case 64:
result = (result << 4) - x;
x = result;
case 65:
x = x * x;
default:
result = x + 75;
}
}
3.64
A. &A[i][j][k] = A + L * (T * S * i + T * j + k);
B. R = 7;S = 5;T = 13;
3.65
A. %rdx;
B. %rax;
C. 15;
3.66
NR(n) = 3 * n;
NC(n) = 4 * n + 1;
3.67
A. %rsp -> x;
%rsp + 8 -> y;
%rsp + 16 -> &z;//结构体strA s部分
%rsp + 24 -> z;
B. %rsp + 64;
C. %rsp + bias;
D. %rdi + bias;
E. %rsp + 64 -> y
%rsp + 72 -> x
%rsp + 80 -> z//结构体strB s部分
F. 结构体传递参数或作为返回值均为其首地址值
3.68
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.
union ele {
struct {
long *p;
long y;
}e1;
struct {
long x;
union ele *next;
}e2;
};
void proc(union ele *up) {
up->e2.x = *(up->e2.next->e1.p) - up->e2.next->e1.y;
//想写up->e2.x = *(*(up->e2.next).e1.p) - *(up->e2.next).e1.y;但是vs报错:表达式必须包含类类型
}
3.71
首先阅读fgets相关信息
http://www.cplusplus.com/reference/cstdio/fgets/
fgets
char * fgets ( char * str, int num, FILE * stream );
Get string from stream
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.
A terminating null character is automatically appended after the characters copied to str.
Notice that fgets is quite different from gets: not only fgets accepts a stream argument, but also allows to specify the maximum size of str and includes in the string any ending newline character.
Parameters
str
Pointer to an array of chars where the string read is copied.
num
Maximum number of characters to be copied into str (including the terminating null-character).
stream
Pointer to a FILE object that identifies an input stream.
stdin can be used as argument to read from the standard input.
Return Value
On success, the function returns str.
If the end-of-file is encountered while attempting to read a character, the eof indicator is set (feof). If this happens before any characters could be read, the pointer returned is a null pointer (and the contents of str remain unchanged).
If a read error occurs, the error indicator (ferror) is set and a null pointer is also returned (but the contents pointed by str may have changed).
void good_echo(void) {
const int BUF_SIZE = 12;
char buf[BUF_SIZE];
while (1) {
char* p = fgets(buf, BUF_SIZE, stdin);
if (ferror(stdin) || p == NULL) {
break;//题目说遇到错误条件返回也没说做啥特殊处理……例如把buf数组清空类似处理
}
fprintf(stdout, "%s", p);
}
return;
}
3.72
A. s1 - (8 * n + 16) n为偶数时;
s1 - (8 * n + 24) n为奇数时;
B. (s2 + 15) & 0xfffffff0;
C. e1 max n为奇数,s2 % 16 == 0;
e1 min n为偶数,s2 % 16 == 1;
D. p 以16位对齐;
s2保证有>= 8 * n的最小十六倍数+ 16的空间;
3.73
find_range:
vxorps %xmm1, %xmm1, %xmm1
vucomiss %xmm1, %xmm0
jp .L1
ja .L2
jb .L3
je .L4
.L2:
movl $2, %eax
ret
.L3:
movl $0, %eax
ret
.L4:
movl $1, %eax
ret
.L1:
movl $3, %eax
rep; ret
3.74
find_range:
vxorps %xmm1, %xmm1, %xmm1
movq $1, %r8
movq $2, %r9
movq $3, %r10
movq $0, %rax
vucomiss %xmm1, %xmm0
cmove %r8, %rax
cmova %r9, %rax
cmovp %r10,%rax
3.75
A. 实部 %xmm(2 * n - 2);
虚部 %xmm(2 * n - 1);
B. 实部 %xmm0;
虚部 %xmm1;