## Compiled Program Information

This information is provided for the general interest of basic programs and for programmers who might be modifying the SM32 source code. Consider the following simple program:

    0010 BEGIN
    0020 LET A%=5
    0030 LET B%=6
    0040 LET C%=C%+A%+B%
    0050 IF C%<100 THEN GOTO 0040

At run time the start of the compiled code for this program (all programs) will contain the following stucture:

    struct pr_header
       {
       lwrd prog_len;
       lwrd ksa_len;
       lwrd total_x_level_slots;
       lwrd vpl_disp;           /* variable references	*/
       lwrd vpls;
       lwrd prog_refs_disp;     /* Line # references	*/
       lwrd prog_refs;
       lwrd compile_rev_no;
       swrd crc16;
       swrd not_useda;
       lwrd fnl_disp;           /* field pointer list	*/
       lwrd fnls;
       lwrd data_statements;
       lwrd save_time;
       lwrd disk_num;
       lwrd not_used[2];
       };

Followed by this code prefix (all programs contain this prefix and execution always starts here). Note the parameters that it was called with, a base_level_minus1 struct (often seen in the code as bm1 and is always contain in EDI of an executing program) and an x_level struct(often seen in the code as x_l and always contain in ESI of an executing program). bm1 starts with a vector of address that point to user run time routines. x_l is mainly used to point to program data and program addresses. The 3rd parameter is a start address for starting somewhere other than the start of the program (for example escape to console mode followed by a run).

    prefix:
        push   ebp
        mov    ebp,esp
        mov    edi,[ebp+8]    ;get base_level_minus1
        mov    esi,[ebp+12]   ;get x_level
        mov    eax,[ebp+16]   ;get start add
        or     eax,eax
        jz     end_prefix     ;start at 1st statement in program
        jmp    eax            ;start somewhere in program (from console mode)
    end_prefix:

        ;0010 BEGIN
        call   dword ptr [edi]        ;call system loop
        mov    eax,0                  ;no EXCEPT list
        push   eax                    ;flag as a BEGIN not BEGIN EXCEPT
        push   esi                    ;pass in x_l
        call   dword ptr [edi+17Ch]   ;do_begin(x_l,0);

        ;0020 LET A%=5
        call   dword ptr [edi]           ;call system loop
        mov    edx,dword ptr [esi+34h]   ;get address of A%
        mov    dword ptr [edx],5         ;5 to A%

        ;0030 LET B%=6
        call   dword ptr [edi]           ;call system loop
        mov    edx,dword ptr [esi+38h]   ;get address of B%
        mov    dword ptr [edx],6         ;6 to B%

        ;0040 LET C%=C%+A%+B%
        call   dword ptr [edi]           ;call system loop
        mov    edx,dword ptr [esi+3Ch]   ;get address of C%
        mov    eax,dword ptr [edx]       ;get C%
        mov    edx,dword ptr [esi+34h]   ;get address of A%
        mov    ecx,dword ptr [edx]       ;get A%
        add    eax,ecx                   ;add A% to C%
        mov    edx,dword ptr [esi+38h]   ;get address of B%
        mov    ecx,dword ptr [edx]       ;get B%
        add    eax,ecx                   ;add B% to (A%+C%)
        mov    edx,dword ptr [esi+3Ch]   ;get address of C%
        mov    dword ptr [edx],eax       ;save C%+A%+B% to C%

        ;0050 IF C%<100
        call   dword ptr [edi]           ;call system loop
        sub    esp,4                     ;get space of stack
        mov    edx,dword ptr [esi+3Ch]   ;get address of C%
        mov    eax,dword ptr [edx]       ;get C%
        mov    dword ptr [ebp-4],eax     ;save on stack
        mov    eax,64h                   ;get 100
        mov    edx,dword ptr [ebp-4]     ;get C% from stack
        mov    ecx,1                     ;type of compare
        push   ecx                       ;push type
        push   eax                       ;push 100
        push   edx                       ;push C%
        call   dword ptr [edi+138h]      ;do_int_comp(C%,100,1);
        call   dword ptr [edi+78h]       ;hw_get_logical ();
        or     eax,eax
        je     end_of_statement
        ;THEN GOTO 0040
        call   dword ptr [edi]
        jmp    dword ptr [esi+40h]       ;jump to statement 40
    end_of_statement:

All programs contain the follwing code:

        ;Hidden END statement
        push        esi
        call        dword ptr [edi+10Ch] ;do_end(x_l);
        ;Hidden error 21 statement
        ;any reference to an undefined TABLE or IOLIST
        ;comes here
        push        esi
        call        dword ptr [edi+128h] ;error_21(x_l);

The use addresses pointed to by EDI is pretty obvious. The User Run Time routine address are simply loaded in bm1->urts[] when SM32 comes up via:
void init_user_routine_adds (struct base_level_minus1 *bm1x)
in initurt.c. Some addresses are modified by:
void float_numbers_init(ei,routines)
depending on the choice of Hardware or Software floating point. The addresses pointed to by ESI vary with each program and are generated in 3 phases. 1st the compile time KSA information then save time translation and finally run time initialization.

## Program Keyed String Array

A program ksa is available to the programmer via LOADPROG and SAVEPROG or when a program is acting as the console mode program. (like $__BEDIT see ENTITY)

### KEYS used in the program KSA
For sample contents: DIM P! - LOADPROG "$__SETUP",P![""] (or some other program) - KSA P!

### "5xxxt" IOLIST/TABLE address

data is slot#
where the address of statement xxx will be found [in X section] at runtime in the x_level struct.
t=I for IOLIST or T for TABLE
xxx is a big endian binary line #.
xxx ranges $000001$ thru $FFFFFC$

### "6xx..xxt" IOLIST/TABLE address for a LABELED statement

The 1st lwrd in the data is slot#
where the address of statement xx..xx will be found [in X section] at runtime in the x_level struct.
The 2nd lwrd in the data is the line #
where the label is defined.
t=I for IOLIST or T for TABLE
xx..xx is the label.

### "7txx.xx" - Function Def

data is 4 lwrd's
skip slot,execute slot,line # (or -1 if not defined) and multi line flag.
The multi line flag is 0 for single line def's and 1 for multi line def's. At run time the skip slot will have the address of the FNEND(multi line) or the next statement(single line), the execute slot will have the address of the 2nd sub statement of the DEF.
t is # for numeric functions or $ for string functions
xx.xx is the function name.

### "8xxx" - FNEND

data is 0.
An FNEND statement is located at xxx. xxx is a big endian binary line #. xxx ranges $000001$ thru $FFFFFC$

### "Axxx" - Statement Address

data is slot#
where the address of statement xxx will be found at runtime in the x_level struct. xxx is a big endian binary line #. xxx ranges $000001$ thru $FFFFFC$

### "Bxx..xx" Constant Address

data is slot#
where the address of this constant will be found at runtime in the x_level struct. xx..xx is any constant string or numeric that is less than 60 bytes in length.

### "Cxx..xx" - Label Address

1st lwrd is slot#
where the address of statement xx..xx will be found at runtime in the x_level struct. The 2nd lwrd in the data is the line #
where the label is defined or 0xFFFFFE if not yet defined. xx..xx is the label.

### "Dxxxss" - WHILE/WEND

WHILE data is slot#
where the address of the default WEND statement will be found at runtime in the x_level struct. The default WEND statement is the end of the WHILE loop if the WHILE loop is executed 0 times.
WEND data is 0xFFFFFFFF
xxx is a big endian binary line #. xxx ranges $000000$ thru $FFFFFC$ ss is a big endian sub line #. ss ranges $0001$ thru $FFFF$

### "Exx..xx" Variable

data is slot#
where the address of this variable will be found at runtime in the x_level struct. xx..xx is an name_id struct.

### "Fvvvvxff...ff" Template Field

data is slot#
where the field number will be found at runtime in the x_level struct. vvvv is the templates variables slot #. x is len in bytes of field name. ff..ff is the field name.

### "Lxxx" - Source

data is source code for this line #
xxx is a big endian binary line #. xxx ranges $000001$ thru $FFFFFC$

### "Uxxx{ss}" - Object

data is object code for this line #.
xxx is a big endian binary line #. xxx ranges $000000$ thru $FFFFFC$ ss is a big endian sub line #. ss ranges $0001$ thru $FFFF$
special U keys:
- "U"+$000000$
contains a pr_header struct followed by the program prefix code.
- "U"+$FFFFFD$
contains a compiled END statement (hidden END at end of program.
- "U"+$FFFFFE$
error 21 code. Any reference to an undefined label will access this code causinng an error 21 to be generated.
- "U"+$FFFFFF$
any immediate (conmode) statement is compiled to here to be executed.

### "Vxxxx" Constant Data

data is constant less than 60 bytes long.
xxxx is the slot # (lwrd).

### "Wxxx{ss} Data Statement"

data is object code for DATA statements.
One expression per sub state number. xxx is a big endian binary line #. xxx ranges $000000$ thru $FFFFFC$. ss is a big endian sub line #. ss ranges $0001$ thru $FFFF$ special W keys:
- "W"+$000000$
data is # of data statements followed by 2 lwrd for each data statement. The 1st word is disp to data statement( in W) and the 2nd is disp to data statement (in U). Used by RESTORE.

### "Xxxxt" - IOLIST

data is object code for an IOLIST or TABLE statement.
t is I for iolist T for table. xxx is a big endian binary line #. xxx ranges $000000$ thru $FFFFFC$

### "ZREF" - Program References

the data is slot # - displacement combinations
For each slot #'s that appear in entries "5","6","7","A","B","C" and "D". The displacement is the number of bytes from "U"+$000000$ data.

### "ZVPL" Variables

the data is an array of var_pointer_list structs
For each variable in "E"

### "ZVTN" Fields

- the data is an array of field_number_list structs for each field name in "F".

### "ZZZZ"

data is "*end"
This entry always exists

### Compile Time

The SM32 compiler maintains "5xxxt" thru "Xxxxt" in the above KSA. The basic programmer affects the compile time KSA entries thru:
COMPILE E$,K![""],A$,L,E,ERR=1000 (bedit does this for you in console mode)
RENUM
RECOMP K![""]

### Save Time

At save time (or when going from conmode to run mode) the "ZREF","ZVPL" and "ZVTN" temporarily created. The object code becomes all the data portion of the KSA from "U"+$000000$ thru "ZZZZ". Displacements to the ZREF data,the ZVPL data and the ZVTN data are placed in the pr_header.

### Run Time

The execute_sm32 routine uses the vpl_disp to load the variable addresses, the prog_refs_disp to load program address references and the fnl_disp to resolve field name numbers into the x_level structure (ESI).