Ok so the test script for StaticsTest seems to want the terminating SP to be 263. The value I get with my translator is 258.
When running the VM version of the test its value is also expected to be (and indeed is) 263, but then the initial SP value is 261 which makes sense seeing as the program terminates with two values on the stack. It seems strange to me that in the VM version (Ending SP) - (Starting SP) = 2 but the translator version the value is expected to be 5 (263 - 256). I hope my description makes sense.
StaticsTest is expecting that you have a complete prologue at the beginning of your translation. You should set SP=256, then emit the code for 'call Sys.init 0'. This will result in a proper stack frame and SP=261 when Sys.init gets called.
I write a halt loop immediately after the Sys.init call for safety (it should never return, but...). I also set THIS, THAT, LCL and ARG to -1 in my prologue so that the CPU emulator will trap if they are used before they are initialized.
Is there any reason not to remove bootstrap code and simply place Sys.vm assembly code at the front of the .asm file? I've been doing this for nearly everything so far and it works fine.. mostly. Added the option to do it the normal way for testing staticstest and some others.
It gives you some free ROM space and 5(?) extra lines on the stack. Assuming my understanding of how the "normal" way works is correct.
Is there any reason not to remove bootstrap code and simply place Sys.vm assembly code at the front of the .asm file?
Sys.jack will eventually be written by the student in chapter 12. There is no guarantee that Sys.init() will be the first function in the Sys class. At minimum, you should jump to Sys.init. This also eliminates you requirement that Sys.vm be the first file processed.
My bootstrap has an infinite loop after it calls Sys.init(). It's much easier to debug your Sys.init() if the machine does something sensible when Sys.init() accidentally returns. If there is not a complete stack frame available when Sys.init() returns, you'll end up jumping through an uninitialized return IP.
If you write assembly language subroutines to handle the bulk of call and return, then the added code to call Sys.init() is minimal. The only time I've overflowed the stack has been with bad recursive code.