CASPP 第三章课后习题解答

3.58

一个函数的原型为

1
long decode2(long x, long y, long z);

GCC产生的汇编代码为

1
2
3
4
5
6
7
decode2:
subq %rdx, %rsi
imulq %rsi, %rdi
movq %rsi, %rax
salq $63, %rax
sarq $63, %rax
xorq %rdi, %rax

参数x、y、z通过寄存器%rdi、%rsi和%rdx传递。代码将返回值存放在寄存器%rax中。写出等价于上述汇编代码的C代码。

1
2
3
4
5
6
7
8
int decode(int x, int y, int z)
{
    y = y - z;
    x = x * y;
    int res = y << 63;
    res >>= 63;
    return res ^ x;
}

这里可以使用将汇编代码进行编译连接,产生方法嵌入到可执行文件中。

1
2
gcc -c -m64 decode2.s -o decode2.o
gcc -m64 main.c decode.c decode2.o -o main

3.60

请解释下面汇编代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
loop:
  movl %esi, %ecx
  movl $1, %edx
  movl $0, %eax
  jmp .L2
.L3:
  movq %rdi, %r8
  andq %rdx, %r8
  orq %r8, %rax
  salq %cl, %rdx
.L2:
  testq %rdx, %rdx
  jne .L3
  rep
  ret

将其转换为C语言(涉及的知识有)

  • 寄存器的类型 p120
  • test用法 p136
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
long loop2(long x, int n)
{
    long res = 0;
    long mask;
    for (mask = 1; mask !=0 ; mask=mask<<n)
    {
        res |= x & mask;
    }
    return res;   
}

3.61

查看代码

1
2
3
4
5
6
7
8
// 试图读取空地址的值
long cread(long *xp) {
  return (xp ? *xp : 0);
}

long cread_alt(long *xp) {
  return (!xp ? 0 : *xp);
}

使用条件传送指令(CSAPP 147页)

1
2
3
4
cread_alt:
  movl $0, %eax
  testq %rdi, %rdi
  cmovne (%rdi), %rax

3.62

3.63

3.64