• Avoid warm boot on exit form a C program (Hi-Tech C compiler)

    From Luca Masini@21:1/5 to All on Sat Jul 22 17:34:55 2023
    Hi,

    I'm playing with HI-TECH-Z80-C from https://github.com/agn453/HI-TECH-Z80-C

    One small program that I did is the following cls.c

    #include <cpm.h>
    void main()
    {
    char * s = "\033[2J\033[H$"; /* Clear the screen and go home */
    bdos(9, s); /* BDOS function 9 (C_WRITESTR) - Output string */
    }

    This clear the screen but on exit a CP/M warm boot is done.

    Is there a way to exit from C without triggering a CP/M warm boot?

    MfG
    Luca

    PS: it was compiled with the following command line
    zxc -n cls.c

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Douglas Miller@21:1/5 to All on Sat Jul 22 19:42:42 2023
    I'm not sure specifically about Hi-Tech C, but generally C compilers use a runtime environment on CP/M that places the stack at top of memory, directly below the BDOS (possibly under some other runtime structures like stdio). So, there is no way to avoid
    a warm boot, since the CCP has been overwritten.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Steve Nickolas@21:1/5 to Luca Masini on Sun Jul 23 00:01:27 2023
    On Sat, 22 Jul 2023, Luca Masini wrote:

    Is there a way to exit from C without triggering a CP/M warm boot?

    That's literally what exiting any program does in CP/M.

    I mean, you could try jumping back into the CCP, but that's going deep
    into the bowels of CP/M and I think won't work at all with 3...

    -uso.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ladislau szilagyi@21:1/5 to All on Sat Jul 22 22:29:46 2023
    Hi,

    see https://github.com/Laci1953/RC2014-CPM/tree/main/ReturnToCCP

    , for an example of how to build, using the HiTech C compiler, a .COM file that returns directly to CCP, without a CP/M warm boot.

    Ladislau

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luca Masini@21:1/5 to ladislau szilagyi on Sun Jul 23 04:26:05 2023
    On Sunday, July 23, 2023 at 7:29:48 AM UTC+2, ladislau szilagyi wrote:

    see https://github.com/Laci1953/RC2014-CPM/tree/main/ReturnToCCP
    , for an example of how to build, using the HiTech C compiler, a .COM file that returns directly to CCP, without a CP/M warm boot.

    thank you ladislau szilagyi.
    I think this will work also in my environment (a Z80-MBC2 board) after I solve a small problem.
    Currently when I submit the make.sub taken from your github repository it end with the following message about unknown psect text


    (xsub active)
    LINK
    link> -PTEXT=100H,DATA,BSS -C100H -OMYDUMPX.COM MYCRTCPM.OBJ DUMPX.OBJ LIBC.LIB
    unknown psect: TEXT

    MfG

    Luca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ladislau szilagyi@21:1/5 to All on Sun Jul 23 04:57:43 2023
    Hi Luca,

    the problem is the name of the segments; they MUST be named 'text' ,'data', 'bss' (NOT uppercase TEXT,DATA,BSS)

    In my make.sub, you will find :

    link
    -ptext=100h,data,bss -c100h -omydumpx.com mycrtcpm.obj dumpx.obj libc.lib

    Now, to be honest, I do not see a big advantage of using this approach of "avoiding" CP/M warm boot...

    Why do you think HiTech did not used this method as a default?

    Because, it's about a balance between gaining speed vs. loosing memory.

    Using my method, you gain speed (CP/M is not read back in memory, after a .COM exits), but you loose 2KB of TPA space.

    This might be important in some cases...

    By the way, see the "original" HiTech's crtcpm.as here: https://github.com/Laci1953/RC2014-CPM/blob/main/ReturnToCCP/crtcpm.original.as

    , in order to see how simple is the modification I used...

    regards,
    Ladislau

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Douglas Miller@21:1/5 to ladislau szilagyi on Sun Jul 23 06:05:14 2023
    On Sunday, July 23, 2023 at 12:29:48 AM UTC-5, ladislau szilagyi wrote:
    Hi,

    see https://github.com/Laci1953/RC2014-CPM/tree/main/ReturnToCCP

    , for an example of how to build, using the HiTech C compiler, a .COM file that returns directly to CCP, without a CP/M warm boot.

    Ladislau

    Ah, you are replacing the standard HiTech C RunTime, so to change how the stack is created. This assumes the CCP is 2K and lowers the stack area used by C so that it avoids overwriting the CCP, in addition to saving the CCP SP so that you can do a clean
    RET on exit. So the only complication would be if it was run on a system with a larger CCP, in which case CCP_SIZE needs to be adjusted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ladislau szilagyi@21:1/5 to All on Sun Jul 23 06:19:40 2023
    Hi Douglas,

    yes, you are right, I could not find a simple way to calculate the CCP base address (or the CCP size) , so I assumed that we are working with the "original" CCP, which is 806H bytes long...

    For other, "custom" CCP's, the mycrtcpm.as source code must be changed accordingly.

    Ladislau

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luca Masini@21:1/5 to ladislau szilagyi on Sun Jul 23 08:14:15 2023
    On Sunday, July 23, 2023 at 1:57:45 PM UTC+2, ladislau szilagyi wrote:

    By the way, see the "original" HiTech's crtcpm.as here: https://github.com/Laci1953/RC2014-CPM/blob/main/ReturnToCCP/crtcpm.original.as
    , in order to see how simple is the modification I used...

    The following lines need to be commented in mycrtcpm.as
    ; push hl
    ; call _exit
    otherwise the call to _exit do a warm boot

    MfG
    Luca.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Douglas Miller@21:1/5 to ladislau szilagyi on Sun Jul 23 07:50:59 2023
    On Sunday, July 23, 2023 at 8:19:42 AM UTC-5, ladislau szilagyi wrote:
    Hi Douglas,

    yes, you are right, I could not find a simple way to calculate the CCP base address (or the CCP size) , so I assumed that we are working with the "original" CCP, which is 806H bytes long...

    For other, "custom" CCP's, the mycrtcpm.as source code must be changed accordingly.

    Ladislau

    Nothing wrong with your approach, I just wanted to make sure anyone looking at this understood the implication. I have seen other threads lately where some have written their own CCP or run across an old one that was larger than 2K.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ladislau szilagyi@21:1/5 to All on Sun Jul 23 08:42:53 2023
    Thanks Luca, you're absolutely right!

    I updated the file on GitHub...

    Ladislau

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fridtjof.martin.weigel@gmail.com@21:1/5 to ladislau szilagyi on Sun Jul 23 08:38:48 2023
    On Sunday, July 23, 2023 at 9:19:42 AM UTC-4, ladislau szilagyi wrote:
    Hi Douglas,

    yes, you are right, I could not find a simple way to calculate the CCP base address (or the CCP size) , so I assumed that we are working with the "original" CCP, which is 806H bytes long...

    For other, "custom" CCP's, the mycrtcpm.as source code must be changed accordingly.

    Ladislau
    Just to let you know -- CCP for CP/NET 1.2 is about 4 pages longer than CP/M 2.2
    See my R program for how I handle this with the R.COM loader (just a single MAC source file).

    https://github.com/ratboy666/r

    Also, have a look at

    https://github.com/ratboy666/tiny/blob/main/tiny.c

    This demonstrates that you don't even need crtcpm.as AT ALL! Just the run-time intrinisic functions. For a 128 byte program written in HiTech C!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Steve Nickolas on Mon Jul 24 14:27:22 2023
    On 23/07/2023 2:01 pm, Steve Nickolas wrote:
    On Sat, 22 Jul 2023, Luca Masini wrote:

    Is there a way to exit from C without triggering a CP/M warm boot?

    That's literally what exiting any program does in CP/M.

    I mean, you could try jumping back into the CCP, but that's going deep into the bowels of CP/M and I think won't work at all with 3...

    Speaking of which, can anyone remind me what would happen were this
    'no warm boot' scheme run under CP/M-3 ? IIRC CCP3 is a transient
    which loads at 100h and whose source is banked memory. Then there
    are the CP/M-3 RSX. Is top of TPA still determined from the page
    number located at address 0007h ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ladislau szilagyi@21:1/5 to All on Mon Jul 24 01:28:40 2023
    Hi Luca,

    after some careful investigations, it turns out that, after all, _exit was called correctly, but after doing its job, it jumped to 0 in its original HiTech library implementation, that's why CP/M re-booted...

    I published a new, corrected version.

    What was the problem: it could happen that in a C program, the author forgets to close a file that was opened for write.

    Because of this, at the end of crtcpm, _exit was used.

    Therefore, I modified mycrtcpm.as, now the final part looks like this:

    call _main ; HL = value returned by main
    ld (80H),hl ; store-it at 80H, as required by the exit(int) definition

    ; close all 8 CP/M files, just in case the program forgot-it

    ld b,8 ; CP/M files counter
    ld hl,__iob ; FILE*
    cloop:
    push bc ; counter on stack
    push hl ; FILE* on stack
    call _fclose ; fclose(FILE*)
    pop hl
    ld bc,8 ; sizeof(FILE)
    add hl,bc ; go to next FILE
    pop bc ; get counter
    djnz cloop ; loop until counter=0

    ld sp,(ccp_sp) ; restore CCP's SP
    ret ; return to CCP

    As a test, I included test.c :

    #include <stdio.h>

    void main(void)
    {
    FILE* f;

    f = fopen("TEST.TXT", "w+");
    fputs("test", f);

    /* the file is NOT closed before exiting */
    }

    ...and the maketest.sub :

    xsub
    zas mycrtcpm.as
    c -v -c -o test.c
    link
    -ptext=100h,data,bss -c100h -omytest.com mycrtcpm.obj test.obj libc.lib

    Try this to verify that test.com and mytest.com have the same outcome :

    c -v -o test.c
    test
    type test.txt
    test
    era test.txt
    submit maketest
    mytest
    type test.txt
    test


    PS.
    I noticed that your Z80-MBC2 has 128 KB RAM (banked). If you intend to work with large C programs on Z80-MBC2,
    you will notice that the original HiTech's C compiler will issue "out-of-memory" error messages...
    I had the same problem, and solved it by customizing all the C compiler toolchain components (P1, CGEN, OPTIM, ZAS).
    The idea is to use the extra 64 KB RAM bank when allocating memory...
    The trick works on all sort of Z80 machines (with RAM of 2 x 64KB, 4 x 32KB, 32 x 16KB), and allows compiling safely quite large C source files...
    See the whole story here: https://github.com/Laci1953/HiTech-C-compiler-enhanced,
    plus here: https://github.com/Laci1953/Z80AS
    Of course, at the time I published these tools, I had no specs on your Z80-MBC2, but all is needed is to change some ports... just let me know if you will ever need-it.

    regards,
    Ladislau

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ladislau szilagyi@21:1/5 to All on Mon Jul 24 01:37:13 2023
    @fridtjof: yes, your code is appropriate for "embedded" C programs, but for the common C programs, it is important to :

    - initialize with 0 the BSS segment
    - handle the command line parameters
    - close the files which were opened for write (and the programmer forgot to close-it...)

    All these jobs are handled in crtcpm.obj, that's why, in most cases, it must be used...

    Ladislau

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Douglas Miller@21:1/5 to dxforth on Mon Jul 24 04:57:25 2023
    On Sunday, July 23, 2023 at 11:27:25 PM UTC-5, dxforth wrote:
    Speaking of which, can anyone remind me what would happen were this
    'no warm boot' scheme run under CP/M-3 ? IIRC CCP3 is a transient
    which loads at 100h and whose source is banked memory. Then there
    are the CP/M-3 RSX. Is top of TPA still determined from the page
    number located at address 0007h ?

    On CP/M 3, this CRT would waste some space but should still work. Most/many CP/M 3 implementations would cache the CCP in an alternate bank of RAM and so warm boot would be very fast and this enhancement is not needed. The CRT could be modified to check
    for CP/M 3 and change its behavior, since none of it is necessary. Similarly, it could check for CP/NET and use a different CCP size (although there is more probability that the CCP might be an expected size, since it was so easy to build your own).

    Note that the standard CCP.SPR from DRI was actually only 2 pages larger than the CP/M 2.2 CCP (0A00H vs. 0800H), but since it is an SPR file it contains extra pages that are not actually part of the running image (header and relocation data) and it "
    looks" bigger. So in the case of CCP.SPR you need to examine the header in order to determine what the size is when running in memory - the file size will be misleading.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luca Masini@21:1/5 to All on Mon Jul 24 14:22:11 2023
    Hi ladislau szilagyi,

    after some careful investigations, it turns out that, after all, _exit was called correctly,
    but after doing its job, it jumped to 0 in its original HiTech library implementation, that's why CP/M re-booted...
    I published a new, corrected version.
    What was the problem: it could happen that in a C program, the author forgets to close a file that was opened for write.
    Because of this, at the end of crtcpm, _exit was used.

    Thank you.
    I implemented your suggestion also in my C-runtime library mincrt.as
    that is based on https://github.com/agn453/HI-TECH-Z80-C/blob/master/cpm/ZNRTCPM.AS

    Just for info: the size of the produced CLS.COM program grow up from 17 records to 31 records
    As expected because now the line
    call _fclose ; fclose(FILE*)
    cause the linking of the fclose function.

    See the whole story here: https://github.com/Laci1953/HiTech-C-compiler-enhanced,
    plus here: https://github.com/Laci1953/Z80AS

    Sound interesting. I will take a look in the next days.

    MfG

    Luca.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Douglas Miller on Tue Jul 25 12:55:30 2023
    On 24/07/2023 9:57 pm, Douglas Miller wrote:
    On Sunday, July 23, 2023 at 11:27:25 PM UTC-5, dxforth wrote:
    Speaking of which, can anyone remind me what would happen were this
    'no warm boot' scheme run under CP/M-3 ? IIRC CCP3 is a transient
    which loads at 100h and whose source is banked memory. Then there
    are the CP/M-3 RSX. Is top of TPA still determined from the page
    number located at address 0007h ?

    On CP/M 3, this CRT would waste some space but should still work. Most/many CP/M 3 implementations would cache the CCP in an alternate bank of RAM and so warm boot would be very fast and this enhancement is not needed. The CRT could be modified to
    check for CP/M 3 and change its behavior, since none of it is necessary. Similarly, it could check for CP/NET and use a different CCP size (although there is more probability that the CCP might be an expected size, since it was so easy to build your own).

    Note that the standard CCP.SPR from DRI was actually only 2 pages larger than the CP/M 2.2 CCP (0A00H vs. 0800H), but since it is an SPR file it contains extra pages that are not actually part of the running image (header and relocation data) and it "
    looks" bigger. So in the case of CCP.SPR you need to examine the header in order to determine what the size is when running in memory - the file size will be misleading.

    Thanks. The option to bypass warm boots exists in programs compiled
    with DX-Forth for CP/M. OTOH it's not particularly useful as it
    assumes a 2K CCP. This thread got me thinking I should at least make
    the number of pages reserved user-selectable.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luca Masini@21:1/5 to All on Tue Jul 25 08:22:48 2023
    Hi dxforth,

    The option to bypass warm boots exists in programs compiled with DX-Forth for CP/M.
    OTOH it's not particularly useful as it assumes a 2K CCP.
    This thread got me thinking I should at least make the number of pages reserved user-selectable.

    I knew that DX-Forth did not call Warm-Boot on termination.
    The implementation of CLS.COM that I did in DX-Forth was the following

    : main page ;
    \ Create cls.com and exit
    turnkey main cls
    bye

    To generate a turnkey CLS.COM I used the following CP/M command line:
    forth - include cls.f

    What I didn't know was this behavior is optional.
    How can we generate a turnkey executable with DX-Forth that calls Warm-Boot on exit?

    MfG
    Luca.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dxforth@21:1/5 to Luca Masini on Wed Jul 26 12:22:54 2023
    On 26/07/2023 1:22 am, Luca Masini wrote:
    Hi dxforth,

    The option to bypass warm boots exists in programs compiled with DX-Forth for CP/M.
    OTOH it's not particularly useful as it assumes a 2K CCP.
    This thread got me thinking I should at least make the number of pages reserved user-selectable.

    I knew that DX-Forth did not call Warm-Boot on termination.
    The implementation of CLS.COM that I did in DX-Forth was the following

    : main page ;
    \ Create cls.com and exit
    turnkey main cls
    bye

    To generate a turnkey CLS.COM I used the following CP/M command line:
    forth - include cls.f

    What I didn't know was this behavior is optional.
    How can we generate a turnkey executable with DX-Forth that calls Warm-Boot on exit?

    So there's at least one other user :)

    Thanks for the question. To clarify, DX-Forth as supplied performs a warm
    boot (JMP 0) on exit. DX-Forth executables may be patched to return to CCP instead by using the INSTALL program and selecting the 'No Warm Boot' option. Note that this assumes a 2KB CCP. In the next release of DX-Forth, users
    will be able to specify the CCP size. I recommend leaving warm boot enabled for the compiler (DX.COM) for maximum TPA and only patching turnkeys.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)