This is an interesting bug. Indeed the output is:
Hello World
Hello World
Hello World
Why it does so is a consequence of the way this toy program is assembled and the way output works in MMIX
When the program is assembled in memory, it starts out with the string at address 0x0 - the bytes are:
0 1 2 3 4 5 6 7 8 9 10 11 12 ...
H e l l o _ W o r l d \n \0 ...
The output instruction is
TRAP 0,Fputs,StdOut
This instruction prints the string whose address is in register $255 and places a return value in $255. The return value is the number of bytes written on success and -1 on error
The loop does run 6 times as intended but what happens is this:
The loop begins with $255 set to 0 which is the address of the string
The first iteration prints "Hello World\n" and sets $255 to 12 which is the length of the string
The second time $255 has the value 12 - this is used as the address of the string to print. You can see in the memory layout above, address 12 has a NUL character. This makes the TRAP print nothing with success and $255 is set to 0 for number of bytes written.
The third time $255 has the value 0 which is the valid address of the string so it gets printed and $255 is set to 12 for the length of the string written.
You get the idea.
So the string is printed every other time for a total of 3 times out of 6
The fix is to set $255 to the address of the string inside the loop. The complete program is:
times IS 3
msg BYTE "Hello World",#A,0
Main SET $91,times
MUL $91,$91,2
SUB $91,$91,1
GETA $255,msg
TRAP 0,Fputs,StdOut
BP $91,@-12
TRAP 0,Halt,0