Lab4 Architecture Lab
写在前言:这个实验的来源是CSAPP官网:CSAPP Labs ,如果感兴趣的话,可以点击这个链接🔗去下载,Arch Lab这个实验锻炼我们编写汇编代码的能力,以及设计一个新指令 iaddq
,分别在顺序 SEQ 和 PIPE 下实现。
实验说明
从官网下载该实验的压缩包,然后执行以下操作:
$ tar -xvf archlab-handout.tar
$ cd sim
$ make clean; make
make
的时候可能提示缺少了某些库,比如 tk
、tcl
,安装对应的开发环境即可,如在 Centos
上,使用以下指令:
$ sudo yum install tk-devel tcl-devel
这个实验分为三个部分,编写Y86-64汇编代码,补充 IADDQ
指令的 SEQ
每一阶段的 HCL
描述。
Part A
这一部分的工作目录位于 sim/misc
,任务是编写并且模拟三个Y86-64
汇编程序,这三个程序的C语言表示在 examples.c
文件下可以找到,以下是他们的C语言版本:
/* linked list element */
typedef struct ELE {
long val;
struct ELE *next;
} *list_ptr;
/* sum_list - Sum the elements of a linked list */
long sum_list(list_ptr ls)
{
long val = 0;
while (ls) {
val += ls->val;
ls = ls->next;
}
return val;
}
/* rsum_list - Recursive version of sum_list */
long rsum_list(list_ptr ls)
{
if (!ls)
return 0;
else {
long val = ls->val;
long rest = rsum_list(ls->next);
return val + rest;
}
}
/* copy_block - Copy src to dest and return xor checksum of src */
long copy_block(long *src, long *dest, long len)
{
long result = 0;
while (len > 0) {
long val = *src++;
*dest++ = val;
result ^= val;
len--;
}
return result;
}
sum_list
函数使用迭代的方式计算链表之和,rsum_list
函数使用递归的方式计算链表之和,copy_block
使用迭代的方式将 src
复制到 dest
。
根据CSAPP书上Y86-64程序示例,可以仿照写出上面三个程序的 Y86-64 版本,需要注意的是必须建立栈,初始化栈指针,以及栈不能覆盖代码和数据。
以下为 sum_list
的 Y86-64
程序:
# Part A: sum.ys: Iteratively sum linked list elements
.pos 0
irmovq stack, %rsp # Set up stack pointer
call main # Execute main program
halt # Terminate program
# linked list
.align 8
ls:
ele1:
.quad 0x00a
.quad ele2
ele2:
.quad 0x0b0
.quad ele3
ele3:
.quad 0xc00
.quad 0
main:
irmovq ls, %rdi
call sum_list # sum_list(ls)
ret
# long sum_list(list_ptr ls)
# ls in %rdi
sum_list:
xorq %rax, %rax # val = 0
jmp test # Goto test
loop:
mrmovq (%rdi), %r8 # Get ls->val
addq %r8, %rax # val += ls->val
mrmovq 8(%rdi), %rdi # ls = ls->val
test:
andq %rdi, %rdi # Set conditional codes
jne loop # Stop when ls is null
ret
# Stack here
.pos 0x200
stack:
以下为 rsum_list
的 Y86-64
版本:
# rsum.ys: Recursively sum liked list elements
.pos 0
irmovq stack, %rsp # Set up stack pointer
call main # Execute main program
halt # Terminate program
# linked list
ls:
ele1:
.quad 0x00a
.quad ele2
ele2:
.quad 0x0b0
.quad ele3:
ele3:
.quad 0xc00
.quad 0
main:
irmovq ls, %rdi
call rsum_list
ret
# long rsum_list(list_ptr ls)
# ls in %rdi
rsum_list:
pushq %rbx # Save %rbx in stack
rrmovq %rdi, %rbx # Copy %rdi to %rbx
xorq %rax, %rax # Clear %rax
andq %rdi, %rdi # Test ls
je end # Jump to end if ls is nullptr
mrmovq 8(%rdi), %rdi # Get ls->next
call rsum_list
mrmovq (%rbx), %r8 # Get ls->val
addq %r8, %rax # Compute val + rsum_list(ls->next)
end:
popq %rbx # Restore %rbx
ret
# Stack here
.pos 0x200
stack:
以下为 copy_block
的 Y86-64
版本:
# copy.ys: Copy a source block to a destination block
.pos 0
irmovq stack, %rsp # Set up stack pointer
call main # Execute main program
halt # Terminate program
.align 8
# Source block
src:
.quad 0x00a
.quad 0x0b0
.quad 0xc00
# Destination block
dest:
.quad 0x111
.quad 0x222
.quad 0x333
main:
irmovq src, %rdi
irmovq dest, %rsi
irmovq $3, %rdx
call copy_block # copy_block(src, dest, 3)
ret
# long copy_block(long *src, long *dest, long len)
# src in %rdi, dest in %rsi, len in %rdx
copy_block:
irmovq $8, %r8 # Constant 8
irmovq $1, %r9 # Constant 1
xorq %rax, %rax # result = 0
andq %rdx, %rdx # Set conditional codes
jmp test # Goto test
loop:
mrmovq (%rdi), %r10 # val = *src
addq %r8, %rdi # src++
rmmovq %r10, (%rsi) # *dest = val
addq %r8, %rsi # dest++
xorq %r10, %rax # result ^= val
subq %r9, %rdx # len--
test:
jg loop # Stop when len <= 0
ret
# Stack here
.pos 0x200
stack:
这一部分实际上没什么难度,只需要注意 Y86-64
和 X86-64
的一些区别即可,就是 Y86-64
没有与立即数直接操作的指令,需要使用 irmovq $c, %reg
,先将常数 c 存入 reg 中备用。
测试,使用 yas
和 yis
测试相应的代码:
$ ./yas sum.ys
$ ./yis sum.yo
Stopped in 26 steps at PC = 0x13. Status 'HLT', CC Z=1 S=0 O=0
Changes to registers:
%rax: 0x0000000000000000 0x0000000000000cba
%rsp: 0x0000000000000000 0x0000000000000200
%r8: 0x0000000000000000 0x0000000000000c00
Changes to memory:
0x01f0: 0x0000000000000000 0x000000000000005b
0x01f8: 0x0000000000000000 0x0000000000000013
注意程序的结果为:0xcba
,因此结果正确。
$ ./yas rsum.ys
$ ./yis rsum.yo
Stopped in 46 steps at PC = 0x13. Stat