; > UnixRT11.mac ; ; Hello World runnable on Unix and RT-11 ; ; This demonstrates code loadable and runnable on both RT-11 and Unix, ; extracting out platform-specific code from the platform-neutral code. ; Based on code by Ian (paramucho) posted on alt.sys.pdp11, 02-Sep-2013. ; ORG 0 ; Position independent code ; Unix header at &0000-&000F (&o0000 to &o0017) ; --------------------------------------------- .word &0107 ; Magic number &o000407, also branch to UxStart .word CodeEnd-UxStart ; size of text .word DataEnd-CodeEnd ; size of initialised data .word ObjectEnd-DataEnd ; size of uninitialised data .word &0000 ; size of symbol data .word &0000 ; entry point .word &0000 ; not used .word &0001 ; no relocation info ; Unix code loads to &o0000 from here, but RT-11 code will be in memory ; at &o0020 here. We can't use ORG 0 for Unix as it throws RT-11 labels ; off. Simplest solution is to ensure we write position-independent code ; and code to subtract 16 from absolute Unix references. ; Unix entry point at &0010 (&o0020) loaded to &0000 ; -------------------------------------------------- UxStart: mov #1,SV_OSFLAG ; Set to 'Unix' jmp Main ; RT-11 startup info at &0020 (&o0040) ; ------------------------------------ .align 32 ; Pad to &o40 .word RtEntry ; RT-11 entry point .word RtStackTop ; RT-11 top of stack .word &0000 ; Job Status Word .word &0000 ; USR swap address .word ObjectEnd ; Program high memory limit .blkb &F0-$ ; Pad to bitmap .byte %11000000 ; First two 512-byte blocks used .byte %00000000 .align &100 ; Pad to end of bitmap ; This area not loaded by RT-11. It is often used as the default stack. ; Unix code could go here. .align &200 ; Pad to end of RT-11 header ; RT-11 entry point at &0100 (&o0400) ; ----------------------------------- RtEntry: mov #2,SV_OSFLAG ; Set to 'RT-11' br Main ; Main platform-neutral code ; ========================== Main: adr msgHello,r1 ; R1=>"Hello world" jsr pc,IO_WrString ; Write z-string to TTY jsr pc,IO_Exit ; And quit. halt msgHello: .ascii "Hello world!" .byte 10,13,0 .even ; =================================================================== ; General I/O that calls more primitive functions ; ----------------------------------------------- ; Write a string to TTY ; --------------------- IO_WrStrLp: jsr pc,IO_WRCH IO_WrString: ; R1=>ASCIZ string movb (r1)+,r0 bne IO_WrStrLp rts pc ; Low-level platform-neutral interface to host ; ============================================ ; Write a character to TTY ; ------------------------ IO_WRCH: ; R0=character to write bit #1,SV_OSFLAG bne UX_WRCH bit #2,SV_OSFLAG bne RT_WRCH rts pc UX_WRCH: mov r0,SV_BUF ; Store char in buffer mov #0,r0 ; r0=stdout trap 4 ; write() .word SV_BUF-16 ; address=buffer-UxStart .word 1 ; count=1 rts pc RT_WRCH: emt 225 ; ttyout bcs RT_WRCH ; loop until done rts pc ; Exit current program ; -------------------- IO_Exit: bit #1,SV_OSFLAG bne UX_Exit bit #2,SV_OSFLAG bne RT_Exit rts pc UX_Exit: trap 1 rts pc RT_Exit: emt 232 rts pc CodeEnd: ; End of code for Unix header DataEnd: ; End of initialised data for Unix header SV_OSFLAG: .word 0 ; b0=Unix, b1=RT-11 SV_BUF: .word 0 ; Workspace for IO calls .word 0 .word 0 ObjectEnd: ; End of entire object RtStackTop: equ ObjectEnd+256 ; RT-11 stack