OpenVMS Notes: (some) VMS-BASIC Coding Techniques

  1. The information presented here is intended for educational use by qualified OpenVMS technologists.
  2. The information presented here is provided free of charge, as-is, with no warranty of any kind.

Overview

History

Back in my VAX days (VMS-4.0 to VMS-6.2) doing any kind of I/O was very expensive so it was always better to concatenate data before doing any serial I/O (like BASIC's PRINT statement). We proved this using system accounting to measure run-time stats. (not the best development tool but better than nothing)

When we moved from VAX to Alpha in 1999-2001 we only used OpenVMS-7.x and noticed everything was less costly (I/Os, spawns, queuing, etc.) but accounting tests proved it was still better to concatenate string data before doing an I/O in BASIC. (caveat: this was never true in C/C++)

Today (2013-10-24)

My recent tests with HP-BASIC-1.7 on OpenVMS-8.4 indicate that something has changed (probably for the better) over the past ten-years which now make pre-i/o concatenations unnecessary. This is also the first time I've seen the smallest binary also consume the least amount of system resources on this RISC system.

I do not have an explanation for this (because HP's solution is hidden behind BASIC RTL routines) but can imagine:

Observations
  1. Every time you see a BASIC print statement, at least two BASIC-RTL calls are made
    • DBASIC$PRINT (start of PRINT statement; possibly sets up a QIO for output to a mailbox/pipe)
    • DBASIC$IO_END (end of PRINT statement; possibly fires the QIO)
  2. Plus Signs
    1. Every time you see a plus sign joining two static strings anywhere, this string is concatenated by the compiler at compile time (no run-time implications)
    2. Every time you see a plus sign joining a static string with a string variable, you will see one system call to concatenate the string data
      • STR$CONCAT
  3. Every time you see a semicolon joining two strings in a print statement, you will see one call to the BASIC-RTL (send what you have to the local buffer)
    • DBASIC$OUT_T_DX_S (possibly just appends TEXT DATA onto the end of a local qio i/o buffer; this produces the same result as a pre-i/o string concatenation operation without the overhead)
  4. Machine-code Analysis:
    Program DBASIC$ calls STR$CONCAT calls Total Calls Size of $CODE$ section
    Neil1.bas 33 0 33 1004
    Neil2.bas 23 10 33 1084
    Neil3.bas 5 15 20 844
    Neil4.bas 21 0 21 732
    Neil5.bas 15 0 15 552

Five Stubs for machine-code analysis

neil1.bas (original code)

1000	! neil1.bas (individual PRINT statements)
	! Compiled Routine Size: 1156 (optim=level=0)
	! Compiled Routine Size: 1004 (optim=level=4)
	option type=explicit
	declare string abc$
	abc$ = "abc"
	print '<tr>';
	print '<td>'; abc$ ;'</td>';
	print '<td>'; abc$ ;'</td>';
	print '<td>'; abc$ ;'</td>';
	print '<td>'; abc$ ;'</td>';
	print '<td>'; abc$ ;'</td>';
	print '</tr>'
1040	end

neil2.bas

1000	! neil2.bas (individual PRINT statements; some plus signs)
	! Compiled Routine Size: 1236 (optim=level=0)
	! Compiled Routine Size: 1084 (optim=level=4)
	option type=explicit
	declare string abc$
	abc$ = "abc"
	print '<tr>';
	print '<td>'+ abc$ +'</td>';
	print '<td>'+ abc$ +'</td>';
	print '<td>'+ abc$ +'</td>';
	print '<td>'+ abc$ +'</td>';
	print '<td>'+ abc$ +'</td>';
	print '</tr>'
1040    end

neil3.bas

1000	! neil3.bas (one PRINT, all plus signs)
	! Compiled Routine Size: 948 (optim=level=0)
	! Compiled Routine Size: 844 (optim=level=4)
	option type=explicit
	declare string abc$
	abc$ = "abc"
	print	'<tr>'+                 &
		'<td>'+ abc$ +'</td>'+  &
		'<td>'+ abc$ +'</td>'+  &
		'<td>'+ abc$ +'</td>'+  &
		'<td>'+ abc$ +'</td>'+  &
		'<td>'+ abc$ +'</td>'+  &
		'</tr>'
1040    end

neil4.bas

1000	! neil4.bas (one PRINT, all semicolons)
	! Compiled Routine Size: 868 (optim=level=0)
	! Compiled Routine Size: 732 (optim=level=4)
	option type=explicit
	declare string abc$
	abc$ = "abc"
	print	'<tr>';			&
		'<td>'; abc$ ;'</td>';	&
		'<td>'; abc$ ;'</td>';	&
		'<td>'; abc$ ;'</td>';	&
		'<td>'; abc$ ;'</td>';	&
		'<td>'; abc$ ;'</td>';	&
		'</tr>'
1040    end

neil5.bas

1000	! neil5.bas (one PRINT; mixture of semicolons and plus signs)
	! Compiled Routine Size: 580 (optim=level=0)
	! Compiled Routine Size: 552 (optim=level=4)
	option type=explicit
	declare string abc$
	abc$ = "abc"
	print	'<tr>'+			&
		'<td>'; abc$ ;'</td>'+	&
		'<td>'; abc$ ;'</td>'+	&
		'<td>'; abc$ ;'</td>'+	&
		'<td>'; abc$ ;'</td>'+	&
		'<td>'; abc$ ;'</td>'+	&
		'</tr>'
1040    end

Machine code Analysis

neil5.lis (optim=level=4)

NEIL5$MAIN                      Source Listing                  27-OCT-2013 10:12:01  Alpha BASIC V1.7-001              Page 1
                                                                27-OCT-2013 09:37:13  CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2

              1 1000    ! neil5.bas (one PRINT; mixture of semicolons and plus signs)
              2         ! Compiled Routine Size: 580 (optim=level=0)
              3         ! Compiled Routine Size: 552 (optim=level=4)
              4         option type=explicit
              5         declare string abc$
              6         abc$ = "abc"
              7         print   '<tr>'+                 &
              8                 '<td>'; abc$ ;'</td>'+ &
              9                 '<td>'; abc$ ;'</td>'+ &
             10                 '<td>'; abc$ ;'</td>'+ &
             11                 '<td>'; abc$ ;'</td>'+ &
             12                 '<td>'; abc$ ;'</td>'+ &
             13                 '</tr>'
             14 1040    end


NEIL5$MAIN                      Source Listing                  27-OCT-2013 10:12:01  Alpha BASIC V1.7-001              Page 2
                                Allocation Map                  27-OCT-2013 09:37:13  CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2




Allocation information for main program NEIL5$MAIN  Offset based on (FP)


Name                               Offset    Size      Type

ABC$                               -8        8         Dynamic string


PROGRAM SECTIONS

    Name                                Bytes Attributes

0   $READ_ONLY$                         132     PIC CON REL LCL   SHR NOEXE   RD NOWRT OCTA
1   $CODE$                              552     PIC CON REL LCL   SHR   EXE NORD NOWRT OCTA
2   $LINK$                              216   NOPIC CON REL LCL NOSHR NOEXE   RD NOWRT OCTA
3   $LITERAL$                                   PIC CON REL LCL   SHR NOEXE   RD NOWRT OCTA
4   $ARRAY                              0     NOPIC CON REL LCL NOSHR NOEXE   RD   WRT OCTA
5   $DESC                               0     NOPIC CON REL LCL NOSHR NOEXE   RD   WRT OCTA


NEIL5$MAIN                      Source Listing                  27-OCT-2013 10:12:01  Alpha BASIC V1.7-001              Page 3
                                Qualifier Summary               27-OCT-2013 09:37:13  CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2

BASIC/REAL_SIZE=DOUBLE/INTEGER_SIZE=LONG/OPTIM=LEVEL=4/LIST/MACHINE NEIL5.BAS

DEFAULT DATA TYPE INFORMATION:           LISTING FILE INFORMATION INCLUDES:     
    Data type : EXPLICIT                       List                             
    Real size : DOUBLE                      NO Cross reference                  
    Integer size : LONG                        CDD Definitions                  
    Decimal size : (15,2)                      Environment                      
    Scale factor : 0                        NO Override of %NOLIST              
    NO Round decimal numbers                   Machine code                     
                                               Map                              
COMPILATION QUALIFIERS IN EFFECT:              INCLUDE files                    
       Object file                                                              
    NO Separate_compilation              FLAGGERS:                              
    NO Line                                 NO Declining features               
       Variant : 0                                                              
       Warnings                          DEBUG INFORMATION:                     
       Informationals                          Traceback records                
    NO Alignment warnings                   NO Debug symbol records             
    NO Diagnostics                                                              
    NO Audit                             OPTIMIZE SETTINGS:                     
    NO Analysis data                           Level : 4                        
    NO Placeholders                            Tune  : GENERIC                  
    NO Comments                                Architecture : GENERIC           
       Old Version : NO CDD Arrays             Overflow check integers          
    NO Dependency data                         Overflow check decimal numbers   
    NO TIE                                     Bounds checking                  
                                            NO Synchronous exceptions           


NEIL5$MAIN                      Machine Code Listing            27-OCT-2013 10:12:01  Alpha BASIC V1.7-001              Page 4
                                NEIL5$MAIN                      27-OCT-2013 09:37:13  CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2

                                .PSECT  $CODE$, OCTA, PIC, CON, REL, LCL, SHR,-
                                        EXE, NORD, NOWRT
             0000       NEIL5$MAIN::
23DEFF00     0000               LDA     SP, -256(SP)
A63B0050     0004               LDQ     R17, 80(R27)
47E05419     0008               MOV     2, R25
B75E00E0     000C               STQ     R26, 224(SP)
B77E0000     0010               STQ     R27, (SP)
A75BFFD0     0014               LDQ     R26, -48(R27)
B7FE0008     0018               STQ     R31, 8(SP)
B45E00E8     001C               STQ     R2, 232(SP)
B47E00F0     0020               STQ     R3, 240(SP)
B7BE00F8     0024               STQ     FP, 248(SP)
63FF0000     0028               TRAPB
47FE041D     002C               MOV     SP, FP
23DEFFF0     0030               LDA     SP, -16(SP)
47FB0402     0034               MOV     R27, R2
221D0008     0038               LDA     R16, 8(FP)
A762FFD8     003C               LDQ     R27, -40(R2)
6B5A4000     0040               JSR     R26, DBASIC$INIT                        ; R26, R26
A7420040     0044               LDQ     R26, 64(R2)                                                                         ; 000006
261F010E     0048               LDAH    R16, 270(R31)
404B1000     004C               ADDL    R2, 88, R0
223D00A8     0050               LDA     R17, 168(FP)
B01D00AC     0054               STL     R0, 172(FP)
47E05419     0058               MOV     2, R25
22100003     005C               LDA     R16, 3(R16)
B21D00A8     0060               STL     R16, 168(FP)
221DFFF8     0064               LDA     R16, ABC$                               ; R16, -8(FP)
A7620048     0068               LDQ     R27, 72(R2)
2FFE0000     006C               UNOP
6B5A4000     0070               JSR     R26, STR$COPY_DX                        ; R26, R26
A742FFE0     0074               LDQ     R26, -32(R2)                                                                        ; 000007
47FF0411     0078               CLR     R17
221D0008     007C               LDA     R16, 8(FP)
47E05419     0080               MOV     2, R25
A762FFE8     0084               LDQ     R27, -24(R2)
6B5A4000     0088               JSR     R26, DBASIC$PRINT                       ; R26, R26
A7420030     008C               LDQ     R26, 48(R2)                                                                         ; 000008
261F010E     0090               LDAH    R16, 270(R31)
404E1000     0094               ADDL    R2, 112, R0
47E03419     0098               MOV     1, R25
22100008     009C               LDA     R16, 8(R16)
B01D00B4     00A0               STL     R0, 180(FP)
B21D00B0     00A4               STL     R16, 176(FP)
221D00B0     00A8               LDA     R16, 176(FP)
A7620038     00AC               LDQ     R27, 56(R2)
6B5A4000     00B0               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A7420030     00B4               LDQ     R26, 48(R2)
47E03419     00B8               MOV     1, R25
221DFFF8     00BC               LDA     R16, ABC$                               ; R16, -8(FP)
A7620038     00C0               LDQ     R27, 56(R2)
6B5A4000     00C4               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A7420030     00C8               LDQ     R26, 48(R2)                                                                         ; 000009
247F010E     00CC               LDAH    R3, 270(R31)
40421120     00D0               SUBL    R2, 16, R0
221D00B8     00D4               LDA     R16, 184(FP)


NEIL5$MAIN                      Machine Code Listing            27-OCT-2013 10:12:01  Alpha BASIC V1.7-001              Page 5
                                NEIL5$MAIN                      27-OCT-2013 09:37:13  CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2

B01D00BC     00D8               STL     R0, 188(FP)
20630009     00DC               LDA     R3, 9(R3)
47E03419     00E0               MOV     1, R25
B07D00B8     00E4               STL     R3, 184(FP)
A7620038     00E8               LDQ     R27, 56(R2)
2FFE0000     00EC               UNOP
6B5A4000     00F0               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A7420030     00F4               LDQ     R26, 48(R2)
47E03419     00F8               MOV     1, R25
221DFFF8     00FC               LDA     R16, ABC$                               ; R16, -8(FP)
A7620038     0100               LDQ     R27, 56(R2)
6B5A4000     0104               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A7420030     0108               LDQ     R26, 48(R2)                                                                         ; 000010
40421120     010C               SUBL    R2, 16, R0
47E03419     0110               MOV     1, R25
221D00C0     0114               LDA     R16, 192(FP)
B01D00C4     0118               STL     R0, 196(FP)
B07D00C0     011C               STL     R3, 192(FP)
A7620038     0120               LDQ     R27, 56(R2)
6B5A4000     0124               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A7420030     0128               LDQ     R26, 48(R2)
221DFFF8     012C               LDA     R16, ABC$                               ; R16, -8(FP)
47E03419     0130               MOV     1, R25
A7620038     0134               LDQ     R27, 56(R2)
6B5A4000     0138               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A7420030     013C               LDQ     R26, 48(R2)                                                                         ; 000011
40421120     0140               SUBL    R2, 16, R0
47E03419     0144               MOV     1, R25
221D00C8     0148               LDA     R16, 200(FP)
B01D00CC     014C               STL     R0, 204(FP)
B07D00C8     0150               STL     R3, 200(FP)
A7620038     0154               LDQ     R27, 56(R2)
6B5A4000     0158               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A7420030     015C               LDQ     R26, 48(R2)
47E03419     0160               MOV     1, R25
A7620038     0164               LDQ     R27, 56(R2)
221DFFF8     0168               LDA     R16, ABC$                               ; R16, -8(FP)
2FFE0000     016C               UNOP
6B5A4000     0170               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A7420030     0174               LDQ     R26, 48(R2)                                                                         ; 000012
40421120     0178               SUBL    R2, 16, R0
221D00D0     017C               LDA     R16, 208(FP)
47E03419     0180               MOV     1, R25
B01D00D4     0184               STL     R0, 212(FP)
B07D00D0     0188               STL     R3, 208(FP)
A7620038     018C               LDQ     R27, 56(R2)
6B5A4000     0190               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A7420030     0194               LDQ     R26, 48(R2)
47E03419     0198               MOV     1, R25
221DFFF8     019C               LDA     R16, ABC$                               ; R16, -8(FP)
A7620038     01A0               LDQ     R27, 56(R2)
6B5A4000     01A4               JSR     R26, DBASIC$OUT_T_DX_S                  ; R26, R26
A742FFC0     01A8               LDQ     R26, -64(R2)                                                                        ; 000013
243F010E     01AC               LDAH    R1, 270(R31)
404A1123     01B0               SUBL    R2, 80, R3
221D00D8     01B4               LDA     R16, 216(FP)
B07D00DC     01B8               STL     R3, 220(FP)


NEIL5$MAIN                      Machine Code Listing            27-OCT-2013 10:12:01  Alpha BASIC V1.7-001              Page 6
                                NEIL5$MAIN                      27-OCT-2013 09:37:13  CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2

2021000A     01BC               LDA     R1, 10(R1)
47E03419     01C0               MOV     1, R25
B03D00D8     01C4               STL     R1, 216(FP)
A762FFC8     01C8               LDQ     R27, -56(R2)
2FFE0000     01CC               UNOP
6B5A4000     01D0               JSR     R26, DBASIC$OUT_T_DX_B                  ; R26, R26
A7420060     01D4               LDQ     R26, 96(R2)
47E03419     01D8               MOV     1, R25
221D0008     01DC               LDA     R16, 8(FP)
A7620068     01E0               LDQ     R27, 104(R2)
6B5A4000     01E4               JSR     R26, DBASIC$IO_END                      ; R26, R26
             01E8       L$2:                                                                                                ; 000014
A742FFA0     01E8               LDQ     R26, -96(R2)
221D0008     01EC               LDA     R16, 8(FP)
63FF0000     01F0               TRAPB
47E03419     01F4               MOV     1, R25
A762FFA8     01F8               LDQ     R27, -88(R2)
2FFE0000     01FC               UNOP
6B5A4000     0200               JSR     R26, DBASIC$END                         ; R26, R26
63FF0000     0204               TRAPB                                                                                       ; 000001
47FD041E     0208               MOV     FP, SP
A75D00E0     020C               LDQ     R26, 224(FP)
A45D00E8     0210               LDQ     R2, 232(FP)
47E03400     0214               MOV     1, R0                                                                               ; 000014
A47D00F0     0218               LDQ     R3, 240(FP)                                                                         ; 000001
A7BD00F8     021C               LDQ     FP, 248(FP)
23DE0100     0220               LDA     SP, 256(SP)
6BFA8001     0224               RET     R26

Routine Size: 552 bytes,    Routine Base: $CODE$ + 0000


                                .PSECT  $LINK$, OCTA, NOPIC, CON, REL, LCL,-
                                        NOSHR, NOEXE, RD, NOWRT
             0000               .LINKAGE DBASIC$END
64742F3C     0010               .ASCII  \</td></tr>\
742F3C3E     0014
    3E72     0018

             0020               .LINKAGE DBASIC$OUT_T_DX_B
             0030               .LINKAGE DBASIC$INIT
             0040               .LINKAGE DBASIC$PRINT
64742F3C     0050               .ASCII  \</td><td>\
64743C3E     0054
      3E     0058


             0060               ; Stack-Frame invocation descriptor
                                Entry point:           NEIL5$MAIN
                                Entry Length:          48
                                Static Handler:        DBASIC$HANDLER
                                Registers used:        R0-R3, R16-R17, R25-R26, R28-FP
                                Registers saved:       R2-R3, FP
                                Fixed Stack Size:      256
00000000                        ; Handler data for DBASIC$HANDLER
00000000
00000000


NEIL5$MAIN                      Machine Code Listing            27-OCT-2013 10:12:01  Alpha BASIC V1.7-001              Page 7
                                NEIL5$MAIN                      27-OCT-2013 09:37:13  CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2

00000000

             0090               .LINKAGE DBASIC$OUT_T_DX_S
             00A0               .LINKAGE STR$COPY_DX
00000000     00B0               .ADDRESS $READ_ONLY$
  636261     00B8               .ASCII  \abc\

             00C0               .LINKAGE DBASIC$IO_END
3E72743C     00D0               .ASCII  \<tr><td>\
3E64743C     00D4


                                .PSECT  $READ_ONLY$, OCTA, PIC, CON, REL, LCL,-
                                        SHR, NOEXE, RD, NOWRT
                        $$1:
00000008     0000               .LONG   X^8 , - ; .LONG 8
00000001     0004               .LONG   X^1 , - ; .LONG 1
00000000     0008               .LONG   X^0 , - ; .LONG 0
00000000     000C               .LONG   X^0 , - ; .LONG 0
000000B8     0010               .LONG   X^B8 , - ; .LONG 184
00000000     0014               .LONG   X^0 , - ; .LONG 0
0000007C     0018               .LONG   X^7C , - ; .LONG 124
00000084     001C               .LONG   X^84 , - ; .LONG 132
00000084     0020               .LONG   X^84 , - ; .LONG 132
00000084     0024               .LONG   X^84 , - ; .LONG 132
00000000     0028               .LONG   X^0 , - ; .LONG 0
00000000     002C               .LONG   X^0 , - ; .LONG 0
00000084     0030               .LONG   X^84 , - ; .LONG 132
00000000     0034               .LONG   X^0 , - ; .LONG 0
00000000     0038               .LONG   X^0 , - ; .LONG 0
00000000     003C               .LONG   X^0 , - ; .LONG 0
00000000     0040               .LONG   X^0 , - ; .LONG 0
FFFFFFF8     0044               .LONG   X^FFFFFFF8 , - ; .LONG -8
00000000     0048               .LONG   X^0 , - ; .LONG 0
FFFFFFF0     004C               .LONG   X^FFFFFFF0 , - ; .LONG -16
00000001     0050               .LONG   X^1 , - ; .LONG 1
00000000     0054               .LONG   X^0 , - ; .LONG 0
00000000     0058               .LONG   X^0 , - ; .LONG 0
00000000     005C               .LONG   X^0 , - ; .LONG 0
00000000     0060               .LONG   X^0 , - ; .LONG 0
00004080     0064               .LONG   X^4080 , - ; .LONG 16512
00000000     0068               .LONG   X^0 , - ; .LONG 0
00000000     006C               .LONG   X^0 , - ; .LONG 0
00000000     0070               .LONG   X^0 , - ; .LONG 0
00000000     0074               .LONG   X^0 , - ; .LONG 0
00000000     0078               .LONG   X^0 ; .LONG 0
                        $$2:
      05     007C               .SIGNED_BYTE X^5 ; .SIGNED_BYTE 5
4C49454E     007D               .ASCII  \NEIL5\
      35     0081

One Stub for the Web (observe via VMS accounting)

neil5_www.bas

Note: The resulting executable can be run directly by Apache. Just drop it in [.scripts] or [.cgi-bin]

1000    ! Neil Rieck
	declare string constant k_program = "neil5_www.bas"
	declare string  abc$    ,&
                long    i%
	abc$ = "abc"
	margin #0, 1999888777			!
	print 'status: 200'			! http status code
	print 'content-type: text/html'		! 
	print					! end of http block
	print '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"'
	print '  "http://www.w3.org/TR/html4/strict.dtd">'
	print '<html>'
	print '<head><title>'+ k_program +'</title></head>'
	print '<meta content="text/html; charset=windows-1252" http-equiv="Content-Type">'
	print '<body>'
	print '<p>'+ k_program +'</p>'
	print '<table>'
	for i% = 1 to 2000
	  print	'<tr>'		     + &
        	'<td>'; abc$ ;'</td>'+ &
        	'<td>'; abc$ ;'</td>'+ &
        	'<td>'; abc$ ;'</td>'+ &
        	'<td>'; abc$ ;'</td>'+ &
        	'<td>'; abc$ ;'</td>'+ &
        	'</tr>'
	next i%
	print '</table>'
	print '</body>'
	print '</html>'
	end

Links:


Back to Home
Neil Rieck
Waterloo, Ontario, Canada.