Lab 2
Lab 2 - 16/01/20
For this lab, we were given code that we looked at in class and asked to modify and report on the results. The code we were given iterates using a column index, increments through memory, and fills the bitmap with pixels.6/7 - Adding TYA after :loop
The TYA opcode takes the value of the Y register and places it in the A register. Since the A register is used to determine what color to set the pixel we are currently drawing, this will cause vertical stripes of different colors to be drawn. What is interesting is that the top left (0,0 coordinate) pixel does not conform to the vertical stripes. This is because that pixel is the only case where the A register is loaded outside of the TYA opcode, at the start of the program we load the A register with #$07, which causes the first pixel to be drawn yellow.
8/9 - Adding LSR after TYA
The LSR opcode stands for Logical Shift Right. As the name describes, this shifts all bits one position to the right. Adding this opcode doubles the length of the vertical stripes, previously each stripe was one pixel wide. The function of this opcode is a bit of an enigma, but thanks to debug mode I can see that after the LSR is executed, the Z and C bits are modified. The carry flag is especially important in this case, since two lines later there is a BNE statement, which looks to the carry flag.
10 - Adding more LSR
Adding two LSR opcodes causes a staggered series of three pixels. This breaks the previous vertical stripe format, I assume because of how the LSR interacts with the following BNE opcode, causing the loop: statement to iterate more times than previously.
Adding three LSR opcodes doubles the length of the staggered series of pixels, the three wide stagger has become six wide.
Adding four LSR opcodes doubles the length of the staggered series once more. Now the bitmap result is a single column of yellow/gray, and the remaining bitmap is divided into two series of staggered colored pixels.
Adding five LSR opcodes intensifies the result of the previous four LSR's, having a single column of staggered pixels followed by lateral rows across the entire remainder of the bitmap.
11 - Replacing LSR with ASL
The ASL opcode stands for Arithmetic Shift Left, doing what I assume to be a similar opposite of the LSR opcode. The result from one ASL is a repeating series of seven vertical stripes. What is interesting about this case is that increasing the number of ASL opcodes changes the color instead of staggering the columns. Once I introduced four ASL opcodes, the program would get stuck in the loop:, I assume because the carry bit was constantly being shifted, and therefore the following BNE opcode was never fulfilled.
12/13 - Remove LSR, ASL, introduce more INY
In the original code we have a single INY opcode before our BNE. This is to continue iterating our index (the Y register) across the bitmap. Adding an even number of INY opcodes (2,4,6) increases the distance between each vertical stripe. This makes sense, since with an even increment we will still arrive at FF and therefore trip our carry flag, which allows the BNE to exit the loop. With an odd number of INY opcodes (3,5,7) the bitmap is completely filled in an odd pattern. This is because during the first loop around, our increment misses the FF value, and overflows. Since each overflow acts as an offset, the loop will eventually reach the FF value and allow our BNE opcode to exit, but this requires multiple iterations across the bitmap.
Writing Code, Part 1
To draw a green line across the top of the bitmap and a blue line across the bottom, we need two loops. Our first loop, for the top of the bitmap, creates a pointer for the first 'page' of memory, sets the color to #$05 (green), draws a pixel, increments the Y register, and performs a CPY #$20. #$20 is the value that our Y register will be at after we draw the very last pixel in the top row, so this comparison will allow our BNE to exit. I repeat a similar process for the bottom row, initializing the A register with #$06 for blue, changing our pointer to $0500 (the last 'page' of memory), and setting our initial Y register value to #$E0. This causes our STA opcode to start at the bottom row, since if we started with a #$00 value in the Y register we would draw a line across the top of the last page of memory instead of the bottom. This change also allows us to omit the CPY opcode. This is because the value #$FF at the bottom of the bitmap is the last value we draw, so the INY opcode immediately after the draw will cause an overflow which sets the overflow flag, which is what our BNE opcode will look for when determining whether to branch or not.
Writing Code, Part 2
Drawing the vertical lines is a bit more difficult, since it requires the use of the ADC opcode. ADC stands for ADd with Carry, which adds a value to our A register. This also requires some use of the TYA and TAY opcodes, which load the value from the Y register into the A register and vice versa. Finally, we need to reset the A register after each swap, since the value of the A register is used to determine which color to draw. The general flow of my program is as follows:
Load A with our initial color (yellow)
Draw our first pixel
Transfer Y (our index) to A (to perform math with ADC)
Add #$1F to A (this pushes our index to the final column of the bitmap, all the way on the right side)
Transfer A (our new index value) to Y (our actual index value)
Load A with our second color (purple)
Draw our second pixel
Transfer Y (index) to A (math)
Add #$01 to A (this sets our index back to the left side of the bitmap)
Transfer A (new index) to Y (actual index)
BNE for our loop
This iterates through one page of memory and draws vertical lines on either side of the bitmap. The only thing we need to add is another loop to nest this loop, and allow it to iterate over memory 'pages'.
Before our left/right code, we add a LDY #$00 to reset our index.
After our left/right code, we add a INC at $61 (our pointer) to increment the page
Then, load the X register with $61 for comparison
Compare X with #$06 to see if we have exhausted the bitmap
BNE for our first loop, which will cause another page's worth of vertical lines to be drawn.
This successfully draws yellow and purple vertical lines across the sides of the bitmap.
For both of the coding portions, I have attached my solution to this post.
Conclusion
I will be very clear, Assembly liquidates my brain. However, this lab was actually incredibly enjoyable to work through. I ran into a lot of problems with solutions that were not obvious, so I had to do some digging through the 6502 opcode references. I learned how to use the ADC, TAY, TYA, CLC, and CLD opcodes, as well as furthered my understanding of the BNE opcode, which was previously a mystery. In the future, it would benefit me to spend more time theorizing what I want my program to do, instead of just jumping in to the coding portion. For instance, the second half of the coding portion would have been much faster and easier to write if I created a flowchart.
Comments
Post a Comment