Sunday, 4 January 2009

Call / Return Macros in Redcode

For a while I've been trying to implement call / ret macros in Redcode so I can call subroutines. The obvious solution is as follows and doesn't work correctly:
; this code is buggy

stack dat 0

call equ mov #2-return, <stack
equ jmp

ret equ jmp return

return mov.b >stack, #0
jmp @return
Unfortunately, this only works for forward calls. The address offset is out by 1 for reverse calls and I can't find a simple fix. I've tried the following solutions, but I'm not particularly happy with any of them:
  • adding a nop to the top of all subroutines (extra code)
  • using a macro to automatically adjust the address, e.g. call subroutine adjust (ugly)
  • adjusting the address the first time it is executed (extra code, slower)
Can you suggest a better solution?

3 comments:

Neogryzor said...

The only solution i can find is to fix the value in the 'call' line.

;redcode
;name call/ret
;author Neo
;assert 1

call equ mov.ab #3-stack,<stack
equ jmp
ret equ add.ba stack,1
equ jmp @stack,>stack

ORG main

stack: dat 0,0

su1: nop 1,1
ret

;main code
main: call su1+(su1<0)
call su2+(su2<0)
jmp 0,0

su2: nop 0,0
ret
end

It's uncomfortable, but at least you don't need extra code.

John said...

Hi Neo,

Your solution is one of the best I've seen. I implemented something similar, but using a macro to adjust the value.

I'm sure there's a better solution waiting to be discovered.

John

PS - your return code doesn't always work if there's other items on the stack.

org start

stack dat 0

; -------------------------------------
call equ mov #2-return, <stack
equ jmp (a=

fix equ )+(a<0)

ret equ jmp return

return mov.b >stack, #0
jmp @return
; -------------------------------------

for 3
dat 0,0
rof

r1 ret

for 3
dat 0,0
rof

start call r1 fix
call r2 fix
jmp 0

for 3
dat 0,0
rof

r2 ret

Neogryzor said...

Uh, i didn't notice that bug in my code.

"equ jmp (a=
fix equ )+(a>0)"

I didn't know it was possible to let those variable asignement lines unfinished, very neat!