《深入理解计算机系统》第三版 第三章家庭作业答案

简述

相信大部分人在做这些题的时候,因为书中没有给答案,而去网上找参考答案,比如那些高阅读量的博客和git。当然,我也是这样,但他们的答案中还是有好多错误,比如3.59他们几乎都没讲清楚提示中的公式怎么来的,3.60中对移位操作中对%cl的读取,等等。。希望读者们在阅读这些文章时,要带着自己的思想和疑问去理解,而不是一味地觉得答案就肯定是对的,当然,本文有任何错误,也欢迎各位指出。

3.58

long decode2(long x,long y,long z)
{
	y = y - z;
	x = x * y;
	y <<= 63;
	y >>= 63;
    return y ^ x;
}

y先左移63位,再右移63位,如果之前y是奇数,那么y的二进制全是1;y是偶数,那么y的二进制全是0.

3.59

在这里插入图片描述
首先讲解一下,提示里的公式 x = 2 64 ∗ x h + x l x=2^{64}*x_h+x_l x=264xh+xl,之所以可以这么写是因为符号拓展,以4位二进制int为例:
1111的补码数,为-1.将其进行符号拓展后为1111 1111,其值也为-1,但这里可以将1111 1111写为高位1111的补码数 * 2 4 2^4 24 + 低位1111的无符号数:
即-1 * 2 4 2^4 24 + 15 = -1.

原理:%rdx和%rax的二进制连起来表示这个数,既然连起来了,符号位就跑到了%rdx的最高位了,除符号位权值为负外,其余位的权值均为正。所以,高位寄存器%rdx当做补码数,低位寄存器%rax当做无符号数。因为符号位现在在高位寄存器那儿呢,所以高位寄存器当做补码数了;而低位寄存器的每一位的权值现在都是正的了,所以低位寄存器要当做无符号数。

所以 x l x_l xl T 2 U ( x ) T2U(x) T2U(x)即x的二进制表示作为无符号数。 x l x_l xl x x x有相同的位级表示。
x h x_h xh,当原数符号位为1,64位二进制位上全为1,其值为-1;当原数符号位为0时,64位二进制位上全为0,其值为0。

再讲解一下本文用到的数学公式:有 x = 2 64 ∗ x h + x l x=2^{64}*x_h+x_l x=264xh+xl y = 2 64 ∗ y h + y l y=2^{64}*y_h+y_l y=264yh+yl,那么有:
x ∗ y = ( 2 64 ∗ x h + x l ) ∗ ( 2 64 ∗ y h + y l ) x*y=(2^{64}*x_h+x_l)*(2^{64}*y_h+y_l) xy=(264xh+xl)(264yh+yl)
= x h y h 2 128 + ( x h y l + x l y h ) 2 64 + x l y l =x_hy_h2^{128}+(x_hy_l+x_ly_h)2^{64}+x_ly_l =xhyh2128+(xhyl+xlyh)264+xlyl
但这个公式其实并不陌生,它与2.3.5补码乘法(P67) 里面的公式2.18有异曲同工之妙,另外理解本题需要阅读此节。

第一项 x h y h 2 128 x_hy_h2^{128} xhyh2128肯定溢出,双寄存器都装不下,截断后全为0,忽略。

关于第二项, ( x h y l + x l y h ) (x_hy_l+x_ly_h) (xhyl+xlyh)这个数值是需要放在高位寄存器中的(因为这一项乘以的数为 2 64 2^{64} 264),假设 x h y l x_hy_l xhyl分别是-1和UMAX,仅仅是它俩的乘积都会使得高位寄存器溢出(考虑补码数和无符号数的表示范围就能想到),如果溢出,放入高位寄存器时会自行截断。

第三项 x l y l x_ly_l xlyl,直接使用双寄存器来保存结果。

下面开始讲解汇编代码:
第一个参数*dest在%rdi中,第二个参数x在%rsi中,第三个参数y在%rdx中。

store_prod:
    movq   %rdx, %rax   # %rax = y
    cqto                # convert q to o,4字符号拓展到8字,假如y的符号位为1,那么%rdx所有位都是1(此时值是-1),否则,%rdx全为0(此时值是0).%rdx = yh
    movq   %rsi, %rcx   # %rcx = x
    sarq   $63,  %rcx   # 将%rcx向右移63位,跟%rdx的含义一样,二进制位要么全是1,要么是0,%rcx = xh.
    imulq  %rax, %rcx   # %rcx = y * xh
    imulq  %rsi, %rdx   # %rdx = x * yh
    addq   %rdx, %rcx   # %rcx = y * xh + x * 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

重点讲一下6-8行,发现这里代码计算的是 ( x h y + x y h ) (x_hy+xy_h) (xhy+xyh),而数学公式里面要求是 ( x h y l + x l y h ) (x_hy_l+x_ly_h) (xhyl+xlyh),之所以汇编要如此计算,是利用了相同的位级向量,无论用无符号数乘法还是补码乘法,其结果的截断的位级表示肯定是一样的。

但这里有点不一样,给定 x ⃗ \vec x x y ⃗ \vec y y 两个位级向量,固定将 x ⃗ \vec x x 看作补码数,而将 y ⃗ \vec y y 分别看作补码数和无符号数,那么x与y的两种乘积的截断的位级表示是一样的。接下来用个小例子来证明该结论。(注意代码是将乘积的截断的位级表示看作补码数的)
假设整数类型为3位, x ⃗ \vec x x y ⃗ \vec y y 分别为111111,x的值为-1,而y的值分别为-1,7.
首先看-1 * -1 = 1,那么位级表示为001
再看-1 * 7 = -7,那么位级表示为1001,截断后为001
证毕。

考虑下第9行是否会溢出,无符号数最大为 2 64 − 1 2^{64}-1 2641,所以两个无符号数的乘积最大为 ( 2 64 − 1 ) 2 (2^{64}-1)^2 (2641)2等于 2 128 + 1 − 2 65 2^{128}+1-2^{65} 2128+1265.而128位的补码数的最大范围为 2 127 − 1 2^{127}-1 21271.
( 2 128 + 1 − 2 65 ) − ( 2 127 − 1 ) (2^{128}+1-2^{65})-(2^{127}-1) (2128+1265)(21271) = 2 127 + 2 − 2 65 2^{127}+2-2^{65} 2127+2265 > 0,所以可能溢出。

3.60

long loop(long x,int n)
{
	long result = 0;
	long mask;
	for(mask = 1;maks != 0;mask=mask << (n % 64))//如果这里不能保证是正余数(0-63)的话,就用下面的写法
	{
		result |= (x & mask);
	}
	return result;
}

这里难点主要在于salq %cl, %rdx这里的移位量到底是多少,根据移位操作中的解释,因为被移位数为64位二进制( 2 6 = 64 2^6 = 64 26=64),所以只看%cl的低6位,或者循环的执行可以改为mask=mask<<(n & 0x3F)

3.61

在这里插入图片描述
首先看上图c语句与其汇编语句的对应(3.6.6节),题目要求新函数对应的汇编代码也会用到条件传送,即要求有三目表达式。对于第4行,看起来可能是多余的,但3.6.6节讲到条件传送中,第一个操作数可以是源寄存器或者内存地址,所以立即数是不可以,所以这里多了一步。

如果函数改成long cread_alt(long *xp) { return (!xp ? 0 : *xp); },那么汇编代码可能是:

cread_alt:
  movl $0, %eax
  testq %rdi, %rdi
  cmovne (%rdi), %rax #直接传送
  ret

当然也可以改成如下:

long cread_alt(long *xp)
{
    long t = 0;
    long *p = xp ? xp : &t; //得到xp指针或者0的地址,这句转换为条件传送语句后,也不会可能去读取空指针
    return *p; //解引用,现在读取指针指向值肯定不会出错
}

为了验证汇编代码,本人用MinGW进行了编译,使用命令gcc -Og -S test.c,c文件内容为long cread(long *xp) { return (xp ? *xp : 0); },发现不管优化程度是多少,生成汇编基本都是(发现并没有使用条件传送,且没怎么看懂):

LFB0:
	movl	4(%esp), %eax #得到了xp指针
	testl	%eax, %eax 
	je	L3
	movl	(%eax), %eax #指针不为空,读取指针指向的值
	ret
L3:
	xorl	%eax, %eax
	ret

3.62

锻炼你的反向工程能力。注意有的语句可以简化,不用非得照着汇编原封不动翻译。

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:
      *p1 = *p1 + *p2;
      result = *p1;
      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

在这里插入图片描述

0000000000400590<switch_prob>:
    400590: 48 83 ee 3c    sub $0x3c, %rsi #n -= 60,说明最后n的实际数要加60
    400594: 48 83 fe 05    cmp $0x5, %rsi #比较n > 5
    400598: 77 29          ja  4005c3 <switch_prob+0x33> #如果n > 5那么跳转到default
    # 所以n <= 5的情况就只有交给跳转表处理
    40059a: ff 24 f5 f8 06 40 00   jmpq *0x4006f8(,%rsi,8) #间接跳转到0x4006f8 + 8*n
    # 跳到跳转表对应的位置,从跳转表来看,n的取值只能是0-5,因为只有6个八字节
    
    # 0和2会跳到这个位置
    4005a1: 48 8d 04 fd 00 00 00   lea  0x0(,%rdi,8),%rax
    4005a8: 00
    400593: c3             retq
    # 3会跳到这个位置
    4005aa: 48 89 f8       mov %rdi, %rax
    4005ad: 48 c1 f8 03    sar $0x3, %rax
    4005b1: c3             retq
    # 4会跳到这个位置
    4005b2: 48 89 f8       mov %rdi, %rax
    4005b5: 48 c1 e0 04    shl $0x4, %rax
    4005b9: 48 29 f8       sub %rdi, %rax
    4005bc: 48 89 c7       mov %rax, %rdi
    # 5会跳到这个位置
    4005bf: 48 0f af ff    imul %rdi, %rdi
    # 大于5和1会跳到这个位置
    4005c3: 48 8d 47 4b    lea 0x4b(%rdi), %rax
    4005c7: c3             retq 

而且从汇编代码来看,如果n的值是<60,那么n-60<0,那么汇编代码就会执行到jmpq *0x4006f8(,%rsi,8),本来应该跳转到这6个八字节,但最终间接跳转到非法的八字节。但也许此题重点不在于此,应假设n>=60.

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;//注意64,65后面没有break
        default:
            result = x + 75;
    }
}

3.64

假设有数组 D [ S ] [ T ] D[S][T] D[S][T],等式3.1为 D + L ( T ⋅ i + j ) D+L(T \cdot i+j) D+L(Ti+j),这里T明显为列数,更加深入的说,代表第一维度中每个维度的元素个数。
假设有数组 D [ R ] [ S ] [ T ] D[R][S][T] D[R][S][T],等式3.1应为 D + L ( S T ⋅ i + T ⋅ j + k ) D+L(ST \cdot i+ T \cdot j + k) D+L(STi+Tj+k),ST为第一维度中每个维度的元素个数。

store_ele:
    leaq  (%rsi, %rsi, 2), %rax  # %rax = 3 * j
    leaq  (%rsi, %rax, 4), %rax  # %rax = j + 4(3j) = 13 * j
    leaq  %rdi, %rsi             # %rsi = i
    salq  $6, %rsi               # %rsi * = 64
    addq  %rsi, %rdi             # %rdi = 65 * i
    addq  %rax, %rdi             # %rdi = 65 * i + 13 * j
    addq  %rdi, %rdx             # %rdx = 65 * i + 13 * j + k
    movq  A(, %rdx, 8), %rax     # %rax = A + 8 * (65 * i + 13 * j + k)
    movq  %rax, (%rcx)           # *dest = A[65 * i + 13 * j + k]
    movl  $3640, %eax            # sizeof(A) = 3640
    ret

则有:

S * T = 65
T = 13
S * T * R * 8 = 3640

得到:R = 7 ; S = 5 ; T = 13

3.65

.L6:
    movq  (%rdx), %rcx  # t1 = A[i][j]
    movq  (%rax), %rsi  # t2 = A[j][i]
    movq  %rsi, (%rdx)  # A[i][j] = t2
    movq  %rcx, (%rax)  # A[j][i] = t1
    addq  $8, %rdx      # A[i][j] -> A[i][j+1]
    addq  $120, %rax    # A[j][i] -> A[j+1][i], 120 == 8*M
    cmpq  %rdi, %rax    
    jne   .L6           # if A[j][i] != A[M][M]

A.从第6行就能看出来%rdx是A[i][j],因为每次只加8,即一个元素大小。
B.因为寄存器%rdx是A[i][j],所以另一个寄存器%rax是A[j][i]。
C.根据公式,120 == 8*M,所以M为15.

3.66

sum_col:
    leaq   1(, %rdi, 4), %r8        # %r8 = 4 * n + 1
    leaq   (%rdi, %rdi, 2), %rax    # result = 3 * n
    movq   %rax, %rdi               # %rdi = 3 * n
    testq  %rax, %rax
    jle    .L4                      # if %rax <= 0, goto L4
    salq   $3, %r8                  # %r8 = 8 * (4 * n + 1)
    leaq   (%rsi, %rdx, 8), %rcx    # %rcx = A[0][j]的地址
    movl   $0, %eax                 # result = 0
    movl   $0, %edx                 # i = 0
.L3:
    addq   (%rcx), %rax             # result += A[i][j]
    addq   $1, %rdx                 # i += 1
    addq   %r8, %rcx                # 这里每次+8*(4n+1),说明每一行有4n+1个,因此NC(n)为4*n+1
    cmpq   %rdi, %rdx               
    jne    .L3                      # 当%rdx等于3*n才循环结束,所以可以说明一共有3n行,因此NR(n)为3*n
    rep; ret
.L4:
    movl $0, %eax
    ret

所以有NR(n) = 3 * n; NC(n) = 4 * n + 1;

3.67

# strB process(strA s)
# s in %rdi
process:
  movq %rdi, %rax        #第一个参数作为返回值,即要返回的结构体的开始地址
  movq 24(%rsp), %rdx	#栈指针开始的第4个八字节的内容,存入%rdx,内容为结构体A的第二个成员:指针p
  movq (%rdx), %rdx      #读取指针p指向的long型对象,再存入%rdx
  movq 16(%rsp), %rcx    #栈指针开始的第3个八字节的内容,内容为结构体A的成员数组的第2个元素:D[1]
  movq %rcx, (%rdi)      #将D[1],存入返回结构体的第1个八字节
  movq 8(%rsp), %rcx     #栈指针开始的第2个八字节的内容,内容为结构体A的成员数组的第1个元素:D[0]
  movq %rcx, 8(%rdi)     #将D[0],存入返回结构体的第2个八字节
  movq %rdx, 16(%rdi)    #将long型对象,存入返回结构体的第3个八字节
  #栈指针开始的第1个八字节,这里并没有使用,因为存的是调用后的返回地址
  ret
# long eval(long x, long y, long z)
# x in %rdi, y in %rsi, z in %rdx
eval:
  subq $104, %rsp       #为栈分配了13*8字节空间,即13个八字节
  movq %rdx, 24(%rsp)   #z存入栈指针开始的第4个八字节
  leaq 24(%rsp), %rax   #栈指针开始的第4个八字节中的第一个字节的地址,存入%rax,作为结构体A的指针成员p
  movq %rdi, (%rsp)     #x存入栈指针开始的第1个八字节
  movq %rsi, 8(%rsp)    #y存入栈指针开始的第2个八字节
  movq %rax, 16(%rsp)   #p存入栈指针开始的第3个八字节
  leaq 64(%rsp), %rdi   #栈指针开始的第9个八字节,的开始地址
  call process          #这里有隐藏操作,分配八字节栈空间,存入返回地址,即下一行代码地址
  movq 72(%rsp), %rax   #这三行汇编执行加法
  addq 64(%rsp), %rax
  addq 80(%rsp), %rax
  addq $104, %rsp       #回收栈空间
  ret

A.
在这里插入图片描述
注意此图中,从下往上是地址增加方向。
B.
传递了%rsp+64,即栈指针开始的第9个八字节,的开始地址。
C.
因为结构参数s存在栈空间里,所以用%rsp+偏移量来访问的。
D.
r的空间是分配在栈空间里,所以也是%rsp+偏移量来设置的。
E.
在这里插入图片描述
F.
结构体作为参数传入和返回时,都是以指针来传递。

3.68

从汇编movslq 8(%rsi), %rax中,可以看出结构体str2中int t是从第2个八字节开始:
在这里插入图片描述
左边为最大情况,右边为最小情况。在最小情况中,如果数组再少一个元素,即数组大小由5字节变成4字节,那么int变量就会跑到第1个八字节中去了。
所以5<=B<=8.

从汇编addq 32(%rsi), %rax中,可以看出结构体str2中long u是从第5个八字节开始:
在这里插入图片描述
左边为最大情况,右边为最小情况。
所以7<=A<=10.

从汇编movq %rax, 184(%rdi)中,184既可能是最大情况,也可能是8字节补齐情况。
所以184-8<A*B*4<=184.

答案唯一解为:A=9; B=5;

3.69

从c语句ap->x[ap->idx] = n;知道a_struct的两个成员分别是数组和整数类型。

# void test(long i, b_struct *bp)
# i in %rdi, bp in %rsi
test:
  mov 0x120(%rsi), %ecx         # bp+288 匹配bp->last
  add (%rsi), %ecx              # bp->first + bp->last
  lea (%rdi,%rdi,4), %rax       # %rax = i*5
  lea (%rsi,%rax,8), %rax       # %rax = bp+i*40

  # ap = &bp->a[i] = bp+8+i*40, +8意味着从bp开始的第1个八字节里面只有int,且a_struct大小必为8字节或更大,若为4字节,就不是+8而是+4了
  # 因为是i*40,所以a_struct大小为40字节
  # 此句很明显取出了一个数,再结合倒数第二条指令mov %rcx, 0x10(%rax,%rdx,8),所以%rdx为ap->idx
  # 而且在结构体a_struct中,第一个成员为整数类型的idx
  mov 0x8(%rax), %rdx

  movslq %ecx, %rcx             # mov时符号拓展成4字8字节

  # 先看0x10(%rax,)部分,是bp+16+i*40,比ap多了8字节,这里是a_struct数组成员的开始地址,也说明了idx大小为8字节
  # 再看(,%rdx,8)部分,是idx*8,所以说明了a_struct数组成员的大小为8字节
  # 合起来看就是bp+8+i*40+8 +idx*8,第二个+8跳过了a_struct的整数成员idx
  mov %rcx, 0x10(%rax,%rdx,8)

  # a_struct大小为40字节,第一个成员idx为long,8字节,还剩32字节
  # 第二个成员是long型数组,按照剩余字节,数组大小为4
  retq

A.
因为7*40 + 8 = 288 = 0x120,所以CNT=7,要推出CNT必须先推理出a_struct的大小。
B.

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

3.70

   proc:
       movq    8(%rdi), %rax  #偏移量为8,存的是up->e1.y或者是up->e2.next
       movq    (%rax), %rdx   #用作内存引用,所以上面是up->e2.next,取出*(up->e2.next)的偏移量为0的内容,也有两种情况
       movq    (%rdx), %rdx   #用作内存引用,所以上面是*(up->e2.next).e1.p,取出*( *(up->e2.next).e1.p )的内容,为long型
       subq    8(%rax), %rdx  #取出*(up->e2.next)的偏移量为8的内容,因为要作为减数,所以减数是*(up->e2.next).e1.y
       movq    %rdx, (%rdi)   #将减法之差存入,up->e2.x
       ret

A.

e1.p     0
e1.y     8
e2.x     0
e2.next  8

B.
16
C.
up->e2.x = *( *(up->e2.next).e1.p ) - *(up->e2.next).e1.y,具体看注释。

3.71

这道题主要需要了解fgets函数(char * fgets ( char * str, int num, FILE * stream );)。下面将fgets函数的api文档进行翻译。

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.

从流中读取字符,并将它们作为C string存储进str参数中,直到num-1个字符已经被读取,或者是到达新行或者EOF,这三个条件谁先到达都会使得读取停止。
换行字符使得fgets函数停止读取,不过换行符也会被当做一个合法字符来读取。
一个空字符将会自动加在读取的字符后,然后再复制给str。

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).

当函数执行成功,返回str。
当读取字符时遇到一个EOF时,EOF标识符被设置。如果在任何字符都没有进行读取时,就发生了这样的事,那么返回空指针(str指向的文本保持不变)。如果发生了读取错误,那么error标识符被设置,也返回空指针(但str指向的文本可能会改变)。

#include <stdio.h>
#include <assert.h>
#define BUF_SIZE 12

void good_echo(void) {
  char buf[BUF_SIZE];
  while(1) {
    char* p = fgets(buf, BUF_SIZE, stdin);
    if (p == NULL) {//这里需要改
      break;
    }
    printf("%s", p);
  }
  return;
}

1.根据翻译得知,使用fgets函数便可以保证“当输入字符超过缓冲区空间大小时,也能正常工作”。
2.关于“你的代码还应该检查错误条件,在遇到错误条件时返回”这点,其实判断条件if (p == NULL)太笼统了,可以通过ferror函数int ferror ( FILE * stream );)来判断(stdin的类型是FILE *),当读取出错时,调用ferror函数返回非0值,上述代码应写成if ( (p == NULL) & (ferror(stdin) != 0) )

3.72

此题与练习题3.49几乎一模一样,具体讲解请看此篇博客。
注意c语句long **p = alloca(n * sizeof(long*));,p的类型为long **即long指针的指针,可以这么理解,分配long型数组时,返回long *指针;当分配long *型数组时,返回long **指针。
在这里插入图片描述
第5行%rax存的是30+8n。
第6行分为两种情况:(and -16解释为向下取整到16的倍数)
a.当为偶数时,分成8n和30两部分,8n and -16得8n,30 and -16得16.
b.当为奇数时,分成8(n-1)和38两部分,8(n-1) and -16得8(n-1),38 and -16得32.
第8行加上偏置15( 2 4 − 1 2^4-1 241),第9行 and -16,执行完这两行,就相当于向上取整到16的倍数。注意在练习题3.49中,andq $-16, %r8这句是通过两句汇编来实现的(先右移再左移,而本题是直接and -16)。
A.
s 2 = s 1 − ( ( 8 ∗ n + 30 ) &amp; 0 x f f f f f f f 0 ) s_2 = s_1 - ((8 * n + 30) \&amp; 0xfffffff0) s2=s1((8n+30)&0xfffffff0),根据上面的分析:
当n为偶数时, s 2 = s 1 − ( 8 ∗ n + 16 ) s_2 = s_1 - (8 * n + 16) s2=s1(8n+16)
当n为奇数时, s 2 = s 1 − ( 8 ∗ n + 24 ) s_2 = s_1 - (8 * n + 24) s2=s1(8n+24)

B.
p = ( s 2 + 15 ) &amp; 0 x f f f f f f f 0 p = (s_2 + 15) \&amp; 0xfffffff0 p=(s2+15)&0xfffffff0

C.
大方向分为,当 s 2 s_2 s2为16的倍数(这种情况p数组就直接从 s 2 s_2 s2开始分配),和 s 2 s_2 s2不为16的倍数(这种情况p数组还需要向地址增加方向滑动1-15个字节)。

1.因为e1和e2是用来滑动的,所以当e2为0,即 s 2 s_2 s2为16的倍数时,当e1就会最大。再看当n为奇数时,分配数组空间为8 * n + 24,多出来24字节空间作为e1。e1最大为24,此时 s 2 s_2 s2为16的倍数,且n为奇数。

2.当 s 2 s_2 s2不为16的倍数时,p数组空间需要滑动来16对齐,当 s 2 s_2 s2%16=1时,向地址增加方向滑动15个字节,此时达到最大滑动距离了,即e2=15。而e1=可滑动空间-e2,当n为偶数时,滑动空间为16字节,则e1=可滑动空间-e2=16-15=1。e1最小为1,此时 s 2 s_2 s2%16=1,且n为偶数。

D.
p数组空间是16对齐的。
s 2 s_2 s2是容下8 * n字节的最小的16的倍数再加16。

3.73

原书中的汇编即图3-51中的汇编,确实很乱,这样改完之后清爽多了。

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

这样的话,连cmovp都不需要用了。

find_range:
    vxorps %xmm1, %xmm1, %xmm1
    movq $0, %r8
    movq $1, %r9
    movq $2, %r10
    movq $3, %rax
    vucomiss %xmm1, %xmm0
    cmovb %r8, %rax
    cmove %r9, %rax
    cmova %r10, %rax
    ret

在这里插入图片描述
在这里插入图片描述
可以看出在比较大于小于时,有两套指令可以用,但因为比较浮点数用到的标志位为CF和ZF,所以再看上表,则应该使用下面这套指令。

3.75

A.

第n个参数realimg
1%xmm0%xmm1
2%xmm2%xmm3
3%xmm4%xmm5
n%xmm(2n-2)%xmm(2n-1)

B.
imag部分返回值在%xmm1, real部分返回值在%xmm0.

  • 42
    点赞
  • 163
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
【石油大学】计算机网络课程设计-第三次在线作业 试卷总分:100 得分:100 第1题,1.(2.5分)下列各项中不属于配置管理的内容的是() A、定义新的管理对象 B、识别管理对象 C、网络资源之间的关系的监视和控制 D、接收差错报告并作出反应 正确答案:D 第2题,2.(2.5分)以下()不是目前使用的标准网络管理协议 A、SNMP B、CMIS/CMIP C、TCP/IP D、LMMP 正确答案:C 第3题,3.(2.5分)以下网络攻击中,哪种不属于主动攻击() A、通信量分析攻击 B、重放攻击 C、拒绝服务攻击 D、假冒攻击 正确答案:A 第4题,4.(2.5分)基于网络底层协议、利用实现协议的漏洞达到攻击目的,这种攻击方 式称为() A、被动攻击 B、非服务攻击 C、人身攻击 D、服务攻击 正确答案:B 第5题,5.(2.5分)预测(假冒)TCP初始序号和利用TCP/UDP数据包的DoS攻击(非授权 使用)属于TCP/IP中()的安全性范畴 A、网络层安全性 B、传输层安全性 C、应用层安全性 D、以上都不是 正确答案:B 第6题,6.(2.5分)以下()不是安全威胁的体现 A、删除 B、中断 C、截取 D、修改 正确答案:A 第7题,7.(2.5分)特洛伊木马攻击的威胁类型属于() A、旁路控制威胁 B、植入威胁 C、渗入威胁 D、授权侵犯威胁 正确答案:B 第8题,8.(2.5分)如果一个登录处理子系统允许处理一个特定的用户识别码,以绕过通 常的口令检查。这种威胁属于() A、陷门 B、假冒 C、中断 D、旁路控制 正确答案:A 第9题,9.(2.5分)防火墙中的数据包过滤技术是在哪一层对数据包进行过滤() A、数据链路层 B、网络层 C、物理层 D、会话层 正确答案:B 第10题,10.(2.5分)误码率是指二进制码元在数据传输系统中被传错的() A、字节数 B、速度 C、概率 D、比特数 正确答案:C 第11题,11.(2.5分)地址解析协议ARP属于TCP/IP的哪一层? A、主机-网络层 B、应用层 C、传输层 D、互联层 正确答案:D 第12题,12.(2.5分)采用直接交换方式的Ethernet交换机,其优点是交换延迟时间短, 不足之处是缺乏() A、并发交换能力 B、差错检测能力 C、地址解析能力 D、路由能力 正确答案:B 第13题,13.(2.5分)以下关于Ethernet地址的描述,哪个是错误的? A、MAC地址又叫做局域网物理地址 B、域名解析必然会用到MAC地址 C、局域网硬件地址存储在网卡之中 D、Ethernet地址就是通常所说的MAC地址 正确答案:B 第14题,14.(2.5分)以下关于Windows2000的描述中,哪一种说法是错误的? A、服务器的新功能之一是活动目录服务 B、域是基本的管理单位 C、域控制器不再区分主从结构 D、数据中心版适合数字家庭使用 正确答案:D 第15题,15.(2.5分)通信线路的带宽是描述通信线路的() A、传输能力 B、纠错能力 C、互联能力 D、物理尺寸 正确答案:A 第16题,16.(2.5分)在因特网中,屏蔽各个物理网络的差异主要通过以下哪个协议实现 ? A、IP B、TCP C、SNMP D、NETBEUI 正确答案:A 第17题,17.(2.5分)链路聚合的目的是保证()负载均衡。 A、链路 B、交换机 C、路由器 D、服务器 正确答案:A 第18题,18.(2.5分)链路聚合需要()的支持,不是所有交换机端口都可以设置成汇聚 模式。 A、软件 B、硬件 C、操作系统 D、传输介质 正确答案:B 第19题,19.(2.5分)在骨干网上对()的过多使用会给网络运行带来不必要的压力。 A、NAT B、QoS C、VLAN D、VPN 正确答案:B 第20题,20.(2.5分)硬件防火墙中的网卡一般都设置为()模式,这样就可以监测到流 过防火墙的数据。 A、混杂 B、交换 C、安全 D、配置 正确答案:A 第21题,21.(2.5分)应用层采用的安全技术有:加密、用户认证、()等。 A、VPN B、MD5 C、哈希函数 D、数字签名 正确答案:D 第22题,22.(2.5分)硬件防火墙至少应当具备三个接口:内网接口、外网接口和()接 口。 A、DMZ B、路由 C、控制 D、安全 正确答案:A 第23题,23.(2.5分)VPN是通过私有的()技术,在公共数据网络上仿真点到点专线技 术。 A、VLAN B、交换 C、隧道 D、安全 正确答案:C 第24题,24.(2.5分)()是实现网络安全最基本、最经济、最有效的措施之一。 A、防火墙 B、杀毒软件 C、IDS D、IPS 正确答案:A 第25题,25.(2.5分)()区域通常放置一些不含机
计算机应用基础(第版)在线作业 一 单项选择题 . 在中,按键,可删除。 插入点后面所有的字符 插入点前面所有的字符 插入点后面的一个字符 插入点前面的一个字符 本题分值: 用户得分: 用户解答: 插入点后面的一个字符 知识点: . 把一台普通的计算机变成多媒体计算机,要解决的关键技术不包括。 多媒体数据压缩编码技术 多媒体数据压缩解码技术 网络包分发技术 视频音频数据的输出技术 本题分值: 用户得分: 用户解答: 网络包分发技术 知识点: . 下面,不符合网络道德的做法是。 给不认识的人发电子邮件 利用博客发布广告 利用博客转发未经核实的攻击他人的文章 利用博客发表对某件事情的看法 本题分值: 用户得分: 用户解答: 利用博客转发未经核实的攻击他人的文章 知识点: . 启动操作系统时,要进入安全模式应按的键或组合键是。 本题分值: 用户得分: 用户解答: 知识点: . 电子邮件不可以传递。 图像 文字 音视频 汇款 本题分值: 用户得分: 用户解答: 汇款 知识点: . 域名服务的主要功能是。 为主机自动命名 合理分配地址 解析主机的地址 查询主机的地址 本题分值: 用户得分: 用户解答: 解析主机的地址 知识点: . 家庭接入属于哪种类型的网络接入。 以上都不是 企业接入 住宅接入 无线接入 本题分值: 用户得分: 用户解答: 住宅接入 知识点: . 协议采用方式传送数据。 请求响应 随机发送 自愿接收 被动接收 本题分值: 用户得分: 用户解答: 请求响应 知识点: . 当的任务栏在桌面屏幕的底部时,其右端的"通知区域"显示的是。 网络连接状态图标 时钟等 用于多个应用程序之间切换的图标 快速启动工具栏 "开始"按钮 本题分值: 用户得分: 用户解答: 网络连接状态图标 时钟等 知识点: . 计算机网络发展的第二个阶段,兴起于。 世纪年代 世纪年代 世纪年代 世纪年代 本题分值: 用户得分: 用户解答: 世纪年代 知识点: . 下列诸因素中,对微型计算机工作影响最小的是。 尘土 湿度 温度 噪声 本题分值: 用户得分: 用户解答: 噪声 知识点: . 计算机网络中常用的有总线型、星型、环形、树型和混合型。 规模结构 通信性能结构 拓扑结构 距离结构 本题分值: 用户得分: 用户解答: 拓扑结构 知识点: . 解决计算机网络间互联的标准化的问题是在发展阶段。 第三 第一和第四 第二和第一 第四和第二 本题分值: 用户得分: 用户解答: 第三 知识点: . 由构成计算机物理实体。 计算机程序 计算机系统 计算机软件 计算机硬件 本题分值: 用户得分: 用户解答: 计算机硬件 知识点: . 下列说法错误的是。 可发送的多媒体信息只有文字和图像 电子邮件具有快速 高效 方便 价廉等特点 通过电子邮件,可向世界上任何一个角落的网上用户发送信息 电子邮件是提供的一项最基本的服务 本题分值: 用户得分: 用户解答: 可发送的多媒体信息只有文字和图像 知识点: . 在 中,能够将文本中字符简体转换成繁体的设置。 在"插入"选项卡中 在"格式"选项卡中 在"审阅"选项卡中 在"开始"选项卡中 本题分值: 用户得分: 用户解答: 在"审阅"选项卡中 知识点: . 在 中,假定一个单元格所存入的公式为"*",则当该单元格处于编辑状态时显示的内容为。 * * 本题分值: 用户得分: 用户解答: * 知识点: . 以下对视频设备的描述中,正确的是。 视频卡主要用于捕捉 数字化 冻结 存储 输出 放大 缩小和调整来自激光视 盘机 录像机或摄像机的图像 视频设备的功能是处理数字化声音() 合成音乐() 音频等音频媒体 视频设备包括功放机 音箱 多媒体控制台 数字调音台等设备 电视卡是一种播放软件 本题分值: 用户得分: 用户解答: 视频卡主要用于捕捉 数字化 冻结 存储 输出 放大 缩小和调整来 自激光视盘机 录像机或摄像机的图像 知识点: . 下面,不是信息安全所包含的内容是。 要保障信息不会被非法阅读 要保障信息不会被非法泄露 要保障信息不会被非法修改 要保障信息不会被非法使用 本题分值: 用户得分: 用户解答: 要保障信息不会被非法使用 知识点: . 在 中,所包含的图表类型共有。 种 种 种 种 本题分值: 用户得分: 用户解答: 种 知识点: ----------------------- 计算机应用基础(第2版)-在线作业-A全文共6页,当前为第1页。 计算机应用基础(第2版)-在线作业-A全文共6页,当前为第2页。 计算机应用基础(第2版)-在线作业-A全文共6页,当前为第3页。 计算机应用基础(第2版)-在线作业-A全文共6页,当前为第4页。 计算机应用基础(第2版)-在线作业-A全文共6页,当前为第5页。 计算机应用基础(第2版)-

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值