Calculator Community > Axe

Variable Subroutines

(1/3) > >>

Terrav:
I was designing a modular program executor when I encountered this problem: The code I was trying to execute was not being executed and instead the calculator reset. I've tried and checked everything; I think the problem is the address. Knowing the TI-84+ only has 24KiB RAM, it puzzled me to learn my program was using memory pointers all the way up to DFFF. Everywhere I have tried to execute has an address somewhere between 8000-BFFF. A brief summary of my test code is printed below.


--- Code: ---"appvTMPFILE"→Str0
GetCalc(Str0,1)→X
[sub]E[/sub]C9→{X}
(X)()

--- End code ---
Note: I know 0xC9 is the assembly equivalent of Return.

If I were to try this with the program data itself or a safe zone (like L1) it works just fine.
Displaying the memory pointer just before calling it shows something like C3F2 or D19A.

My questions are, how is this caused, and how do I work around it?

Deep Toaster:
Hi Terrav, welcome to Omnimaga! :)
--- Quote from: Terrav on January 02, 2021, 04:18:17 pm ---Knowing the TI-84+ only has 24KiB RAM, it puzzled me to learn my program was using memory pointers all the way up to DFFF.
--- End quote ---
On the TI-83 Plus series (including the TI-84 Plus), memory addresses 0000h–3FFFh point to a flash page and 4000h–FFFFh point to RAM (hence FFFFh – 3FFFh = 24 KiB).
--- Quote from: Terrav on January 02, 2021, 04:18:17 pm ---Everywhere I have tried to execute has an address somewhere between 8000-BFFF.
--- End quote ---
Funny thing—you pretty much discovered the issue.

Addresses C000h–FFFFh point to a RAM page on which you're not allowed to execute code. That's it. Once you jump to an address beyond BFFFh, the calculator resets. (There is a way around this if you're interested, but you might find a way around this issue without unprotecting the page.)
--- Quote from: Terrav on January 02, 2021, 04:18:17 pm ---If I were to try this with the program data itself or a safe zone (like L1) it works just fine.
--- End quote ---
Both of these zones are guaranteed to be below C000h :) In fact, the reason the TI-OS refuses to execute programs larger than 8192 bytes by default seems to be a precaution against going beyond C000h—9D95h (which is where all programs are moved when they start executing) + 8192 = BD95h, which is a bit below the BFFFh limit.

E37:
I'm a bit late, but if you want to have a memory area that holds executable code and not use a fixed area, you can use the Buff(<size>) command to create a buffer at the end of the program where you can store code at. Or, if you know what you want to put there, you can simply include the assembly code as hex and jump to the data. Since Axe already lets you directly use assembly code, I assume you are trying to do something else.

You could use the Memkit axiom to create space somewhere you know will be under the execution limit. Its command New( is usually used to resize existing programs or appvars, but it doesn't have to. You can call New( on anywhere you want (although bad things would probably happen if you tried it under 9D95h) to get a safe area of memory. For example, if you have an app you can do New(E9D95, 0, 1000) to create 1000 bytes at the start of where programs usually execute. You can then do:

--- Code: ---:GetCalc("prgmWHATEVER", Y1) .Get pointer to the program
:Copy(Y1, E9D95, 1000) .Copy it to the ram area. Since programs are normally executed from E9D95, you can use absolute jumps and calls without problem
:(E9D95)() .Run the program. Once it is finished you should use Delete( to restore the 1000 bytes of memory you took. Or you can copy a different program there and run it first

--- End code ---
This assumes you are using an app. If you are using a program you are running at 9D95h and bad thing will happen if you try to push it around and write code over yourself. You don't have to use 9D95h. You can use some area after the end of your program instead.

Alternatively, if you are using a ti-84+ and don't care about 83+ compatibility, you could swap the extra ram page into 4000h-7FFFh and just put whatever you want in that 16k block of ram. Then you have 40k of ram to work with! I could be wrong but I'm pretty sure that BCALLs use that block so you should probably swap it back every time you want to read or run from it. Although they may swap it back for you.

I can give more detailed examples and code for any of this, but I don't know what you are trying to do.

Terrav:
Thank you for the suggestion; I'm basically trying to create a launcher that can run assembly programs apart from TI-OS. The allowed program size built in my program should be variable, but I guess I should watch out for the 8K program size limitation as well. Also, is there any article about the actual structure of memory/Flash/addresses that I can read? I originally thought it was 24K RAM + 1M Flash and that's it, but it appears there's a lot more I need to learn before I go digging deep in memory.

Deep Toaster:

--- Quote from: Terrav on January 04, 2021, 04:18:57 pm ---Thank you for the suggestion; I'm basically trying to create a launcher that can run assembly programs apart from TI-OS.
--- End quote ---
I don't know your architecture so I wouldn't know if you're addressing this issue already, but something to keep in mind is that assembly programs in general must be loaded (moved) to a known location in memory. This is because a common instruction in assembly code is to jump to a label, which is a absolute address (calculated relative to the location the program was loaded to). (The TI-OS loads all assembly programs to 9D95h, as I mentioned.)
--- Quote from: Terrav on January 04, 2021, 04:18:57 pm ---The allowed program size built in my program should be variable, but I guess I should watch out for the 8K program size limitation as well. Also, is there any article about the actual structure of memory/Flash/addresses that I can read? I originally thought it was 24K RAM + 1M Flash and that's it, but it appears there's a lot more I need to learn before I go digging deep in memory.
--- End quote ---
Check out https://wikiti.brandonw.net/index.php?title=83Plus:Memory_Mapping for an overview of how the pages are laid out. (Like you said, there's 24K RAM and 1M flash, but there's only 65,536 addresses (this is called virtual address space), so to access anything beyond the first first 16K (page 0) of flash, pages are swapped in and out as necessary. https://en.wikipedia.org/wiki/Paging#Main_memory_larger_than_virtual_address_space sort of describes the situation the TI calculators are in.

Check out https://wikiti.brandonw.net/index.php?title=83Plus:OS:Memory_Layout for an overview of how the RAM (in general, 4000h through FFFFh in the virtual address space) is organized. If you need the actual values of the addresses listed by name, check out https://wikiti.brandonw.net/index.php?title=83Plus:OS:ti83plus.inc.

In general, I'd recommend taking a gander at Learn TI-83 Plus Assembly in 28 Days if you haven't already. It's a fantastic guide to how assembly programs work.

Navigation

[0] Message Index

[#] Next page

Go to full version