title: archlab实验报告:y86命令的使用
date: 2021-05-10 22:00:00
tags:
- csapp report
- assemble command
comments: true
categories: - assemble
- y86
下载文件之后:
脑瓜子嗡嗡的,writeup
看不懂,只能先去看看已有的实验报告,然后先做个总结——
先把里面的sim.tar
解压了,然后进入目录之后make clean
,make
会在里面的所有文件该生成的文件生成了。
part A
这个部分的文件全在misc
文件夹。
意思大概是用y86
指令集实现example.c
文件里面的三个函数,那也太棒了呀,我最擅长手写汇编了,汇编它虽然码起来效率低,但是能直接对底层进行操作,想想都激动awa
要用到的指令:
./yis xxx.ys
./yas xxx.yo
第一条可以理解为汇编,第二条可以理解为链接且运行。
sum_list
/* 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;
}
就是一个很朴素的链表求和,用循环实现。书上有例子的,那就直接把代码写下来吧,注释上写的挺清晰了。
.pos 0#初始化
irmovq stack,%rsp#初始化一个栈帧
call main#执行主函数
halt#结束
.align 8#对齐
ele1:#链表头
.quad 0x00a#链表值1
.quad ele2#连接下一个表
ele2:
.quad 0x0b0#链表值2
.quad ele3#连接下一个表
ele3:
.quad 0xc00#链表值3
.quad 0#NULL
#This is main function
main:
irmovq ele1,%rdi#传参
call sum_list#调用函数
ret
sum_list:
irmovq $0,%r14
irmovq $0,%rax
L2:
subq %r14,%rdi
je L4#到了NULL跳转L4返回
mrmovq (%rdi),%r13#取值
addq %r13,%rax#加给ax寄存器
mrmovq 8(%rdi),%rdi#下一个地址给%rdi
jmp L2
L4:
ret
#stack starts here and grows to lower addresses
.pos 0x200
stack:
运行结果:
while
实现方式有多种,下面几种都可以,
L2:
//循环块
jnz L2
ret
L2:
jz L4
//循环块
jmp L2
L4:
ret
……接下来读者自己想象吧
rsum_list
这一次也是要一个链表求和,只是函数需要递归。
那么这次我们稍微改一下,把跳转到L2
改成重新call
一次就好了呗,这里不过多解释了。
.pos 0#初始化
irmovq stack,%rsp#初始化一个栈帧
call main#执行主函数
halt#结束
.align 8#对齐
ele1:#链表头
.quad 0x00a#链表值1
.quad ele2#连接下一个表
ele2:
.quad 0x0b0#链表值2
.quad ele3#连接下一个表
ele3:
.quad 0xc00#链表值3
.quad 0#NULL
#This is main function
main:
irmovq ele1,%rdi#传参
irmovq $0,%rax
call sum_list#调用函数
ret
sum_list:
irmovq $0,%r13
subq %r13,%rdi
je L4#到了NULL跳转L4返回
mrmovq (%rdi),%r13#取值
addq %r13,%rax#加给ax寄存器
mrmovq 8(%rdi),%rdi#下一个地址给%rdi
call sum_list#递归调用
L4:
ret
#stack starts here and grows to lower addresses
.pos 0x400
stack:
但是我这个做法在编译应该是不存在的,真正递归的话每次调用都应该用rax
保存返回值的,但是我没有,因为我们是直接写汇编指令的,所以不必那么麻烦(其实我也不知道符不符合要求,反正能过的程序)
贴一个运行结果吧:
(PS:就感觉这个lab
我写的挺水的,分析的东西比较少,可能还是我菜吧qwq
)
copy_block
/* 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;
}
这第三个函数跟链表关系不大了,给出源地址和目的地址,源地址保存了一些值,要将源地址开始的len
长度的数据拷贝到目的地址,并且把拷贝的值异或起来并且返回。首先len
为循环次数没得跑,那么就先可以构建出它循环的基本框架
L2:
//……
irmovq $1,%r9
subq %r9,%rdx
jne L2
ret
然后略去的内容无非就是赋值,异或,然后就完了…最后注意一下在main函数把三个参数传好,64位的程序前六个参数依次给rdi,rsi,rdx,rcx,r8,r9
寄存器,那么main函数就应该是
main:
irmovq src,%rdi
irmovq dest,%rsi
irmovq xxx,%rdx//这里的xxx自己写,写了多长的数据给多少数值
call copy
ret
那么自己再随便取一下dest
和src
汇编运行后就可以看到结果。
完整代码:
.pos 0#初始化
irmovq stack,%rsp#初始化一个栈帧
call main#执行主函数
halt#结束
.align 8#对齐
src:
.quad 0x00a
.quad 0x0b0
.quad 0xc00
dest:
.quad 0x111
.quad 0x222
.quad 0x333
#This is main function
main:
irmovq src,%rdi
irmovq dest,%rsi
irmovq $3,%rdx#argument len
call copy
ret
cop