#Tower of Alloy

8 messages · Page 1 of 1 (latest)

minor torrent
#

||```const disk_nr = r1
const source = r2
const dest = r3
const spare = r4
const pickup = r5

main:
mov pickup, 5
mov sp, 1800
console sp
mov sp, 2048

in disk_nr
in source
in dest
in spare

call move
jmp main

move:
cmp disk_nr, zr
jne skip
call doPlace
ret
skip:
push disk_nr
push source
push dest
push spare
call swapsd
sub disk_nr, disk_nr, 1
call move
pop spare
pop dest
pop source
pop disk_nr
call doPlace
push disk_nr
push source
push dest
push spare
call swapss
sub disk_nr, disk_nr, 1
call move
pop spare
pop dest
pop source
pop disk_nr
ret

doPlace:
out source
out pickup
out dest
out pickup
ret

swapsd:
mov r6, spare
mov spare, dest
mov dest, r6
mov r6, zr
ret

swapss:
mov r6, spare
mov spare, source
mov source, r6
mov r6, zr
ret```||

exotic vector
#

Since you've asked for feedback, some minor points:

  • mov r6, 0 is doing nothing useful, you never use r6 without moving some other value into it first.
  • You can sub disk_nr, disk_nr, 1 once after push disk_nr and then not touch it until the final pop disk_nr. pop-ing it only to then sub again (creating exactly the same value) is busy work.
  • swapss and swapsd are called exactly once each, I'd inline them and then "undo" the swaps (by swapping in reverse) instead of pushing and popping, but your push/pop works too.
  • swapss and swapsd are short but not very descriptive function names.
  • I don't see the purpose behind
console sp
mov sp, 2048``` is that just to clear the display?
minor torrent
#

Much appreciated. That's very helpful -- I've shared my thought process below,. If I've made any deductive errors, hopefully, the cause will be clear.

a) mov r6, 0 does nothing because the program restarts for each test, Line 17 jmp main is also never called if I'm not mistaken.
b) I am under the impression that the doPlace on line 38 needs disk_nr and not disk_nr-1?
c/d) Agreed, I would do that inline in a further refactor -- they are a vestige of magnification, like my previous push/pop pseudo-functions.
e) ON 💯
f) Clearing the display is a bonus. However, I find it nearly imposable to scroll the ram component. Using the console to see that data is being stored in ram (in this case the stack) helped to visualize the flow of data on the stack even without it being human readable. The stack fills from bottom up, so I'm setting the console pointer a little lower than the SP. In general operation, my ISA actually has a Constant for inject a framebuffer address offset, so I don't need to clear the screen every level.

exotic vector
#

a) Not quite. The only time you use r6, is in the swapss and swapsd functions, any data in them is lost. It doesn't matter if you leave stale data in r6 since you never read it, without first putting known data in.
This is tiny toy program so we can confidently state r6 is never used outside these function. In a larger program you might not know this so you'd ned to take greater care, either restoring r6 (by pushing and popping) in those functions or document it as a "caller saved" register, and make sure the caller (in this case move) preserved any important data in it.
b) Write out the changes that happen to disk_nr, you'll see some redundancy, what fat can you trim?
f) That makes sense, it's a handy way to get around the clunky scrolling. BTW you can use the "Jump to Offset" button on the RAM to scroll to a known address.

minor torrent
exotic vector
#

@minor torrent we were discussing Tower here.

minor torrent
#

Thanks, I forgot!

minor torrent
#

Figured it out

||```const disk_nr = r1
const source = r2
const dest = r3
const spare = r4
const pickup = r5

main:
mov pickup, 5
mov sp, 2048

in disk_nr
in source
in dest
in spare

call move

move:
cmp disk_nr, zr
jne skip
call doPlace
ret

skip:

; Store arguments
push disk_nr
push source
push dest
push spare

; swap Spare and Dest, sub 1 from disk_nr
mov r6, spare
mov spare, dest
mov dest, r6
mov r6, zr
sub disk_nr, disk_nr, 1

call move

; Restore arguments
pop spare
pop dest
pop source
pop disk_nr

call doPlace

; Swap Spare and Source, sub 1 from disk_nr:
mov r6, spare
mov spare, source
mov source, r6
mov r6, zr
sub disk_nr, disk_nr, 1

call move

ret

doPlace:
out source
out pickup
out dest
out pickup
ret```||