A: voidcond(long a, long *p) { if (p == 0) goto done; if (*p >= a) { goto done; } *p = a; done; } B:汇编一次只能执行一条指令, 两条比较指令包含两个分支
练习题 3.17
答:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
longgotodiff_se(long x, long y) { long result; if (x < y) { goto x_lt_y } ge_cnt++; result = x - y; return result; x_lt_y: lt_cnt++; result = y - x; return resultl;
}
练习题 3.18
com s1, s2 // s2 - s1
1 2 3 4 5 6 7 8 9 10 11
longtest(long x, long y, long z) { long val = x + y + z; if (x < -3) { if (y < z) val = x * y; else val = y * z; } elseif (x > 2) val = x * z; return val; }
练习题 3.19
1 2 3
//不懂 A: T = 2 * (31 - 16) = 30 B:16 + 30 = 47
条件传送指令
练习题 3.20
1 2 3 4 5 6 7 8 9 10
A: x / 8, 如果x是负数, 必须先加上偏置数7 B: //long arith(long x): //x in %rdi arith: leaq 7(%rdi), %rax // temp = 7 + x testq %rdi, %rdi // x & x cmovns %rdi, %rax // 如果 %rdi > 0, %rax = %rdi sarq $3, %rax // %rax >> 3; ret
练习题 3.21
1 2 3 4 5 6 7 8 9 10 11 12 13
longtest(long x, long y, long z) { long val = 8 * x; if (y > 0) { if (x < y) val = y - x; else val = x + y;
A. x : %rax y : %rcx n : %rdx B. 答;编译器认为指针p总是指向x,因此表达式(*p) ++就能实现x+1。通过第7行的leap指令, 把这个加一和加y组合起来。 C. // long dw_loop(long x) // x initially in %rdi dw_loop: movq %rdi, %rax //%rax = x movq %rdi, %rcx //%rcx = x imulq %rdi, %rcx //y = x * x leaq (%rdi, %rdi) //n = x + x .L2: //loop leaq 1(%rcx, %rax), %rax //x += y + 1; subq $1, %rdx //n-=1 testq %rdx, %rdx //Test n jg .L2 //if n > 0, goto loop; rep;ret //return %rax;
练习题 3.25
1 2 3 4 5 6 7 8
longloop_while2(long a, long b) { long result = b; while (b > 0) { result = result * a; b = b - a; } return result; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
A; 方法:跳转到中间 (jump to middle) B; longfun_a(unsignedlong x) { long val = 0; while (x) { val ^= x; x >>= 1; } return val & 0x1; } C; 不懂 参考答案: 这个代码计算参数x的奇偶性。 也就是, 如果x中有奇数个1,就返回1, 否则返回0;
longfact_for(long n) { long i; long result = 1; for (i = 2; i <= n; i ++) result *= i; return result; } A; 改while; longfact_for(long n) { long i = 2; long result = 1; while (i <= n) result *= i++; return result; } guarded_do 变换; longfact_for_gd_goto(long n) { long i = 2; long result = 1; if (n <= 1) goto done; loop: result *= i; i ++; if (i <= n) goto loop; done: return result; }
练习题 3.28
1 2 3 4 5 6 7 8 9 10 11 12 13
A; longfun_b(unsignedlong x) { long val = 0; long i; for (i = 64; i != 0; i --) { val = (val << 1) | (0x1 & x); x >>= 1; } return val; } B; 这段代码是从guarded_do变换生成的。编译器发现i初始化成64,所以一定满足不等于0,因此初始测试是没必要的。 C; 翻转x的二进制位
练习题 3.29
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
A: for翻译到while循环; long sum = 0; long i = 0; while (i < 10) { if(i & 1) continue; sum += i; i ++; } 当continue时, 会跳过iupdate部分代码, 导致死循环; long sum = 0; long i = 0; while ( i < 10 ) { if (1 & 1) goto update; sum += 1; update: i ++; }
练习题 3.30
1 2
A; -1, 0, 1, 2, 3, 5, 7; B; 2, 3;
练习题 3.31 (我不李姐)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
voidswitcher(long a, long b, long c, long *dest) { long val; swtich(a) { case5: c = b ^ 15; case0: val = c + 112; break; case2: case7: val = (b + c) << 2; break; case4: val = a; default: val = b; } *dest = val; }