4

I have a 68000 assembly language program running on my Commodore Amiga 500 that could potentially use a lot of stack space, so I want to do bounds checking.

If I call FindTask(NULL), and check tc_SPUpper and tc_SPLower, I get $c22c24 and $c21fa4, which is 3200 bytes of stack; however, the CLI has 8000 bytes of stack allocated, and the program starts with a stack pointer of $c29598—about 26K higher in memory than tc_SPUpper.

I read in the AmigaDOS Developer's Manual that, on start, 4(sp) contains the stack size. This value does contain 8000. ("Below this on the stack at 4(SP) is the size of the stack in bytes, which may be useful if you wish to perform stack checking.")

Can I safely take sp - 4(sp) as the lower limit of the stack? Do I need to allow for the stack size, the return address, and some other data that the CLI may have on the stack?

tim.smith
  • 143
  • 7
  • Why would your program "potentially use a lot of stack space"? Is it a recursive solution to some problem? Can the problem be solved through an iterative solution instead? Or by using a formula and simple arithmetic to avoid looping of any kind? – Some programmer dude May 03 '20 at 18:15
  • I'm writing a BASIC interpreter, and the expression parser is recursive. – tim.smith May 04 '20 at 19:06
  • As far as I remember (was a few years since I worked on an Amiga) there was a command to start a program with a specified stack size. Most programs that required larger stacks had this prominently mentioned in the documentation. And of course the `.info` file also contains a field for stack size if you want to run it from the Workbench. Perhaps you could simply mention this in your documentation? And test with some different inputs to try and figure out some common requirements for the stack size? – Some programmer dude May 04 '20 at 19:14
  • As for checking the amount of available stack, the difference between `tc_SPUpper` and `tc_SPLower` is the amount of available stack when the process was last switched currently running. If this comes below a certain amount, say 1KiB, then you could halt your program and report the input to be too complex, and your program needing to be rerun with an increased stack (possibly showing example command to run). – Some programmer dude May 04 '20 at 19:17
  • Thanks. That would be the STACK command. My problem is that the amount of stack required by the interpreter depends upon the most-complex expression. For example, a*(b+c) requires (slightly) more stack space than a*d. I would rather display an error message than crash. Also, I'd really like to understand how the stack works, in case I need it for some other project in the future. – tim.smith May 04 '20 at 19:31

1 Answers1

4

After re-re-(…)-reading the manuals, I may have figured it out.

From Amiga ROM Kernel Reference Manual: Libraries & Devices, p.584:

The CLI does not create a new process for a program; it jumps to the program's code and the program shares the process with the CLI.

From this, I gather that the process returned by FindTask(NULL) is the CLI process, and tc_SPUpper and tc_SPLower refer to the stack for that process.

From AmigaDOS Developer's Manual, p. 160:

When the CLI starts up a program, it allocates a stack for that program. This stack is initially 4000 bytes, but you may change the stack size with the STACK command. AmigaDOS obtains this stack from the general free memory heap just before you run the program; it is not, however, the same as the stack that the CLI uses.

From this, I conclude that my program stack is separate from the stack in the task returned by FindTask(NULL).

Also from AmigaDOS Developer's Manual, p. 160:

AmigaDOS pushes a suitable return address onto the stack that tells the CLI to regain control and unload your program. Below this on the stack at 4(SP) is the size of the stack in bytes…

From this, I conclude that, for programs run from the CLI, the following code will give me the lowest address available on the stack.

        move.l  sp,d0               ; current stack pointer
        addq.l  #8,d0               ; return address and stack size
        sub.l   4(sp),d0            ; size of stack
        move.l  d0,stack_lowest     ; save for stack checking

For programs launched from Workbench, I think tc_SPUpper and tc_SPLower are the values that I want.

From Amiga ROM Kernel Reference Manual: Libraries & Devices, p.584:

When a user activates a tool or project, Workbench runs a program. This program is a separate process and runs asynchronously to Workbench.

I have confirmed that the difference between these two values is, indeed, the stack size specified in the .info file.

tim.smith
  • 143
  • 7