| CompOrg Spring 2005 Lab |
|   CompOrg Home     Y86 Assembly Programming     Y86 Multiple subroutine     Building a new Y86 Simulator |
|
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
|
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)
|
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:
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.
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.hclseq-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