I'm implementing a sorting algorithm in 68000 assembly and decided to use the stack to pass parameters to a subroutine that swaps two elements in an array. I want to make sure I'm handling the stack correctly and efficiently.
Specifically, before calling the SWAP_SUB
subroutine, I push the addresses of the two elements onto the stack using pea.l
, then retrieve them inside the subroutine using offsets from A7
.
Here’s the full code:
ORG $8000
START:
moveq.l #len-1,d7
OUTER_LOOP:
lea.l array,a0
moveq.l #len-2,d6
INNER_LOOP:
move.b (a0)+,d2
cmp.b (a0),d2
blt.s DO_SWAP
NO_SWAP:
subq.l #1,d6
bge.s INNER_LOOP
subq.l #1,d7
bge.s OUTER_LOOP
SIMHALT
DO_SWAP:
pea.l (a0)
pea.l -1(a0)
bsr.s SWAP_SUB
addq.l #8,a7
bra.s NO_SWAP
SWAP_SUB:
movem.l d3-d4,-(a7) ;new line
move.l 4(a7),a0
move.l 8(a7),a1
move.b (a0),d3
move.b (a1),d4
lsl.w #8,d3
or.w d4,d3
rol.w #8,d3
move.w d3,d5
lsr.w #8,d5
move.b d5,(a0)
andi.w #$00FF,d3
move.b d3,(a1)
movem.l (a7)+,d3-d4 ;new line
rts
array DC.B 5,3,8,1,7
len EQU 5
END START
- Did I correctly use the stack for passing parameters? Are there any potential issues with my approach?
- Is there a general way to set up the stack when passing parameters to a subroutine?
The stack aspect is fine. The cleanup is in place. And really you can pass your parameters anyway you like. Either in registers, pushed on the stack in your preferred order, a mixture of registers and stack, or even through passing a single address that directs the callee to a chunk of memory that contains the actual parameters (GEM on the Atari did it that way). The choice is yours.
- Can this code be simplified in any way?
Some people might cry out: you must be joking!
Why do you use that many instructions (and clobber that many registers) for such a simple task?
SWAP_SUB:
movea.l 4(a7), a0
movea.l 8(a7), a1
move.b (a1), d0
move.b (a0), (a1)
move.b d0, (a0)
rts
Why do you keep using a construct that leaves the loop and then has to unconditionally BRA
back? Just write the opposite condition for your blt.s DO_SWAP
:
bge.s NOSWAP
pea.l (a0)
pea.l -1(a0)
bsr.s SWAP_SUB
addq.l #8, a7
NOSWAP:
subq.l #1,d6 bge.s INNER_LOOP subq.l #1,d7 bge.s OUTER_LOOP
Why did you use BGE
here? D7 was setup with 4 (5-1). The outer loop runs through 4, 3, 2, 1, and 0 which is 5 times, but it's simply impossible to correctly have 5 comparisons in an array that only consists of 5 elements! The solution is to stick with the trustworthy BNE
. Alternatively, use the DBNE
instruction that I explained just now in great detail in my answer to one of your previous questions.
(This might not solve all the issues in this bubble sort).