In the interests of speeding up program development, I am collecting various 'standard' routines. If you have a little trick that you like to use, by all means, send it to me, I'd like to see it. Anyway, I'm better at brute force than elegance, so I put my skills to work figuring out a standard program copier. It wasn't difficult:
; Start of your program. M equ 2 ; The number of MOVs in the copier SIZE equ (0-START+LAST+1)/M ; Size of our program FROM equ LAST ; Our FROM counter TO equ LAST+1 ; Our TO counter BOTM equ 0 ; It's always zero dest equ -500 ; Where we jump to. ; START ; Stick all your code here. jmp 1 ; Do nothing except even out the code ; ??? A, B ; Lots and lots of redcode. :) ; Entrance to the copier FLEE mov #dest, TO ; set our TO location mov #BOTM, FROM ; set our starting location mov #SIZE, CNT ; the length of our program needs to be set LOOP mov <FROM, <TO ; our copier mov <FROM, <TO ; our copier CNT djn LOOP, #0 ; SIZE gets placed here jmp @TO ; Jump to the copied program LAST end START
I think it's pretty simple. If you know of a better/quicker way, tell me, I'd like to know it. It doesn't really matter where in your code you place the copier. However, the FROM and TO locations cannot be changed. (Well, they can, but this is a general purpose, reusable routine and changing them adds some difficulty to it.)
That, of course, wasn't what I used brute force on. Rather, I wanted to know the effect of adding more MOV <FROM, <TO lines would have. So, I wrote a quick and dirty program to do it and got some useful results. Here are the number of MOVs needed for the best utilization of the copy routine. I've seen very few programs (other than my own monstrousities) that exceed 20 instructions, so I'm just going to list the first 20 values. If anyone would like to see the values up to 100 usable instructions, just send me mail and I'll send them to you.
Usable Cycles Usable Cycles Instructions MOVs to copy Instructions MOVs to copy 1 \ If the program you want to 11 3 27 2 \ copy is between one and five 12 4 28 3 } instructions long, you really 13 3 31 4 / should hand-optimize it. 14 3 31 5 / 15 4 33 6 2 21 16 4 33 7 3 23 17 3 35 8 3 23 18 4 38 9 2 27 19 4 38 10 2 27 20 4 39
Usable instructions indicates the number of instructions (excluding the copy routine) that you have to write your main program in. MOVs are the TOTAL number of MOVs in the copy routine. The most surprising thing I found was that using 1 MOV is NEVER a good idea. The ONLY exception is in the case of a 1 line mobile program - the IMP. :) The final JMP in the copy routine takes up one of the usable instructions. Remember that when you program for it. Also, your program should ALWAYS use a number of instructions that has the number of MOVs as a factor. Below is the data the numbers above were culled from. The first column is 'Usable instructions', the numbered columns indicate the number of MOVs in the copy routine (1111=1, 2222=2, etc), the last column is the # of movs / of the best cycle count. The data in the numbered columns is the number of cycles needed to copy the entire program. The entire program is 4+MOVs+### instructions long.
If you want to check this data, the formula for figuring out the number of cycles is simple - C = 3 cycles for the copier initialization M = number of moves D = 1 (the cycle for the DJN) TI = total instructions (usable+M+4) CYCLES = C + INT(TI/M)*(M+D) If TI/M<>INT(TI/M) then add (M+D) cycles to the processing time.
The reason you need to add cycles if TI/M is not an integer is because the loop moves nM instructions. The final JMP in the copy is set up the JMP to the last instruction copied under the possibly mistaken belief that the last instruction happens to be the start of the program. If this isn't true, just change the @TO to a direct value. Technically, the final JMP might be considered another used cycle. If you feel that it is, just add 1 to all the cycle counts above.
Okay, I've written long enough, it's somebody else's turn now.
In <59...@cup.portal.com> Ordania...@cup.portal.com (Charles K Hughes) writes:
>TOTAL number of MOVs in the copy routine. The most surprising thing I >found was that using 1 MOV is NEVER a good idea. The ONLY exception is >in the case of a 1 line mobile program - the IMP. :)
Maybe I'm missing something, but what about the following routine:
(BTW, I'm not much on using EQU statements, so bear with the example)
source DAT #10 dest DAT #30 start mov temp1,source mov temp2,dest loop mov <source,<dest jmn start,source add #2,dest jmp @dest temp1 DAT #10 temp2 DAT #30
This would copy the entire program to a location 20 cells from the position of "source" and jump to that program. Now, true, it has to reload the source and dest at the beginning, but once it gets to the copying stage, it moves quite fast. I think it works especially well for long programs. Seeing that most of the successfull programs are short, though, I can understand why one wouldn't want to waste time with the "loading" portion of the code. Please pick at this. I'd personally like to know why this is a bad idea; it would help me out. Thanks... -- "Have you ever danced with the Devil by the pale moonlight? I ask that of all my prey. I just like the sound of it..." - the Joker ************************************************************************ Damon Gallaty E-mail: d...@cad.gatech.edu
This is a pretty standard way to copy your prog somewhere else. There are more sophisticated ways such as utilized by Notepaper, but this is not too bad.
init mov <prog length>,0 mov <init,<dest jmn -1,init ... lots of really useful code ... dest jmp @0,<offset to new location>
This is the routine I use, simple data location optimisation. It MUST be at the beggining of the code though...
size equ 4 dist equ 617 length equ 5
start mov #length,start ; size of code mov #dist, dest ; destination copy mov <start, <dest ; copy jmn copy, start ; till the end dest jmp @dest, dist ; jump to new code
end -- "Pis Bourassa qui est toujours la. Y'a pas d'remede contre le SIDA" - French B "This is a mad house !" - Rosencrantz ..............................................................@info.polymtl.ca
Everybody who has posted a copy routine used only 1 mov instruction in the copy loop. The reason this is a bad idea is simple- it takes X cycles longer where X is 1/6th the program size when compared to a 2 MOV copy routine. In programs where the copying code is controlled by a tight scanner, or where the program is large, those extra cycles cost a lot. When your program splits, those cycles often mean the difference between life and death.
Oh, and thanks to Andrew Pierce for his JMP B-field instruction. That *NEVER* occurred to me.
The copy routines I have seen posted here so far assume only one process is doing the copying. Now, my UseNet feed has been down for a few days & so I may have missed it, but what about the routine used by Waspnest (a contemporary of Cowboy -- I think '88)? The idea is that you split off several processes that execute the same instructions. I think Waspnest splits off 7 processes so that each instruction is executed 8 times before the next one is executed. By using predecrement, you get to move lots of code for a little footprint.
Example:
offset equ 100 ; the distance the program jumps ;spinner - in this part you split up and synchronize the processes ; ; ;bomber - the bombing or scanning code, or whatever - the parallel ; processes work best for bombing ; ;jumper - the copy part jmp copy, #0 src dat #last, #0 ; points to the bottom of your code dst dat -offset, #0 ; where it's all going to go copy mov <src, <dst ; this copies N lines of code, for N = ; number of processes mov <src, <dst ; do this until you've got enough to ; copy the whole thing jmp bomber-offset, #0
-- Stephen Beitzel -- sbeit...@wet.com | "Happy, happy. Joy, joy." "Ownership of the above opinions | depends solely on how offended you are | Relax. Have a homebrew. by them." |
In article <3...@wet.UUCP>, sbeit...@wet.UUCP (Stephen Beitzel) writes: > The copy routines I have seen posted here so far assume only one process is > doing the copying. Now, my UseNet feed has been down for a few days & so I
Not quite . . . The self-copying program ImpDwarf I posted uses four processes to copy itself with no loops. This actually slows down the copy procedure (20 cycles copying as opposed to 16 with a loop) but I used it anyway because it put more emphasis on the copying over the bombing, which I felt was less important.
*********************************************************************** * Warren Kurt * "Bones, quick! He's choking!" * * vonRoeschlaub * "Dammit Jim, I'm a doctor, not a . . . oh yeah!" * ***********************************************************************
Stephen Beitzel mentioned copying with multiple threads...
The added code for splitting would make that useful (IMHO) only for larger programs. For very specific applications (Molerat & ilk, Lichen & ilk) multi-threaded copies are great. For an application like a scanner I don't think they're very useful - they take too much code to handle 'properly' , and slow down the scanning. Right now the best scanner can scan 2 locations in 3 cycles. Using multi-threading if would be possible to scan 4 locations in two cycles, but you'd still use another 4 cycles for the add/loop. On the average that is still 2 locations for 3 cycles. Programmed right, (i.e. with a LOT of tweaking) you could gain the benefit of scanning while bombing, but I don't think the effort is worth the gain because a better bomber would work just as well.
In article <1992Jun5.162347.16...@dcs.glasgow.ac.uk> fras...@dcs.glasgow.ac.uk (Campbell Fraser) writes:
>In article <60...@cup.portal.com>, Ordania...@cup.portal.com (Charles K Hughes) writes: >> Right now the best scanner can scan 2 locations in 3 cycles. Using >It's possible scan (2x-1) locations in x cycles with the following -
As has been posted to the net already (I thought it was by Campbell Fraser but maybe I'm wrong on that) it is possible to scan three locations in three cycles with something like: add offset,1 cmp a,b slt #len,-1 ;self protection jmz -3,<y ;the third scan