How to calculate total TSR block size from multiple .asm files?

After 23 years since the last time I did something in the assembly, I am now writing the DOS TSR program just for fun.

I had a rather large source file, and I decided to split it into smaller .asm files. The problem is that I am having problems calculating the size of the TSR block. With one .asm file, I just did something like:

mov ax, offset end_of_code_label - offset start_of_code_label

but now that I have parts of the code scattered across multiple source files, this approach will not work.

I found that playing with the linker will help by manually specifying the order of the links and making sure that the last .obj file is the one that has "end_of_code_label".

Is there an elegant way to do this, or at least something that wouldn't be considered an ugly hack?

+4
source share
1 answer

The easiest way to control the order of things is to put everything in segments, depending on where they should be in the final program, and then use the assembly template file, which you link first to arrange the segments. By default, the linker arranges the segments in the order in which they occur, so if you have all the segments used in your program in the first file, then it sees that this file determines the order of the segments.

, TSR COM , , . . .

:

    EXTERN  init_start:NEAR
    PUBLIC  resident_end

PSPSEG  GROUP   RTEXT, REND, ITEXT

RTEXT   SEGMENT PUBLIC PARA 'RESIDENT'
    ORG 100h
start:
    jmp init_start
RTEXT   ENDS

REND    SEGMENT PUBLIC BYTE 'REND'
resident_end:
REND    ENDS

ITEXT   SEGMENT PUBLIC BYTE 'INIT'
ITEXT   ENDS

    END start

RTEXT ITEXT, . resident_end , , , .

GROUP , , RTEXT, REND ITEXT . , , PSPSEG, , . , GROUP , , .

COM , , . EXE, , RTEXT END END start. END .

TSR, :

    EXTERN  resident_end:NEAR
    PUBLIC  init_start

PSPSEG  GROUP   RTEXT, ITEXT

RTEXT   SEGMENT PUBLIC PARA 'RESIDENT'
    ASSUME  DS:NOTHING, SS:NOTHING, CS:PSPSEG
old_handler DD 0cccccccch
interrupt_handler:
    jmp [old_handler]
RTEXT   ENDS

ITEXT   SEGMENT PUBLIC BYTE 'INIT'
    ASSUME  DS:PSPSEG, SS:PSPSEG, CS:PSPSEG
init_start:
    mov ax, 3508h
    int 21h        ; get old timer interrupt handler
    mov WORD PTR [old_handler], bx
    mov WORD PTR [old_handler + 1], es
    mov dx, OFFSET interrupt_handler
    mov ax, 2508
    int 21h        ; set new timer interrupt handler

    mov ax, 3100h
    mov dx, OFFSET resident_end + 15
    shr dx, 4
    int 21h        ; terminate and stay resident
ITEXT   ENDS

    END

GROUP , , . ( ) MASM, TASM, PSPSEG , OFFSET. mov dx, OFFSET PSPSEG:interrupt_handler.

+3

Source: https://habr.com/ru/post/1692558/


All Articles