long decode2(long x, long y, long z)
{
long result;
y = y - z;
x = x * y;
result = (y << 63) >> 63;
result = result ^ x;
return result;
}
用x1, y1来分别表示x和y的低位,用x2, y2来分别表示x和y的高位,用N表示2^64,因此有:
p = x * y
= (x2 * N + x1) * (y2 * N + y1)
= (x2 * y2 * N * N) + N * (x2 * y1 + x1 * y2) + (x1 * y1)
在这里面x2*y2*N*N
超过了128位,而且没有超出128位的部分每位都是0,因此可以直接去掉,
于是公式就变成了p=N*(x2*y1+x1*y2)+(x1*y1)
,值得注意的是,(x1*y1)
可能会超出64位,
设(x1*y1)
超出64位的部分为z2
,没有超出的部分为z1
,则公式可变为p=N*(x2*y1+x1*y2)+z1
;
所以,要把(x2*y1+x1*y2)
放到最终结果的高位(%rdi)
,(x1*y1)
或(z1)
放到低位8(%rdi)
。
[注]:%rdx和%rax共同代表一个128位数,是指可以用公式%rdx * 2^64 + %rax来表示这个数,
而并不是把%rax和%rdx的二进制串连起来表示。
store_prod:
movq %rdx, %rax # %rax = y1
cqto # 有符号扩展高位,%rdx和%rax分别表示高位和低位, %rdx = y2
movq %rsi, %rcx # %rcx = x1
sarq $63, %rcx # 将%rcx右移63位,跟%rdx的含义一样,要么是-1,要么是0。 %rcx = x2
imulq %rax, %rcx # %rcx = x2 * y1
imulq %rsi, %rdx # %rdx = y2 * x1
addq %rdx, %rcx # %rcx = x2 * y1 + y2 * x1
mulq %rsi # 无符号计算x1 * y1,并将128位结果的高位放到%rdx,低位放到%rax,所以%rdx = z2, %rax = z1
addq %rcx, %rdx # %rdx = z2 + x2 * y1 + y2 * x1
movq %rax, (%rdi) # 将%rax的值放到低位
movq %rdx, 8(%rdi) # 将%rdx的值放到高位
ret
A: %rdi-->x
%esi-->n
%rdx-->mask
%rax-->result
B: result = 0
mask = 1
C: mask != 0
D: mask <<= (n & 0xFF)
E: result |= (x & mask)
F:
long loop(long x, int n)
{
long result = 0;
long mask;
for (mask = 1; mask != 0; mask = mask << (n & 0xFF))
{
result |= (x & mask);
}
return result;
}
cread_alt(long *xp)
{
long rval = *xp;
long eval = 0;
long ntest = (xp = 0);
if (ntest) rval = eval;
return rval;
}
long switch3(long *p1, long *p2, mode_t action)
{
long result = 0;
switch(action){
case MODE_A: result = *p2;
action = *p1;
*p2 = action;
break;
case MODE_B: result = *p1 + *p2;
*p1 = result;
break;
case MODE_C: *p1 = 59;
result = *p2;
break;
case MODE_D: result = *p2;
*p1 = result;
case MODE_E: result = 27;
default: result = 12;
}
return result;
}
long switch_prob(long x, long n)
{
long result = x;
switch(n){
case 60:
case 62: result = 8 * x;
break;
case 63: result = result >> 3;
break;
case 64: result = (result << 4) - x;
x = result;
case 65: x = x * x;
default: result = x + 0x4b;
}
return result;
}
A: &A[i][j][k] = Xa + L * {T * (S * i + j) + k}
B:
由题可知:
S * T = 65
T = 13
S * T * R * 8 = 3640
故解得
R = 7, S = 5, T = 13
A: %rdx
B: %rax
C: 由题可知:
M * 8 = 120
解得 M = 15
NR(n) = 3 * n
NC(n) = 4 * n + 1
A:
相对于%rsp的偏移量 | 存储的值 |
---|---|
%rsp+24 | z |
%rsp+16 | &z |
%rsp+8 | y |
%rsp | x |
B:传递了%rsp + 64 ,是栈地址,不是结构体
C:通过%rsp+偏移量访问栈地址来访问结构参数s的元素
D:通过访问栈地址的参数来设置结果结构r的字段
E:
相对于%rsp的偏移量 | 存储的值 |
---|---|
%rsp+80 | z |
%rsp+72 | x |
%rsp+64 | y |
%rsp+56 | |
%rsp+48 | |
%rsp+40 | |
%rsp+32 | |
%rsp+24 | z |
%rsp+16 | &z |
%rsp+8 | y |
%rsp | x |
E:传递或者返回不能使用寄存器的结构体,都是通过栈来进行的。
由movq %rax, 184(%rdi)
可知: 176 < 4*A*B <= 184
解得44 < A*B <= 46
由movslq 8(%rsi), %rax
可知: 4 < B < 8
由addq 32(%rsi), %rax
可知:7 <= A <= 10
综上所述, 可解得A = 9, B = 5
mov 0x120(%rsi), %ecx
add (%rsi), &ecx
# 这两行说明first和a[CNT]占288个字节, %rcx = n
lea (%rdi, %rdi, 4), %rax # rax = 5 * i
lea (%rsi, %rax, 8), %rax # rax = 40 * i + bp,说明a占据的字节为40
mov 0x8(%rax), %rdx # ap->idx = %rax + 8说明了first占8个字节,a的第一个元素也占8个字节
movslq %ecx, %rcx # 将做了符号扩展的双字传递到四字,说明x的数组是long类型
mov %rcx, 0x10(%rax, %rdx, 8)
# 这行说明了ap->x[ap->idx]的地址计算公式是&ap + 16 + idx * 8
# +16是因为包含了first和idx,由于first占8个字节,所以idx占8个字节,为long类型
# 由于a占40个字节,减去idx占的8个字节,数组x的元素为(40 - 8) / 8 = 4
retq
A:CNT * 40 = 280,解得CNT = 7
B:
typedef a_struct{
long idx;
long x[4];
}
A:
e1.p | 0 |
---|---|
e1.y | 8 |
e2.x | 0 |
e2.next | 8 |
B:16
C:
1 proc:
2 movq 8(%rdi), %rax
3 movq (%rax), %rdx
4 movq (%rdx), %rdx
5 subq 8(%rax), %rdx
6 movq %rdx, (%rdi)
7 ret
首先我们看一下第5行,说明2-4行都是在传递被减数,由于3,4行是传递值的参数,则加2次*号,
故被减数的形式应该为 *(*(A).B)
,然后我们再看第2行,偏移量为8,结合被减数的形式,
需要指针,故应该是 *next
。然后再看第3行,偏移量为0,需要指针,则为 *p
。
故被减数应该为 *(*(up->e2.next).e1.p)
,继续看第5行,减去偏移量为8的数,由于在第
2行%rax变成了 *(up->e2.next)
,则减数为 *(up->e2.next).e1.y
最后只剩左边的未知,结合C代码和第6行,偏移量为0,传递的是地址的参数,则为 up->e2.x
综上所述:
void proc(union ele *up){
up->e2.x = *(*(up->e2.next).e1.p) - *(up->e2.next).e1.y
}
定义文档都找不到,写个屁啊
A:第5行计算8n+30,第6行的andq指令把该数向下舍入到最接近16倍数的值。
若n为奇数,则为8n+24;若n为偶数,则为8n+16
B:将s2舍入到最接近16倍数的值。(s2+15) & 0xffffff0
C:1.若要使e1的值最小,那么e2的值最大。要e2最大,则p最小,当p为16的倍数值加1时,e2=15,
然后使e1+e2的值最小,则n为偶数,8n+16-8n = 16,故e1为1最小时,n为偶数,s1%16=1。
2.若要使e1的值最大,那么e2的值最小。要e2最小,则p最大,当p为16的倍数值时,e2=0最小,
然后使e1+e2的值最大,故当n为奇数时,8n+24-8n=24,当e1最大为24时,n为奇数,s1%16=0。
D:s2的计算方式会保留s1的偏移量为最接近16的倍数值,p会以16的倍数对齐。
find_range:
vxorps %xmm1, %xmm1, %xmm1
vucomiss %xmm1, %xmm0
jp .L1
ja .L2
jb .L3
je .L4
.L2:
movl $2, %eax
jmp .Done
.L3:
movl $0, %eax
jmp .Done
.L4:
movl $1, %eax
jmp .Done
.L1:
movl $3, %eax
.Done
find_range:
vxorps %xmm1, %xmm1, %xmm1
movq $0, %r8
movq $1, %r9
movq $2, %r10
movq $3, %rax
vucomiss %xmm1, %xmm0
cmovl %r8, %rax
cmove %r9, %rax
cmova %r10, %rax
A:对于第n个参数,虚部传%xmm(2n-1),实部传%xmm(2n-2)
B: 虚部返回到%xmm1,实部返回到%xmm0