; Public Domain %include "lmacros3.mac" numdef DOSEXIT, 0 numdef DOSENTRY, 0 numdef LARGEFILL, 0 numdef RELOC, 1 numdef BASESEGMENT, 0 numdef RELOCEXE, 0 cpu 8086 %if _RELOCEXE %assign ORIGIN 0 org ORIGIN addsection HEADER, start=0 header_start: db "MZ" ; exeSignature FILESIZE equ fromparas(header_size_p + BEHINDSEGMENT) dw FILESIZE % 512 ; exeExtraBytes dw (FILESIZE + 511) / 512 ; exePages dw relocationtable.amount ; exeRelocItems dw header_size_p ; exeHeaderSize dw paras(512) ; exeMinAlloc dw paras(512) ; exeMaxAlloc dw +BEHINDSEGMENT ; exeInitSS dw 512 ; exeInitSP dw 0 ; exeChecksum dw 0, +0 ; exeInitCSIP dw relocationtable ; exeRelocTable addsection FIRST, vstart=0 align=16 follows=HEADER %elif _DOSENTRY %assign ORIGIN 256 org ORIGIN addsection FIRST, start=ORIGIN %else %assign ORIGIN 0 org ORIGIN addsection FIRST, start=ORIGIN %endif first_start: addsection SECOND, vstart=0 align=16 follows=FIRST second_start: addsection THIRD, vstart=0 align=16 follows=SECOND third_start: first_size equ first_end - first_start endarea first, 1 second_size equ second_end - second_start endarea second, 1 third_size equ third_end - third_start endarea third, 1 %if _RELOCEXE header_size equ header_end - header_start endarea header, 1 %endif FIRSTSEGMENT equ _BASESEGMENT + 0 SECONDSEGMENT equ _BASESEGMENT + paras(ORIGIN) + first_size_p THIRDSEGMENT equ _BASESEGMENT + paras(ORIGIN) + first_size_p + second_size_p BEHINDSEGMENT equ _BASESEGMENT + paras(ORIGIN) + first_size_p + second_size_p + third_size_p %define RELOCATIONFROMFIRST "" %define RELOCATIONFROMSECOND "" %define RELOCATIONFROMTHIRD "" %imacro relocation 0-1.nolist -2 %%reloc equ $ + %1 %ifidn _CURRENT_SECTION, FIRST %xdefine RELOCATIONFROMFIRST RELOCATIONFROMFIRST, %%reloc, FIRSTSEGMENT %elifidn _CURRENT_SECTION, SECOND %xdefine RELOCATIONFROMSECOND RELOCATIONFROMSECOND, %%reloc, SECONDSEGMENT %elifidn _CURRENT_SECTION, THIRD %xdefine RELOCATIONFROMTHIRD RELOCATIONFROMTHIRD, %%reloc, THIRDSEGMENT %else %error Unknown section for relocation %endif %endmacro usesection FIRST start: mov dx, cs mov ds, dx %if !_RELOCEXE && _RELOC mov si, relocationtable mov cx, relocationtable.amount jcxz .noreloc @@: lodsw xchg bx, ax lodsw add ax, dx mov es, ax add word [es:bx], dx loop @B .noreloc: %endif displayfirst: mov si, firstmsg mov bx, 7 mov ah, 0Eh db __TEST_IMM16 ; (skip int 10h) @@: int 10h lodsb test al, al jnz @B call SECONDSEGMENT:secondentry relocation exit: %if _DOSEXIT mov ax, 4C00h int 21h %else xor ax, ax int 16h int 19h %endif bouncetothird: jmp THIRDSEGMENT:bounced relocation firstmsg: asciz "Hello from first!",13,10 usesection SECOND secondmsg: asciz "Hello from second!",13,10 secondentry: displaysecond: mov si, secondmsg mov bx, 7 mov ah, 0Eh db __TEST_IMM16 ; (skip int 10h) @@: int 10h cs lodsb test al, al jnz @B jmp THIRDSEGMENT:thirdentry relocation usesection THIRD align 2, db 0 indirect_to_bounce: dw bouncetothird relocation 0 dw FIRSTSEGMENT thirdmsg: asciz "Hello from third!",13,10 thirdentry: jmp far [cs:indirect_to_bounce] bounced: displaythird: mov si, thirdmsg mov bx, 7 mov ah, 0Eh db __TEST_IMM16 ; (skip int 10h) @@: int 10h cs lodsb test al, al jnz @B retf %ifn _RELOCEXE usesection FIRST %else usesection HEADER %endif %if _RELOCEXE || _RELOC align 4, db 0 relocationtable: .: dw RELOCATIONFROMFIRST dw RELOCATIONFROMSECOND dw RELOCATIONFROMTHIRD .end: .amount: equ (.end - .) / 4 %endif %if _RELOCEXE align 16 header_end: %endif %if _LARGEFILL usesection SECOND _fill fromkib(64), 0CCh, second_start %endif usesection FIRST align 16 first_end: usesection SECOND align 16 second_end: usesection THIRD align 16 third_end: