Omnimaga
Calculator Community => TI Calculators => Axe => Topic started by: thepenguin77 on February 17, 2012, 04:47:13 pm
-
Bet you didn't think you'd see a topic from me.
In any case, we just discussed it on IRC, and there's a pretty simple way to call one axe program from another.
Copy("prgmNAME",33912,9
asm(EF7C4E)
This will work as long as prgmNAME is in ram, so if it's not, you'll have to unarchive it first. Hopefully someone has fun with this.
Edit:
And here's (http://ourl.ca/9465/181010) how you do Basic programs.
-
Woah, that's pretty nice. I knew that you could do it from an app, but I didn't imagine that it could work from program-to-program.
Incidentally, where is 33912? Does it corrupt any other data? And would using Return in the called program return to the homescreen or return to the parent program?
-
Nice, I totally forgot about the BASIC one until it was linked to on IRC earlier. Glad to see an Axe one. Can conflict happen between programs?
-
Woah, that's pretty nice. I knew that you could do it from an app, but I didn't imagine that it could work from program-to-program.
Incidentally, where is 33912? Does it corrupt any other data? And would using Return in the called program return to the homescreen or return to the parent program?
According to thepenguin77, 33912 is the location of OP1
-
can you call the program within the program that is being called?
-
can you call the program within the program that is being called?
I assume you are asking if a program can call itself? The answer is yes, but only if the program was not run with a shell. If it was run with a shell, you are going to run into problems.
-
Does this work with any ASM program or just ones compiled with Axe?
-
It should work with all Asm programs :) (but you might need to wait for confirmation)
-
If you want a program to call itself, just put a label at the beginning of the program and call it using a normal subroutine, I'd say.
-
It doesn't work... it always crash.
-
It doesn't work... it always crash.
Make sure the Asm program is compiled for No Shell, or else it will crash
-
I'm sure, have you tested it ? Please show me a screen if you think it work, but I tested twice : on my real 83+ and on wabbitemu (84+SE). :/
-
Yes, it's OP1. Yes, control is returned the caller. This code just calls the OS routine that runs assembly programs. You can even run unsquished programs this way. (Ignore the last statement if you don't know what a squished program is.)
However, keep in mind a few things:
- Just like running programs with the Asm( token from the homescreen, you need a quantity of free RAM equal to the size of the program being run.
- Because the OS has to shuffle RAM around for this to work, it takes a split second for the new program to start. So if you do this a lot, it'll be really slow.
- If you call yourself like this, the OS will make yet another copy of yourself. Duh.
- Instant quit will return control to the calling program, not the homescreen or the shell. This is because the error handlers get nested. (The good news is that if the calling program throws an OS error, control is returned to the calling program, but I don't believe any Axe programs use error handlers.)
- By extension, do not call a shell's instant quit routine, or the memory used by caller won't get freed.
- Assuming Axe just makes a stub ISR that jumps to the real ISR, you're going to get a crash if you have an interrupt running and you try this, because your ISR just got moved.
- L1 through L6 will not be modified by the OS, neither during calling nor returning. The OP registers, however, will be corrupted.
-
Have you tested it ? Does it work with your calc ? O_o
Damn, where is the problem on my code ?
-
Huh. . . . it looks like you're doing nothing wrong. I wrote a test program myself and found a problem in the disassembly:
prgmA
.AAA
Disp "ONE...",i
Copy("prgmAAAA",33912,9
Asm(EF7C4E
Disp "...ONE.",i
Pause 2000
prgmAA
.AAAA
Disp "TWO",i
Disassembly:
prgmAAA
9D95: ld hl, 9DC3 ; Disp "ONE...",i
bcall(_450A)
bcall(_452E)
ld hl, 9DCAh ; Copy("prgmAAAA",33912,9
push hl ; Load arguments in a complicated fashion
ld hl, 8478h
ld bc, 0009
ex de, hl
pop hl
ldir ; Copy the data
ldir ; Clobber all of RAM
ld c, (hl) ; ???
ld hl, 9DD0h ; Disp "...ONE.",i
bcall(_450A)
bcall(_452E)
ld hl, 07D0h ; Pause 2000
9DBB: djnz 9DBB
dec hl
ld a, l
or h
jr nz, 9DBB
ret ; End of program code
9DC3: .db "ONE...", 0
9DCB: .db ProgObj, "AAAA", 0
9DD0: .db "...ONE.", 0
prgmAAAA
9D95: ld hl, 9D9F ; Disp "TWO",i
bcall(_450A)
bcall(_452E)
ret ; End of program code
9D9F: .db "TWO", 0
For some reason, Axe 1.1.2 is inserting the ldir twice, clobbering all of RAM. NOPing one of the ldirs out fixes it.
EDIT: Runer112 has a workaround for you:(6:43:18 PM) DrDnar: Runer112: I found an Axe bug, see http://ourl.ca/15239/286978
(6:43:32 PM) Runer112: I saw
(6:43:39 PM) DrDnar: k
(6:43:53 PM) Runer112: I can tell you it's a peephole optimizer problem
(6:44:00 PM) Runer112: so you can fix it by compiling without peephole opts [Use ZOOM---DrDnar]
(6:44:08 PM) Runer112: but I can't tell you why it's happening
(6:44:48 PM) Runer112: I'm sure Quigibo will know it's a peephole optimizer problem too
(6:44:51 PM) Runer112: it's pretty clear
-
So is there a way to easily (on calc) fix this, manually or auto? Or does it require changing it on the computer?
-
To conclude, how to to fix it ?
-
On IRC, Runer suggested Zoom compiling the source, and it seems to work
-
I've got an epic solution and optimization for you all. I can both eliminate the problem with Copy( and reduce the code size by about ten bytes.
"prgmNAME"Asm(E7EF7C4E
BAM! One-liner.
EDIT: This code causes a memory leak; see below (http://ourl.ca/15239/288877) for the fix.
For the curious:
ld hl, ptrToName
rst rMOV9TOOP1
bcall(_ExecutePrgm)
Also, to recap: The peep-hold optimizer is causing crashes with the Copy( command sometimes. You can stop Axe from doing the peep-hole optimization with ZOOM. However, it's all a moot point since I just replaced the Copy( command with the single assembly instruction rst rMOV9TOOP1.
-
I've got an epic solution and optimization for you all. I can both eliminate the problem with Copy( and reduce the code size by about ten bytes.
"prgmNAME"Asm(E7EF7C4E
BAM! One-liner.
For curious:
ld hl, ptrToName
rst rMOV9TOOP1
bcall(_ExecutePrgm)
Also, to recap: The peep-hold optimizer is causing crashes with the Copy( command sometimes. You can stop Axe from doing the peep-hole optimization with ZOOM. However, it's all a moot point since I just replaced the Copy( command with the single assembly instruction rst rMOV9TOOP1.
Thanks for the fix :D
-
Could this somehow be added to the next version of Axe? Good thought for starting this topic, penguin77.
-
Damn, is work perfectly ! :D
* kindermoumoute wonder if there is a way to start asm program compatible with shells...
-
Yeah sorry about that, I've fixed this problem but haven't released the update yet.
-
I think I found a bug with this... it causes my RAM to steadily decrease
I tried running both programs seperately, took out the "prgmNAME"Asm(E7EF7C4E) command, chose the same options on the menu (except no program was run from it), and no memory was lost ???
As you can see in the screenie, nothing was created, yet about 5000 bytes of memory disappeared (15000 at start to 10000 at finish) :(
-
You can try this:
Type 1 in homescreen, press enter, and check memory again.
-
You can try this:
Type 1 in homescreen, press enter, and check memory again.
Tried that, it doesn't fix it
Still about 2000-2500 bytes lost per run :(
-
How are you quitting from the second program? It looks like the subprogram is quitting in a manner that prevents the memory being used by the caller from being freed.
-
Update: I blame thepenguin77's for this one. Looking at the disassembly of _ExecutePrgm, it's clear that the OS does not save the value in 89ECh (a.k.a. asm_prgm_size) before modifying it, so it turns out that the memory used by the caller will never be properly freed, unless you save it yourself. Fortunately, that's easy to do, so here's the new version:
"prgmNAME"Asm(E72AEC89E5EF7C4EE122EC89
Edit: calc84maniac suggested rearranging the assembly instruction sequence to make it less ugly, though no smaller or faster.
So, once again, keep these points in mind:
- Just like running programs with the Asm( token from the homescreen, you need a quantity of free RAM equal to the size of the program being run.
- Because the OS has to shuffle RAM around for this to work, it takes a split second for the new program to start. So if you do this a lot, it'll be really slow.
- If you call yourself like this, the OS will make yet another copy of yourself. Duh.
- Instant quit will return control to the calling program, not the homescreen or the shell. This is because the error handlers get nested. (The good news is that if the calling program throws an OS error, control is returned to the calling program, but I don't believe any Axe programs use error handlers.)
- WARNING: This code will leak memory if the program throws an error! To prevent this, use the Axiom for running programs.
- By extension, do not call a shell's instant quit routine, or the memory used by caller won't get freed.
- Assuming Axe just makes a stub ISR that jumps to the real ISR, you're going to get a crash if you have an interrupt running and you try this, because your ISR just got moved.
- L1 through L6 will not be modified by the OS, neither during calling nor returning. The OP registers, however, will be corrupted.
OS Disassembly:
OS 2.55MP _ExecutePrgm disassembly
07:5758:
ld a, 03h
call 3891h
ld a, 38h
jp nz, 2793h
call 178Bh
ex de, hl
ld c, (hl)
inc hl
ld b, (hl)
inc hl
ld a, (hl)
cp 0BBh
jp nz, 2729h
inc hl
ld a, (hl)
cp 6Dh
jr nz, 57D4h
inc hl
push hl
push bc
pop de
push de
ld hl, 2000h
or a
sbc hl, de
jp c, 2729h
ex de, hl
call 1735h
pop hl
push hl
ld de, 9D95h
call 0F81h
pop hl
ld (89ECh), hl
pop hl
ld de, 9D95h
ld bc, (89ECh)
add hl, bc
ldir
579Fh: call 1837h
jr nz, 57AEh
in a, (20)
push af
bit 5, (iy+24h)
call 0DCBh
57AEh: ld hl, 5800h
call 27DAh
call 57FDh
call 2800h
call 1837h
jr nz, 57C4h
pop af
and 01
out (20), a
57C4h: ld de, (89ECh)
ld hl, 0000h
ld (89ECh), hl
ld hl, 9D95h
jp 1368h
57D4h: rst 18h ;rPUSHREALO1
call 5717h
ld hl, 2000h
or a
sbc hl, de
jp c, 2729h
ex de, hl
push hl
call 1735h
pop hl
push hl
ld de, 9D95h
call 0F81h
pop hl
ld (89ECh), hl
call 150Fh
ld de, 9D95h
call 5734h
jr 579Fh
57FDh: jp 9D95h
5800h: call 1837h
jr nz, 580Ah
pop af
and 01
out (20), a
580Ah: ld de, (89ECh)
ld hl, 0000h
ld (89ECh), hl
ld hl, 9D95h
call 1368h
jp 2799h