第3章 程序的机器级表示课后作业
3.58
一个函数的原型为:
long decode2(long x, long y, long z);
GCC 产生如下汇编代码:
# long decode2(long x, long y, long z)
# x in %rdi, y in %rsi, z in %rdx
decode2:
subq %rdx, %rsi
imulq %rsi, %rdi
movq %rsi, %rax
salq $63, %rax
sarq $63, %rax
xorq %rdi, %rax
ret
写出等价于上述汇编代码的 decode2 的 C 代码。
long decode2(long x, long y, long z) {
y = y - z;
x = x * y;
return x ^ ((y << 63) >> 63);
}
3.59下面的代码计算两个 64位有符号值 x 和 y 的 128 位乘积,并将结果存储再内存中:
typedef __int128 int128_t;
void store_prod(int128_t *dest, int64_t x, int 64_t y) {
*dest = x * (int128_t) y;
}
GCC 产出下面的汇编代码来实现计算:
store_prod:
movq %rdx, %rax
cqto
movq %rsi, %rcx
sarq $63, %rcx
imulq %rax, %rcx
imulq %rsi, %rdx
addq %rdx, %rcx
mulq %rsi
addq %rcx, %rdx
movq %rax, (%rdi)
movq %rdx, 8(%rdi)
ret
为了满足在 64 位机器上实现 128 位运算所需的多精度计算,这段代码用了三个乘法。描述用来计算乘积的算法,对汇编代码加注释,说明它是如何实现你的算法的。提示:在把参数 x 和 y 扩展到 128 位时,它们可以重写为 x = 2 64 ⋅ x h + x l x=2^{64}\cdot x_h+x_l x=264⋅xh+xl 和 y = 2 64 ⋅ y h + y l y=2^{64}\cdot y_h+y_l y=264⋅yh+yl,这里 x h x_h xh , x l x_l xl 和 y h y_h yh, y l y_l yl 都是 64 位值。类似地,128 位的乘积可以写成 p = 2 64 ⋅ p h + p l p=2^{64}\cdot p_h+p_l p=264⋅ph+pl,这里 p h p_h ph 和 p l p_l pl 是 64位值。请解释这段代码是如何用 x h x_h xh , x l x_l xl , y h y_h yh, y l y_l yl 来计算 p h p_h ph 和 p l p_l pl 的。
计算公式如下:
x ⋅ y = [ ( 2 64 ⋅ x h + x l ) ⋅ ( 2 64 ⋅ y h + y l ) ] m o d 2 128 = 2 64 ⋅ ( x h y l + y h x l ) + x l y l = 2 64 ⋅ ( x h y l + y h x l + z h ) + z l x\cdot y=[(2^{64}\cdot x_h+x_l)\cdot(2^{64}\cdot y_h+y_l)]\mod{2^{128}}=2^{64}\cdot(x_hy_l+y_hx_l)+x_ly_l=2^{64}\cdot(x_hy_l+y_hx_l+z_h)+z_l x⋅y=[(264⋅xh+xl)⋅(264⋅yh+yl)]mod2128=264⋅(xhyl+