CompOrg Spring 2005 Lab


To access your account you need to ask Dave to help you set up your password (all passwords were removed due to the security problems on monte). Once your password is established you need to login to d29-170.dyn.cs.rpi.edu.

Lab #10 - Y86 Assembly Programming and Y86 Simulator and HCL

4/13/2005


A Y86 Instruction Reference is available here
Y86 Simulator manual (pdf)


Y86 Assembly Programming

This part of the lab involves writing programs (C functions) in Y86 assembly language. Y86 is a small subset of the IA32 instruction set, there is a list of Y86 instructions (and many code examples) in the text, lecture notes (Y86.pdf), and this reference: y86ref.html.

The C subroutine shown below sums the values in an array of integers:

int Sum(int *Start, int Count) {
  int tot=0;
  while (Count>0) {
     tot += *Start;
     Start++;
     Count--;   // Creates a Gui control panel for the ray tracer
  }
  return(tot);
}

asum.ys is complete Y86 assembly program that includes this subroutine and a main function that calls the function files to work on this part of the labSum to test it out. Your first task is to assemble this program (using yas - the Y86 assembler) and test it (using yis - the Y86 simulator).

> mkdir lab10
> cd lab10
> cp ~hollingd/public/lab10/asum.ys asum.ys
> yas asum.ys
> yis asum.yo

After running the simulator (yis) you will see output of all the registers and memory locations that were changed by the asum program. Based on the code (in asum.ys) and this output, you need to determine what the return value of Sum()is (the sum of the array passed to Sum). Just like with IA32 subroutines, Y86 subroutines put the return value in %eax.

Now change the asum.ys program so that the Sum subroutine is passed an array of 10 elements with the values 1,2,3...10. Reassemble and run the simulator and determine what the sum of the integers from 1 to 10 is.

Here is the entire asum.ys Y86 assembly program:

asum.ys
# Execution begins at address 0
	.pos 0                  # sets starting address
init:
	irmovl Stack, %esp  	# Set up Stack pointer
	irmovl Stack, %ebp  	# Set up base pointer
	jmp Main		# Execute main program

# Array of 4 elements is declared here
	.align 4
array:
	.long 0xd
	.long 0xc0
	.long 0xb00
	.long 0xa000

Main:
	irmovl $4,%eax			# length of array
	pushl %eax			# Push  length of array
	irmovl array,%edx		# put address of array in edx
	pushl %edx      		# Push address of array
	call Sum			# Sum(array, 4)
	halt

# C code for sum subroutine:
#
# int Sum(int *Start, int Count) {
#  int tot=0;
#  while (Count>0) {
#     sum += *Start
#	  Start++;
#     Count--;
#  }
#  return(tot);
# }

Sum:
	pushl %ebp		# stack frame setup
	rrmovl %esp,%ebp	#
	mrmovl 8(%ebp),%ecx	# ecx = Start
	mrmovl 12(%ebp),%edx	# edx = Count
	irmovl $0, %eax		# tot = 0 (eax)
	andl   %edx,%edx	# 
	je     End		# jump if edx == 0
Loop:
	mrmovl (%ecx),%esi      # get *Start in esi
	addl %esi,%eax          # add to tot
	irmovl $4,%ebx          # 
	addl %ebx,%ecx          # Start++
	irmovl $-1,%ebx	        # 
	addl %ebx,%edx          # Count--
	jne    Loop             # Stop when edx is 0
End:	
	popl %ebp		# restore stack frame
	ret		

	.pos 0x100
Stack:	# The stack goes here (at address 0x100)

Multiply Subroutine

You should write a Y86 assembly function named Mult that will multiply two unsigned integers. Recall that there is no multiply instruction in the Y86 instruction set, so you need to use repeated addition to accomplish this. The C prototype for the function looks like this:

unsigned int Mult(unsigned int a, unsigned int b);

Below is a Y86 main that will test your code (you need to add the code for the Mult subroutine):

mult.ys
# Execution begins at address 0
	.pos 0
init:
	irmovl Stack, %esp  	# Set up Stack pointer
	irmovl Stack, %ebp  	# Set up base pointer

Main:
	irmovl $5,%eax		# second number passed to Mult
	pushl %eax		# Push  number

	irmovl $12,%eax		# first number passed to Mult
	pushl %eax		# Push  number

	call Mult		# Call multiply subroutine
				# answer is in eax
	halt

# Your code for Mult goes here --------------

# -------------------------------------------
	.pos 0x400
Stack:	# The stack starts at 0x400

Notes:




Building a new Y86 simulator

The code needed for this part of the lab is in ~hollingd/public/lab10/mksim, there is also a tar file available: lab10.tar. You will need a complete copy of these files to work on this part of the lab:

> cp -r ~hollingd/public/lab10/mksim .
> cd mksim

There are a number of files that are needed to build a Y86 simulator given an file that contains a description of the control system specified in HCL. There are currently two HCL files:

seq-std.hcl: contains HCL for standard Y86 sequential implementation.
seq-inc.hcl: includes support for increment "incl" instruction.

There is a Makefile already constructed for your use with this lab. You can build the 'standard' simulator by typing "make ssim" when in the directory holding the files (your copy of the directory). This simulator can only handle the standard Y86 instructions.

The Makefile will also build a simulator that includes an incl instruction, this simulator is based on the hcl file seq-inc.hcl. The README file contains a description of what was added to the standard hcl file to implement the new instruction.

NOTE: There is also a colorized version of this file (with changes shown in red) available : seq-inc.hcl.html

You should build and test both simulators. Recall that to assemble a Y86 program you use the "yas" program, you need to use the version of "yas" that is included with the lab10 files. The asum.ys program from last lab can be tested with "ssim", and there is also a new version of this program (named asum-inc.ys) that uses the "incl" instruction - you can test this with the "sinc" simulator:

> ./yas asum.ys
> ./ssim asum.yo
...
IF: Fetched addl at 0x65.  ra=%ebx, rb=%ecx, valC = 0x0
IF: Fetched irmovl at 0x67.  ra=----, rb=%ebx, valC = 0xffffffff
IF: Fetched addl at 0x6d.  ra=%ebx, rb=%edx, valC = 0x0
IF: Fetched jne at 0x6f.  ra=----, rb=----, valC = 0x57
IF: Fetched popl at 0x74.  ra=%ebp, rb=----, valC = 0x0
IF: Fetched ret at 0x76.  ra=----, rb=----, valC = 0x0
IF: Fetched halt at 0x39.  ra=----, rb=----, valC = 0x0
46 instructions executed
Exception status = HLT
Condition Codes: Z=1 S=0 O=0
Changed Register State:
%eax:   0x00000000      0x0000abcd
%ecx:   0x00000000      0x00000024
%ebx:   0x00000000      0xffffffff
%esp:   0x00000000      0x000000f8
%ebp:   0x00000000      0x00000100
%esi:   0x00000000      0x0000a000
Changed Memory State:
0x00f0: 0x00000000      0x00000100
0x00f4: 0x00000000      0x00000039
0x00f8: 0x00000000      0x00000014
0x00fc: 0x00000000      0x00000004

> ./yas asum-inc.ys
...
IF: Fetched incl at 0x65.  ra=%ecx, rb=----, valC = 0x0
IF: Fetched irmovl at 0x67.  ra=----, rb=%ebx, valC = 0xffffffff
IF: Fetched addl at 0x6d.  ra=%ebx, rb=%edx, valC = 0x0
IF: Fetched jne at 0x6f.  ra=----, rb=----, valC = 0x57
IF: Fetched popl at 0x74.  ra=%ebp, rb=----, valC = 0x0
IF: Fetched ret at 0x76.  ra=----, rb=----, valC = 0x0
IF: Fetched halt at 0x39.  ra=----, rb=----, valC = 0x0
54 instructions executed
Exception status = HLT
Condition Codes: Z=1 S=0 O=0
Changed Register State:
%eax:   0x00000000      0x0000abcd
%ecx:   0x00000000      0x00000024
%ebx:   0x00000000      0xffffffff
%esp:   0x00000000      0x000000f8
%ebp:   0x00000000      0x00000100
%esi:   0x00000000      0x0000a000
Changed Memory State:
0x00f0: 0x00000000      0x00000100
0x00f4: 0x00000000      0x00000039
0x00f8: 0x00000000      0x00000014
0x00fc: 0x00000000      0x00000004

Note: You can run the program asum.yo using the new simulator, it should work fine (the new simulator just adds the capability of handling the incl instruction). You can't run the new asum-inc.yo program using the old simulator (ssim) since it doesn't know what to make of the incl instruction.


A new Y86 instruction: dbl (double)

Your job in this lab is to create a new Y86 simulator that supports an instruction named "dbl":

dbl rA,rB

This instruction should set rB to be twice the value in rA (double the value of the first register and store the result in the second register).

Your first step is to determine what needs to happen during each stage in the processing of the instruction. You may need to refer to fig 4.21, make a table of what has to happen during each stage of a Y86 instruction (like the tables we went over in class for each instruction).

Once you know what needs to happen for the dbl instruction to work, you need to create a file that contains the HCL that includes any changes to support the new instruction. You should start by copying the standard hcl file:

cp seq-std.hcl seq-dbl.hcl

Once you have made all the changes you think are necessary, you can try to build s simulator by typing "make sdbl" (there are rules in the Makefile to build this for you - make sure your hcl file is named "seq-dbl.hcl"). You should see something like this:

>  make sdbl
# Building the seq-dbl.hcl version of SEQ
./hcl2c -n seq-dbl.hcl seq-dbl.c
gcc -Wall -O2  -o sdbl \
        seq-dbl.c ssim.c isa.c -lm

Write some test code (a Y86 program) that uses the dbl instruction and test your simulator. Once you think your simulator has a correct implementation of the double instruction, assemble and run the program named tdbl.ys:

> ./yas tdbl.ys
> ./sdbl tdbl.yo
...
IF: Fetched dbl at 0x31.  ra=%eax, rb=%ebx, valC = 0x0
IF: Fetched rrmovl at 0x33.  ra=%ebx, rb=%eax, valC = 0x0
IF: Fetched irmovl at 0x35.  ra=----, rb=%edx, valC = 0xffffffff
IF: Fetched addl at 0x3b.  ra=%edx, rb=%ecx, valC = 0x0
IF: Fetched jmp at 0x3d.  ra=----, rb=----, valC = 0x2a
IF: Fetched andl at 0x2a.  ra=%ecx, rb=%ecx, valC = 0x0
IF: Fetched je at 0x2c.  ra=----, rb=----, valC = 0x42
IF: Fetched popl at 0x42.  ra=%ebp, rb=----, valC = 0x0
IF: Fetched ret at 0x44.  ra=----, rb=----, valC = 0x0
IF: Fetched halt at 0x19.  ra=----, rb=----, valC = 0x0
70 instructions executed
Exception status = HLT
Condition Codes: Z=1 S=0 O=0
Changed Register State:
%eax:   0x00000000      0x00000100
%edx:   0x00000000      0xffffffff
%ebx:   0x00000000      0x00000100
%esp:   0x00000000      0x000000fc
%ebp:   0x00000000      0x00000100
Changed Memory State:
0x00f4: 0x00000000      0x00000100
0x00f8: 0x00000000      0x00000019
0x00fc: 0x00000000      0x00000008