3.58
long decode2(long x,long y,long z)
{
int ret;
y=y-z;
x=x*y;
ret=y;
ret<<=63;
ret>>=63;
return ret^x;
}
算术左移63再右移63,得到的要么是全0,要么全1,取决于y的最低位
3.59
画了个简单的图便于理解,要不很难说明白,图中每个XY都是64位
现在分析汇编代码
movq rdx,rax //rdx为x
cqto //rdx被设置为rax的符号位扩展,也就是要么0要么-1(ffffffff),说白了现在rdx是x_h,rax是x_l
movq rsi,rcx //rsi为y_l
sarq $63,rcx //rcx为y_h,也是要么0要么-1
imulq rax,rcx //rcx=y_h*x_l
imulq rsi,rdx //rdx=x_h*y_l
addq rdx,rcx //将前面两个结果相加
mulq rsi //x_l*y_l,得到,rax为低64位结果,rdx为进位
addq rcx,rdx //进位rdx的值加上之前计算得到的两个高位结果,得到最终的高64位
movq rax,(rdi) //低64位结果赋给dest
movq rdx,8(rdi) //高64位结果赋给dest+8开始地址
ret
3.60
long loop(long x,int n)
{
long result=0;
long mask;
for(mask=1;maks!=0;mask=mask<<(n%256))
{
result|=(x+mask);
}
return result;
}
程序都写出来了,下面ABCDE是个问题就明了了,不再赘叙
3.61
搞清楚函数在干嘛就像简单呢,xp地址为空,就返回0,要么返回地址里面的值也就是*xp,但是xp有可能为空,那么用*xp就存在风险
所以,只能操作xp,不操作*xp,代码如下:
long cread_alt(long *xp)
{
long x = 0;
long *p = xp?xp:&x;
return *p;
}
3.62
MODE_A: result = *p2 ;*p2=*p1; break;
MODE_B: result = *p1 + *p2; *p1 = result; break;
MODE_C: *p1 = 59; result = *p2; break;
MODE_D: *p1 = *p2; result=27; break;
MODE_E: result = 27; break;
default: result = 12; break;
3.63
int switch_prob(int x, int n)
{
int result = x;
switch(n)
{
case 60:
case 62:
result *= 8; break;
case 63:
result >>= 3; break;
case 64:
result <<= 4;
result -= x;
x=result;
case 65:
x *= x;
case 61:
default:
result = x+0x4b; break;
}
return result;
}
3.64
A: &A[i}[j][k]=Xa+L(i*S*T+j*T+k)
B:可以很容易看出rdx=65i+13j+k,所以T=13;S=5,R=3640/(8*65)=7
3.65
A:rdx
B:rax
C:8M=120,M=15
3.66
NR(n)=3n
NC(n)=1+4n 不是1+4n再<<3这是乘以8是因为long每个8字节
3.67
A:调用process之前,栈结构:(调用进入时会多压入一个返回地址,要注意区别,rsp会减8)
B:结构体strA s
CDE,其实看图也看的出来,只是区别在于多压进去一个返回地址,所以图中的rsp都要少8,来访问
F:允许我略
3.68
这题关键在于理解数据对齐,这两个结构体都是8字节对齐
首先t偏移位8,知道1<=B<=8
然后u偏移32,知道32-8-4=20,头两个short(4字节)和int对齐8字节,剩下的16字节占了两排,7<=A<=10
最后184偏移是y,int两个两个占一排(一排8字节),最后一排可能满也可能缺一,所以可能有184/4=46,或45个int,那么结合前面的知道B=5,A=9;
3.69
注意还是8字节对齐
首先0x120=288,偏移位last
int first和浪费的4字节占一排,那么中间288-8=280字节位结构体数组a
然后bp+40*i+8为结构体的初始地址也就是ap的地址也是ap->idx的地址,这里的8是int first和4字节剩余的
这里我们知道了每个结构体是40字节,那么cnt=280/40=7
然后注意到movslq指令,猜测idx为int,x为long数组
最后0x10+rax+rdx*8这里乘8说明了是long型,变形一下,8+bp+40*i+8+rdx*8,这里rdx就是idx,8+bp+40*i什么意思上面已经解释了,再加8是假的int idx和剩余的4字节
那么long数组的个数是多少,40-8/8=4所以:
a_struct{int idx ; long x[4];}
3.70
A:0,8,0,8
B:16
void proc(union ele *up)
{
up->e2.x=*(up->e2.next)-up->e1.y;
}
3.71
不可能申请一个无穷大的空间给你一次读进来,所以只能一次读有限个字节分多次读取,然后一个个输出
void good_echo()
{
const int BufferSize = 0x8;
char buf[BufferSize];
int i;
while(fgets(buf, BufferSize, stdin)!=NULL)
{
for(i=0;buf[i];i++)
putchar(buf[i]);
if(i<BufferSize-1) break;
}
return;
}
3.72
A:n为奇数的时候取8n+24,为偶数取8n+16,向16取整数倍
B:向上取16的整数倍
C:n=0,s1=16时候,e1最大为16
n=1,s1=1时候,e1最小为1
D:都是16对齐
3.73
vxorps xmm0,xmm0,xmm0
movl $3,eax
vucomiss xmm0,xmm1 //cmp x:0
ja .L1 //大于0
je .L2 //等于0
jb .L3 //小于0
jp .L4
.L3:
subl $1,eax
.L2:
subl $1,eax
.L1:
subl $1,eax
.L4:
rep;ret
3.74
vxorps xmm0,xmm0,xmm0
movl $3,eax
movl $2,ebx
movl $1,ecx
movl $0,edx
vucomiss xmm0,xmm1 //cmp x:0
cmova ebx,eax //大于0
cmove ecx,eax //等于0
cmovb edx,eax //小于0
.L4:
rep;ret
3.75
A:单个参数时候xmm0是实部,xmm1是虚部,两个时候第一个一样,第二个的实部在xmm2,虚部在xmm3
B:xmm0返回实部,xmm1返回虚部.