Corning Community College
CSCS2650 Computer Organization
Extend our debugging infrastructure with the creation of a _debugmemory subroutine.
Implement a Vircon32 assembly subroutine that uses your dap0 _debug subroutine. Your task is to display a range of memory addresses, along with their hexadecimal contents.
The starting and ending memory addresses are given as parameters via the stack.
Specifically:
You will want to go here to edit and fill in the various sections of the document:
For our debug to work with any given code we need to preserve everything that we may be using; part of this is to save the contents of our registers.
To do this we can set up a local stack to save the contents of our register while we use them with the instructions:
PUSH BP MOV BP, SP
Once we set up a local stack, we can push all of our registers onto this new stack, while still having access to the previous stack with some manipulations.
Once you have done everything you need to, you need to restore your registers and stack.
For the registers, simply pop them off the stack in reverse order, i.e if you pushed 0-13, you will pop 13-0.
The stack can be just as simple as that, or more difficult depending on your approach. The simpler approach is to do the reverse of creating a local stack, that is:
MOV SP, BP POP BP
Along with preserving your register you need to preserve your texture and region, this should be done after preserving at least one of your registers, as we need to use a register to get the data to preserve.
Once we have preserved our registers, simply use the 'IN' instruction to get information from the GPU port like this:
IN R0, GPU_SelectedTexture PUSH R0 IN R0, GPU_SelectedRegion PUSH R0
And just like our registers, we need to pop them in reverse order to restore them when we're done:
POP R0 OUT GPU_SelectedRegion, R0 POP R0 OUT GPU_SelectedTexture, R0
The AND op code will do an and comparison of two values
mov R0, 0x00F00000 mov R1, 0x12689649 and R0, R1
This code will leave us with 0x00600000 because every other value was put into and with a zero.
A shift left can be done with the op code SHL
mov R0, 0x00F00000 mov R1, 4 shl R0, R1
This code will give R0 the value 0x0F000000 because the original value was left-shifted by 4 bits.
There isn't an op code provided by Vircon32 for right shifts, so we must shift left by a negative value.
mov R0, 0x00F00000 mov R1, -4 shl R0, R1
This code will give R0 the value 0x000F0000 because we shifted the original value to the left by -4 bits.
SET DATA SET X SET Y SET POSITION TO LEFTMOST NIBBLE UNTIL WE HAVE DISPLAYED ALL NIBBLES: OBTAIN NIBBLE AT POSITION SHOULD NIBBLE BE GREATER THAN OR EQUAL TO TEN: ADD SEVEN TO ITS VALUE ADD FORTY EIGHT TO ITS VALUE DISPLAY NIBBLE AT X, Y INCREMENT X ACCORDINGLY ADJUST POSITION TO NEXT NIBBLE TO THE RIGHT REPEAT
In your code you will want to put
%include "debug.s"
at the very end of your code. THIS IS VERY IMPORTANT. If you include debug.s at the top of your code, the hexadecimal values may print but the remainder of the program in which you called __debug may not function as expected.
Beyond getting your values to be displayed you also need to include “0x” to signify that the number you are displaying in hexadecimal. It is important to know that the 0 and x have a number assigned to them in ASCII code which are as follows:
ASCII code for 0 --> decimal 48, hexadecimal 0x30 ASCII code for x --> 120 ASCII code for [ --> 91 ASCII code for ] --> 93 ASCII code for : --> 58
Knowing this, we can now select where we want to display these values by simply calling the following:
mov R0, 48 ; ASCII code for 0 is moved into RO out GPU_SelectedRegion, R0 ; Selecting region out GPU_DrawingPointX, R2 ; Providing X axis location out GPU_DrawingPointY, R3 ; Providing Y axis location out GPU_Command, GPUCommand_DrawRegion ; Displaying iadd R2, 9 ; Spacing logic
We need to get a nibble on it's own, to do this we can use a bit mask
A mask only allows certain bit positions to be either 1 or 0, and forces everything else to be 0
This is done with the and operator
In order to get the most significant nibble we would want a mask of 0xF0000000 (0b11110000000000000000000000000000)
mov R1, 0xF0000000 ; Creating the mask and R1, R0 ; R0 is the original value
To get the second most significant nibble, instead of creating a new mask by hand, we can shift the old mask over by a nibble ever time we loop
We should have a register keep track of our loop count
mov R2, R3 ; R3 is the loop count imul R2, -4 ; Left shift bits per nibble mov R1, 0xF0000000 ; Creating the mask shl R1, R2 and R1, R0 ; R0 is the original value
Because we already have the debug function, we can use that to display all of the hex values needed
The format is identical for every address, and goes as the following: [address]:value
We can print the brackets and colon manually and leave the address and values to the debug function
mov R3, 91 ;ASCII code for '[' out GPUREGION, R3 mov R3, 0 ;Xpos out XDRAWINGP, R5 out GPUCOMMAND, DRAWREGION ;Draw
Repeat this for ']' and ':' changing the Xpos and accounting for the address width
Utilize the debug function to print the address and value as shown in the following
push R2 ;R2 is the current address mov R3, 10 ;Xpos push R3 push R4 ;Ypos call _debug mov R3, [R2] ;Get the value push R3 mov R3, 130 ;Xpos push R3 push R4 ;Ypos call _debug
All of this code should be run for every address, stepping from the start value to the end value
We will need to setup a loop with an exit condition
MOVE THE STARTING ADDRESS INTO A DEDICATED REGISTER (current address) UNTIL WE HAVE PASSED THE FINAL ADDRESS: TEST IF THE CURRENT ADDRESS IS GREATER THAN THE FINAL ADDRESS SHOULD IT BE GREATER SKIP TO AFTER THIS LOOP DISPLAY THE ADDRESS AND VALUE INCREMENT THE YPOS INCREMENT THE ADDRESS REPEAT
To be successful in this project, the following criteria (or their equivalent) must be met:
Let's say you have completed work on the project, and are ready to submit, you would do the following:
lab46:~/src/SEMESTER/DESIG/PROJECT$ submit DESIG PROJECT file1 file2 file3 ... fileN
You should get some sort of confirmation indicating successful submission if all went according to plan. If not, check for typos and or locational mismatches.
I'll be evaluating the project based on the following criteria:
182:dap1:final tally of results (182/182) *:dap1:submitted file called debug.s or debug.asm [13/13] *:dap1:subroutine is called _debugmemory or __debugmemory [13/13] *:dap1:code assembles with no warnings or errors [13/13] *:dap1:parameters obtained, modified in the stack [13/13] *:dap1:register states preserved across call [13/13] *:dap1:debug subroutine uses stack instructions [13/13] *:dap1:screenshot of subroutine in action to discord [26/26] *:dap1:code contains usage instructions in comments [26/26] *:dap1:output contains display of addresses, contents [26/26] *:dap1:functionality is correct and to specifications [26/26]