计算机系统概论 作业2


  1. 使用不超过 $3$ 条 $x86$ 指令实现如下函数: 其中 $x, y, z, w$ 分别存储于 %rdi, %rsi, %rdx, %rcx. 返回值存储于 %rax.

    long add(long x, long y, long z, long w) { 
    	return 32 * x + 8 * y + 4 * z + w; 
    }
    add:
    	leaq (%rsi,%rdi,4), %rsi
    	leaq (%rcx,%rsi,8), %rcx
    	leaq (%rcx,%rdx,4), %rcx
    	ret
  2. $X86-64$ 体系结构中的条件跳转指令 $jg$ 是用于带符号数比较还是无符号数比较的? 其产生跳转的成立条件是 ~(SF^OF) & ~ZF​ 为真, 请解释为何是这一条件.

    答:

    条件跳转指令 $jg$ 是用于带符号数比较的.

    考虑被比较的两个数 $a, b$, 当 $\text{~(SF^OF)&~ZF}$ 为真时:

    有 $\text{~(SF^OF)}$ 为真, 则 $\text{SF^OF}$为假, 从而 $\text{SF = OF = 1}$ 或 $\text{SF = OF = 0}$,

    即此时 $a\le b$.

    同时有 $\text{~ZF}$ 为真, 则 $\text{ZF}$为假, 从而 $\text{ZF = 0}$,

    即此时 $a\ne b$.

    故 $a < b$ 成立.

  3. 有如下对应的 $C$ 代码与汇编代码 $(x86-64)$, 请对照着填上代码中缺失的部分(数字请用十进制表示).

    call_swap: 
    	subq 	$24, %rsp 
    	movl 	__①__, 12(%rsp) 
    	movl 	$91125, 8(%rsp) 
    	leaq 	8(%rsp), %rsi 
    	leaq 	12(%rsp), __④__ 
    	movl 	$0, %eax 
    	call 	swap
    void swap(int *a, int *b); 
    void call_swap() 
    { 
    	int zip1 = 15213; 
    	int zip2 = __②__; 
    	__③__;
    }

    ① : $15213

    ② : 91125

    ③ : swap(&zip1, &zip2)

    ④ : %rdi

  4. 一个 $C$ 语言的 $for$ 循环代码 (部分) 及其 $64$ 位 $Linux$ 汇编如下所示, 请对照汇编填充 $C$ 语言里的缺失部分.

    int looper(int n, int *a) { 
    	int i; 
    	int x = 0; 
        for (i = 0; i < n; i++) { 
            if (x < a[i] - 1) 
                x = 2 * a[i]; 
            else 
                x += 1; 
        } 
        return x; 
    }
    looper: 
        movl 	$0, %eax 
        movl 	$0, %edx 
        jmp 	.L2 
    .L4: 
        movslq 	%edx, %rcx 
        movl 	(%rsi,%rcx,4), %ecx 
        addl 	$1, %eax 
        cmpl 	%eax, %ecx 
        jle 	.L3 
        leal 	(%rcx,%rcx), %eax 
    .L3: 
        addl 	$1, %edx 
    .L2: 
        cmpl 	%edi, %edx 
        jl 	    .L4 
        ret
  5. 对于如下代码

    long v2permute(long *array, long x, long y, long z) { 
        long t1 = 8253 * x; 
        long t2 = array[t1 + 2 * y]; 
        long t3 = array[t2 * 16 + z]; 
        long t4 = t1 + t2 + t3; 
        long t5 = array[0] * t1; 
        long ret = t3 & t5; 
        return ret; 
    }

    对应如下汇编指令, 请写出每条指令之后目标寄存器存储的变量/临时变量值.

    v2permute: 
        movq 	%rdx, %r8
        movq 	%rcx, %rdx 
        imulq 	$8253, %rsi, %rax 
        leaq 	(%rax,%r8,2), %rcx 
        movq 	(%rdi,%rcx,8), %rcx 
        salq 	$4, %rcx 
        addq 	%rdx, %rcx 
        imulq 	(%rdi), %rax 
        andq 	(%rdi,%rcx,8), %rax

    ① : y

    ② : z

    ③ : 8253 * x

    ④ : 8253 x + 2 y

    ⑤ : array[8253 x + 2 y]

    ⑥ : 16 array[8253 x + 2 * y]

    ⑦ : 16 array[8253 x + 2 * y] + z

    ⑧ : array[0] 8253 x

    ⑨ : array[16 array[8253 x + 2 y] + z] & (array[0] 8253 * x)

  6. 请对照下面的 $C$ 语言代码与相应汇编 $(Linux X86-64)$, 给出 $M$、$N$ 的值.

    copy_element: 
        movslq  %edi, %rdi 
        movslq  %esi, %rsi 
        leaq    (%rsi,%rsi,2), %rax 
        leaq    (%rsi,%rax,4), %rax 
        addq    %rdi, %rax 
        movl    mat2(,%rax,4), %edx 
        leaq    0(,%rdi,8), %rax 
        subq    %rdi, %rax 
        addq    %rax, %rsi 
        movl    %edx, mat1(,%rsi,4) 
        ret
    #define M 13
    #define N 7
    int mat1[M][N]; 
    int mat2[N][M]; 
    int copy_element(int i, int j) 
    { 
    	mat1[i][j] = mat2[j][i]; 
    }

文章作者: Chengsx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Chengsx !
  目录