#show link: set text(blue) #set text(font: "Calibri") #show raw: set text(font: "Fira Code") #set table.cell(breakable: false) #set table(stroke: (x, y) => ( left: if x > 0 { .1pt }, top: if y == 1 { 0.5pt } else if y > 1 { 0.1pt }, )) #set page(margin: (y: .25in)) #let solve(solution) = { block( inset: 3pt, stroke: blue + .3pt, fill: rgb(0, 149, 255, 15%), radius: 4pt, )[#solution] } #let solvein(solution) = { let outset = 3pt h(outset) box( outset: outset, stroke: blue + .3pt, fill: rgb(0, 149, 255, 15%), radius: 4pt, )[#solution] } #let note(content) = { block( inset: 3pt, stroke: luma(20%) + .3pt, fill: luma(95%), radius: 4pt, )[#content] } #let notein(content) = { let outset = 3pt h(outset) box( outset: outset, stroke: luma(20%) + .3pt, fill: luma(95%), radius: 4pt, )[#content] } #align(center)[ = CS 3843 Computer Organization HW 8\ #underline[Price Hiller] *|* #underline[zfp106] ] #line(length: 100%, stroke: .25pt) = Part A: (Refer to the appendix for help with CPU instructions) 1. Create an instruction, which #underline[moves] number 5 to register `R00`. #solve[`MOV #5, R00`] 2. Execute the above instruction (#text(red)[You do this by double-clicking on the instruction]). Observe the result in the *CPU Registers* view (Image 4). 3. Create an instruction, which #underline[moves] number 7 to register `R01`. #solve[`MOV #7, R01`] 4. Execute it (#text(red)[You do this by double-clicking on the instruction]). 5. Observe the contents of `R00` and `R01` in the *CPU Registers* view (Image 4). #solve[ #figure( image("assets/5.png"), caption: [Observing contents after questions 1 & 3], ) ] 6. Create an instruction, which #underline[adds] the contents of `R00` and `R01`. #solve[`ADD R00, R01`] 7. Execute it. 8. Note down which register the result is put in. #solve[The result of the `ADD` was put into `R01` with a value of `12`.] 9. Create an instruction, which #underline[pushes] the value in the above register to the top of the program stack, and then execute it. Observe the value in *Program Stack* (Image 5). #solve[ Instruction: `PSH R01` ] #note[ #figure( image("assets/9-2.png"), caption: [Current program stack], ) ] #align(center)[#text(size: 3em)[#note[See next page]]] #pagebreak() 10. Create an instruction to #underline[push] number 2 on top of the program stack and execute it. Observe the value in *Program Stack* (Image 5). #solve[ Instruction: `PSH #2` ] #note[ #figure( image("assets/10.png"), caption: [Current program stack], ) ] 11. Create an instruction to #underline[unconditionally jump] to the first instruction. #solve[ `JMP 0` ] 12. Execute it. 13. Observe the value in the *PC* register. This is the address of the next instruction to be executed. What instruction is it pointing to? #solve[ The *PC* register is pointing to the original `MOV` instruction created in question one #note[ #figure( image("assets/13.png"), caption: [Current *PC* value], ) ] ] 14. Create an instruction to #underline[pop] the value on the top of the *Program Stack* into the register `R02`. #solve[`POP R02`] 15. Execute it. #solve[This just removed the value `2` from the stack.] 16. Create an instruction to #underline[pop] the value on top of the *Program Stack* into register `R03`. #solve[`POP R03`] 17. Execute it. #solve[This just removed the value `12` from the stack.] #align(center)[#text(size: 3em)[#note[See next page]]] #pagebreak() 18. Execute the last instruction once again. What happened? Explain. #solve[ I received the following error message: #figure( image("assets/18.png"), caption: [Stack underflow failure], ) This occurred because there are no values remaining in the Program Stack. In a real assembly program, this would lead to a true underflow and cause a wrap around. The `*sp` pointer would get incremented and likely result in the _relative_ address being the value 0. Most operating systems would kill off the process due to this underflow as a general rule of thumb. For example, on my Linux system running the following assembly on x86_64 produces a segfault: ```asm SECTION .TEXT GLOBAL _start _start: ; Arbitrary register chosen that a callee controls, ; could be rdi, rax, etc. pop r10 ``` ] 19. Create a #underline[compare] instruction, which compares values in registers `R04` and `R05`. #solve[`CMP R04, R05`] 20. Manually insert two equal values in registers `R04` and `R05` (image 4). #solve[ #figure( image("assets/20.png"), caption: [Equal values manually inserted], ) ] 21. Execute the above compare instruction. // #pagebreak() 22. Which of the status flags *OV/Z/N* is set (i.e. box is checked)? #solve[ The `Z` flag is set. #figure( image("assets/22.png"), caption: [`Z` flag set after equal `CMP`], ) ] #align(center)[#text(size: 3em)[#note[See next page]]] #pagebreak() 23. Manually insert a value in the first register greater than that in the second register. #solve[ #figure( image("assets/23.png"), caption: [Larger value in the _first_ register], ) ] 24. Execute the compare instruction again. 25. Which of the status flags *OV/Z/N* is set? #solve[ The `N` flag is set. #figure( image("assets/25.png"), caption: [`N` flag set after reg 1 > reg 2 `CMP`], ) ] 26. Manually insert a value in the first register smaller than that in the second register. #solve[ #figure( image("assets/26.png"), caption: [Smaller value in the _first_ register.], ) ] 27. Execute the compare instruction once again. 28. Which of the status flags *OV/Z/N* is set? #solve[ None of the flags are set. #figure( image("assets/28.png"), caption: [No flags set after reg 1 < reg 2 `CMP`], ) ] 29. Create an instruction, which will #underline[jump] to the first instruction if the values in registers `R04` and `R05` are equal. #solve[ ```asm CMP R04, R05 JEQ 0 ``` ] 30. Test the above instruction by manually putting equal values in registers `R04` and `R05`, then first executing the compare instruction followed by executing the jump instruction (*Remember*: #text(red)[You execute an instruction by double-clicking on it]). If it worked, the first instruction should be highlighted. Write your observations and what you have learned. #note[I feel I'm not quite understanding what this question is asking for, so here's to winging it.] #solve[ I've learned that `JEQ 0` will check the `Z` flag to see if its set. If it is, then it'll set the *PC* (Program Counter) register to the specified value. Of particular note, `JEQ` operates very similarly to `JZR` (in fact they have the same underlying functionality), but the semantic reason for them is different. Taking a look at https://www.felixcloutier.com/x86/jcc, it becomes clear that the semantic meaning of `JEQ` is intended to be used when we're validating equality after a `CMP` instruction, whereas `JZR` is more intended for checking the `ZF` flag where non comparison instructions may set it. ] #line(length: 100%, stroke: .25pt) = Full Program Below #note[As a note: I moved the _*unconditional*_ jump to the first instruction to the very end of the program.] #figure( image("assets/full-prog.png"), caption: [Full progam in CPU Simulator], )