Archlab 实验报告 
Part A 
1.  SUM.YS  计算链表的和 
  简要说明 
  将链表起始地址存入%edi 
  将求和结果存入%eax 
  用一个循环实现加和,当到达最末尾元素,用 andl 判断,再 jne 指令跳出 
  结果显示,%eax=0x00000cba. 
 
  每行程序对应 C 语言 
        .pos 0 
init: irmovl Stack,%esp 
            call Main 
            halt 
 
            .align 4 
list: 
ele1: 
            .long 0x00a 
            .long ele2 
ele2: 
            .long 0x0b0 
            .long ele3 
ele3: 
            .long 0xc00 
            .long 0 
 
Main: irmovl list,%edi 
            call sum_list 
            ret 
 
sum_list: 
            irmovl $0,%eax 
Loop: 
            mrmovl (%edi),%ecx 
            addl %ecx,%eax 
            mrmovl 4(%edi),%edi 
            andl %edi,%edi 
#Execution begins at address 0 
#set up stack pointer 
#execute main program 
#terminate program 
 
 
#list of 3 elements 
 
 
 
 
 
 
 
 
 
 
#get ls 
#sum_list(list_ptr ls) 
 
 
#int val=0 
 
#while 
#get ls->val 
#val+=ls_val 
#ls=ls->next 
#if ls==0 
            jne Loop 
            ret 
   
            .pos 0x200 
Stack: 
 
 
#stop when 0 
#return 
 
#stack  starts  here  and  grows  to  lower 
addresses 
2.  RSUM.YS  递归计算链表的和 
  简要说明 
  将链表起始地址存入%edi 
  将求和结果存入%eax 
  利用栈结构实现递归循环:每次把 val 值压入栈,并且触发 call 函数跳转,直到读
到末尾元素,把%eax 值赋 0;然后依次 ret 回到上一级位置,再将 pop 出来的 val
值和当前%eax 值相加并存入%eax,循环,一直到 ret 回主函数。 
  结果显示,%eax=0x00000cba 
 
  每行程序对应 C 语言 
        .pos 0 
init: irmovl Stack,%esp 
            call Main 
            halt 
 
            .align 4 
list: 
ele1: 
            .long 0x00a 
            .long ele2 
ele2: 
            .long 0x0b0 
            .long ele3 
ele3: 
            .long 0xc00 
            .long 0 
 
Main:   
            irmovl list,%edi 
            call rsum_list 
            ret 
 
rsum_list: 
loop: 
#Execution begins at address 0 
#set up stack pointer 
#execute main program 
#terminate program 
 
 
#list of 3 elements 
 
 
 
 
 
 
 
 
 
 
 
#get ls 
#rsum_list(list_ptr ls) 
 
 
 
#while 
            andl %edi,%edi 
            je zero 
            mrmovl (%edi),%edx 
            pushl %edx 
            mrmovl 4(%edi),%edi 
            call rsum_list 
            popl %edx         
            addl %edx,%eax 
            jmp end 
zero: 
            irmovl $0,%eax 
            ret 
end: 
            ret 
   
            .pos 0x100 
Stack: 
#if ls==0 
#jump to zero if ls==0 
#get ls->val 
#put ls->val on the stack 
#ls=ls->next 
#iteration 
#get current val 
# rest=val+rest 
 
 
#return 0 
#return to last address 
 
#return to last address 
 
#stack  starts  here  and  grows  to  lower 
addresses 
 
 
3.  COPY.YS  复制并计算异或 
  简要说明 
  将 src 首地址存入%edi,将 dest 首地址存入%esi 
  将异或结果存入%eax 
  用一个循环实现:将(%edi)存入(%esi),由于 Y86 指令中没有 mmmovl 指
令,因此需要借助%ecx 来实现,即先 mrmovl,再 rmmovl。然后将%ecx 和%eax
异或,即是 c 语言中的 result^=val。然后对%edi 和%esi 分别加 4,对%edx(len)
减 1,通过判断 len 是否为 0,跳出。 
  结果显示,%eax=0x00000cba 
 
  每行程序对应 C 语言 
.pos 0   
init:   
          irmovl Stack, %esp   
          call Main   
          halt   
 
.align 4   
src:   
        .long 0x00a   
        .long 0x0b0   
        .long 0xc00 # Destination block   
#Execution begins at address 0 
#set up stack pointer 
#execute main program 
#terminate program 
 
 
 
#source block 
 
 
 
dest:   
        .long 0x111   
        .long 0x222   
        .long 0x333   
 
Main:   
          irmovl src,%edi 
          irmovl dest,%esi 
          irmovl $0x3,%edx      #len 
          call copy 
          ret 
 
copy: 
          irmovl $0,%eax 
loop: 
          mrmovl (%edi),%ecx 
          rmmovl %ecx,(%esi) 
          xorl %ecx,%eax 
          irmovl $4,%ecx 
          addl %ecx,%edi       
          addl %ecx,%esi       
          irmovl $1,%ecx 
          subl %ecx,%edx       
          jne loop 
          ret 
 
      .pos 0x200   
Stack: 
 
#destination block 
 
 
 
 
 
#get src 
#get dest 
#let len=3 
#copy_block(int* src,int* dest,int len) 
 
 
 
#int result=0 
#while 
#int val=*src 
#*dest=val 
#result^=val 
 
#src+4 
#dest+4 
 
#len— 
#back to loop if len>0 
 
 
#stack  starts  here  and  grows  to  lower 
addresses 
 
 
 
 
 
Part B 
将立即数与寄存器相加 
对应于如下 Y86 代码: 
rrmovl %ebp,%esp 
popl %ebp 
1.  SEQ-FULL.HCL 
  指令说明 
IIADDL 
ILEAVE 
 
  指令分析 
 
 
  模拟器修改过程 
  在  instr_valid  添加  IIADDL  和  ILEAVE  让指令有效。 
  在  need_regids  添加  IIADDL。leave  指令不需要寄存器参数。 
  在  need_valC  添加  IIADDL。leave  指令不需要常数参数。 
 
srcA  中,iaddl  指令无需设置,leave  指令设为  REBP。 
srcB  中,iaddl  指令设为  rB, leave  指令设为  REBP。 
 
  dstE  中,iaddl  指令设为  rB, leave  指令设为  RESP。 
  dstM  中,iaddl  指令无需设置,leave  指令设为  REBP。 
  aluA  中,iaddl  指令设为  valC, leave  指令设为  4。 
  aluB  中,iaddl  指令和  leave  指令均设为  valB。 
  在  set_cc  中添加  IIADDL, leave  指令不影响标志位。 
  在  mem_read  中添加  ILEAVE, iaddl  指令无需访存。 
  mem_addr  中,leave  指令设为  valA, iaddl  指令无需设置。 
2.  PIPE-FULL.HCL 
  指令分析 
 
 
与顺序流水线类似,需要注意的是,iaddl 不存在加载/使用冒险,而 leave  存在加载/
使用冒险,故应该在  F  阶插入  stall, D  阶段插入  stall, E  阶段插入  bubble。 
条件 
加载使用冒险  暂停 
F 
D 
暂停 
E 
气泡 
M 
正常 
W 
正常 
 
  模拟器修改过程 
  在  INSTR_VALID  添加  IIADDL  和  ILEAVE  让指令有效。 
BOOL INSTR_VALID = F_ICODE IN   
 
    IOPL, IJXX, ICALL, IRET, IPUSHL, IPOPL, IIADDL, ILEAVE }; 
{ INOP, IHALT, IRRMOVL, IIRMOVL, IRMMOVL, IMRMOVL, 
 
  在  NEED_REGIDS  添加  IIADDL。LEAVE  指令不需要寄存器参数。 
BOOL NEED_REGIDS = 
 
 
F_ICODE IN { IRRMOVL, IOPL, IPUSHL, IPOPL,   
          IIRMOVL, IRMMOVL, IMRMOVL, IIADDL }; 
 
 
  在  NEED_VALC  添加  IIADDL。LEAVE  指令不需要常数参数。 
BOOL NEED_VALC = 
F_ICODE IN { IIRMOVL, IRMMOVL, IMRMOVL, IJXX, ICALL, IIADDL }; 
 
 
  D_SRCA  中,IADDL  指令无需设置,LEAVE  指令设为  REBP。 
INT D_SRCA = [ 
 
 
 
 
D_ICODE IN { IRRMOVL, IRMMOVL, IOPL, IPUSHL } : D_RA; 
D_ICODE IN { IPOPL, IRET } : RESP; 
D_ICODE IN { ILEAVE } : REBP; 
1 : RNONE; # DON'T NEED REGISTER 
]; 
 
  D_SRCB  中,IADDL  指令设为  RB,LEAVE  指令设为  REBP。 
INT D_SRCB = [ 
 
 
 
 
D_ICODE IN { IOPL, IRMMOVL, IMRMOVL, IIADDL } : D_RB; 
D_ICODE IN { IPUSHL, IPOPL, ICALL, IRET } : RESP; 
D_ICODE IN { ILEAVE } : REBP; 
1 : RNONE;    # DON'T NEED REGISTER 
]; 
 
  D_DSTE  中,IADDL  指令设为  RB,LEAVE  指令设为  RESP。 
INT D_DSTE = [ 
 
 
 
D_ICODE IN { IRRMOVL, IIRMOVL, IOPL, IIADDL } : D_RB; 
D_ICODE IN { IPUSHL, IPOPL, ICALL, IRET, ILEAVE } : RESP; 
1 : RNONE;    # DON'T WRITE ANY REGISTER 
]; 
 
  D_DSTM  中,IADDL  指令无需设置,LEAVE  指令设为  REBP。 
INT D_DSTM = [ 
 
 
 
D_ICODE IN { IMRMOVL, IPOPL } : D_RA; 
D_ICODE IN { ILEAVE } : REBP; 
1 : RNONE;    # DON'T WRITE ANY REGISTER 
]; 
 
  ALUA  中,IADDL  指令设为  VALC, LEAVE  指令设为  4。 
INT ALUA = [ 
 
 
 
 
 
E_ICODE IN { IRRMOVL, IOPL } : E_VALA; 
E_ICODE IN { IIRMOVL, IRMMOVL, IMRMOVL, IIADDL } : E_VALC; 
E_ICODE IN { ICALL, IPUSHL } : -4; 
E_ICODE IN { IRET, IPOPL, ILEAVE } : 4; 
# OTHER INSTRUCTIONS DON'T NEED ALU 
]; 
 
  ALUB  中,IADDL  指令和  LEAVE  指令均设为  VALB。 
INT ALUB = [ 
 
 
 
 
          IPUSHL, IRET, IPOPL, IIADDL, ILEAVE } : E_VALB; 
E_ICODE IN { IRMMOVL, IMRMOVL, IOPL, ICALL,   
 
E_ICODE IN { IRRMOVL, IIRMOVL } : 0; 
# OTHER INSTRUCTIONS DON'T NEED ALU 
]; 
 
  在  SET_CC  中添加  IIADDL,LEAVE  指令不影响标志位。 
BOOL SET_CC = E_ICODE IN { IOPL, IIADDL } && 
 
!M_STAT IN { SADR, SINS, SHLT } && !W_STAT IN { SADR, SINS, SHLT }; 
# STATE CHANGES ONLY DURING NORMAL OPERATION 
 
 
  MEM_ADDR  中,LEAVE  指令设为  VALA,IADDL  指令无需设置。 
INT MEM_ADDR = [ 
  M_ICODE IN { IRMMOVL, IPUSHL, ICALL, IMRMOVL } : M_VALE; 
  M_ICODE IN { IPOPL, IRET, ILEAVE } : M_VALA; 
 
# OTHER INSTRUCTIONS DON'T NEED ADDRESS 
]; 
 
  在  MEM_READ  中添加  ILEAVE,IADDL  指令无需访存。 
BOOL MEM_READ = M_ICODE IN { IMRMOVL, IPOPL, IRET, ILEAVE }; 
 
 
以上指令和SEQ-FULL.HCL中对应一致。 
  在  F_STALL  的  E_ICODE  条件中添加  ILEAVE,IADDL  指令不存在加载/使用冒险。 
BOOL F_STALL = 
 
 
 
 
IRET IN { D_ICODE, E_ICODE, M_ICODE }; 
# CONDITIONS FOR A LOAD/USE HAZARD 
E_ICODE IN { IMRMOVL, IPOPL, ILEAVE } && 
  E_DSTM IN { D_SRCA, D_SRCB } || 
# STALLING AT FETCH WHILE RET PASSES THROUGH PIPELINE 
 
 
  在  D_STALL  的  E_ICODE  条件中添加  ILEAVE,IADDL  指令不存在加载/使用冒险。 
BOOL D_STALL =   
 
 
  E_DSTM IN { D_SRCA, D_SRCB }; 
# CONDITIONS FOR A LOAD/USE HAZARD 
E_ICODE IN { IMRMOVL, IPOPL, ILEAVE } && 
 
 
  在  D_BULLLE  的  E_ICODE  条件中添加  ILEAVE,防止插入  D_BUBBLE。IADDL  指令不
存在加载/使用冒险。 
BOOL D_BUBBLE = 
 
 
 
 
 
&& 
 
# MISPREDICTED BRANCH 
(E_ICODE == IJXX && !E_CND) || 
# STALLING AT FETCH WHILE RET PASSES THROUGH PIPELINE 
# BUT NOT CONDITION FOR A LOAD/USE HAZARD 
!(E_ICODE IN { IMRMOVL, IPOPL, ILEAVE } && E_DSTM IN { D_SRCA, D_SRCB }) 
    IRET IN { D_ICODE, E_ICODE, M_ICODE }; 
  在  E_BUBBLE  的  E_ICODE  条件中添加  ILEAVE,IADDL  指令不存在加载/使用冒险。 
BOOL E_BUBBLE = 
 
 
 
 
  E_DSTM IN { D_SRCA, D_SRCB}; 
# MISPREDICTED BRANCH 
(E_ICODE == IJXX && !E_CND) || 
# CONDITIONS FOR A LOAD/USE HAZARD 
E_ICODE IN { IMRMOVL, IPOPL, ILEAVE } && 
 
 
 
 
Part C