Burngate wrote:I did the same with the BBC BASIC assembler version - that took a bit more fudging, to get the count returned, but I don't think it's changed anything material
Code: Select all
.
A% = 0: Loops% = 1: Total% = 0
B% = 1:C% = 2:D% = 3:E% = 25
PRINT "Starting ..."
FOR I% = 1 TO Loops%
startTime% = TIME
REM CALL code%
count%=USR(code%)
.
.
.entry%
ADC R0,R0,#1 ;increment loop count
STMFD R13!, {R1-R4,R14} ;save to stack
CMP R4,#1 ;check pieces
LDMLEFD R13!, {R1-R4,PC} ;if 1 piece or less return
SUB R4,R4,#1 ;dec. pieces
BL entry% ;go back in
SUB R4,R4,#1 ;dec. pieces
BL entry% ;go back in
LDMFD R13!, {R1-R4,PC} ;return
What's odd is that it comes up with only 439202
I haven't looked at the other versions yet, but something odd is going on.
With suitable qualifications in place (i.e., I might be wrong in stating this - so if you know better please let me know !) - it appears that a slightly altered version based on the original program
doesn't seem to complete in 2^n-1 calls.
The modified code is as follows (I've added a bit to Gavin's that outputs the actual iteration count (held in R4)) this is incremented after each call (or recursive call) to the original routine. I've noted lines in the program that are different from the original.
Code: Select all
REM Hanoi in Basic and Assembler
REM GCW 11/04/2013
ON ERROR PRINT REPORT$;" at line ";ERL:END
PROCDebug : REM [AMcS] New Line - Assemble Debugging code
code% = FNasm
A% = 25: Loops% = 1: Total% = 0
B% = 1:C% = 2:D% = 3
E%=0 : REM [AMcS] New Line - To initialise register 4 to zero
PRINT "Starting ..."
FOR I% = 1 TO Loops%
startTime% = TIME
CALL code%
endTime% = TIME
Total% += endTime% - startTime%
NEXT
PRINT "Average ", Total%/Loops%, " centiseconds"
END
DEF FNasm
DIM P% 60
[ OPT 2
.entry%
STMFD R13!, {R0-R3,R14}
ADD R4,R4,#1 \\New Line - Increment number of times Hanoi ASM entry is called
BL debugEntry \\New Line - Call new Debug entry point to output R4 (Count of calls)
CMP R0,#1
LDMLEFD R13!, {R0-R3,PC}
SUB R0,R0,#1
EOR R2,R2,R3
EOR R3,R3,R2
EOR R2,R2,R3
BL entry%
SUB R0,R0,#1
EOR R1,R1,R2
EOR R2,R2,R1
EOR R1,R1,R2
BL entry%
LDMFD R13!, {R0-R3,PC}
]
= entry%
REM Debug ASM code added by AMcS
DEF PROCDebug
DIM DebugCode% 256
P%=DebugCode%
[OPT 2
.buffer
EQUS STRING$(16," ")
ALIGN
.debugEntry
STMFD R13!,{R0-R4,R14}
ADR R1,buffer
MOV R2,#16
MOV R0,R4
SWI "OS_ConvertInteger4"
SWI "OS_Write0"
SWI "OS_NewLine"
LDMFD R13!,{R0-R4,R14}
MOV PC,R14
]
ENDPROC
When I call this (with 25 disks - that is A%=25) the program consistently finishes at 242,785 iterations (@Burngate - this differs from the result you obtained - but can't immediately tell if that is because of an error introduced in the code I've altered or the changes you made).
Varying the number of disks gives different results - as far as I can tell only 2 disks is correct (takes 3 iterations) - everything after that appears off.
By changing A% (which I think sets the number of disks)
With A%=...
4 Disks I get 9 iterations (not 15 (2^4-1))
8 Disks I get 67 iterations (not 255 (2^8 -1))
16 Disks I get 3193 iterations (not 65535 (2^16-1))