Lab4 Architecture Lab

本文详述了完成CSAPP的Arch Lab的过程,包括编写Y86-64汇编代码,设计并实现新指令ADDI,以及通过指令重排和循环展开优化代码,以提高流水线性能。实验室涵盖了从设置栈指针到优化循环的多个步骤,并通过测试确保了结果的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Lab4 Architecture Lab

写在前言:这个实验的来源是CSAPP官网:CSAPP Labs ,如果感兴趣的话,可以点击这个链接🔗去下载,Arch Lab这个实验锻炼我们编写汇编代码的能力,以及设计一个新指令 iaddq,分别在顺序 SEQ 和 PIPE 下实现。

实验说明

从官网下载该实验的压缩包,然后执行以下操作:

$ tar -xvf archlab-handout.tar
$ cd sim
$ make clean; make

make 的时候可能提示缺少了某些库,比如 tktcl,安装对应的开发环境即可,如在 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_listY86-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_listY86-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_blockY86-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-64X86-64 的一些区别即可,就是 Y86-64 没有与立即数直接操作的指令,需要使用 irmovq $c, %reg,先将常数 c 存入 reg 中备用。

测试,使用 yasyis 测试相应的代码:

$ ./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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值