Помощь в написании программ TSR в сборке NASM для DOS - PullRequest
8 голосов
/ 28 июля 2011

Я пытался написать программы TSR (Terminate-Stay-Resident) (в общем) на ассемблере (16-битный) для MS-DOS. Я прочитал страницу Википедии на TSR, а также на странице, посвященной его использованию в DOS (но, похоже, он преподает это на C, а не на ассемблере напрямую). Я посмотрел сайт с тоннами документации по прерываниям DOS и обнаружил этот , этот , а также другой наиболее актуальный для программ TSR. Я не могу опубликовать все ссылки, потому что, будучи новым пользователем, я могу иметь до 2 гиперссылок на сообщение.

Итак, я попытался написать (казалось бы) очень простую программу TSR в плоской модели реального режима (формат файла .COM) в NASM. Вот код:

[BITS 16]
[ORG 0x0100]

[SECTION .text]

Start:
; Get current interrupt handler for INT 21h
mov AX,3521h                ; DOS function 35h GET INTERRUPT VECTOR for interrupt 21h
int 21h                     ; Call DOS  (Current interrupt handler returned in ES:BX)

mov WORD [v21HandlerSegment],ES     ; Store the current INT 21h handler segment
mov WORD [v21HandlerOffset],BX      ; Store the current INT 21h handler offset

; Write new interrupt handler for INT 21h
mov AX,2521h                ; DOS function 25h SET INTERRUPT VECTOR for interrupt 21h
mov DX,TSRStart             ; Load DX with the offset address of the start of this TSR program
;   DS already contains the segment address, it is the same as CS in this .COM file
int 21h                     ; Override the INT 21h handler with this TSR program

; The TSR program will be called even when this portion uses INT 21h to terminate and stay resident
mov AX,3100h                ; DOS function TSR, return code 00h
mov DX,00FFh                ; I don't know how many paragraphs to keep resident, so keep a bunch
int 21h                     ; Call our own TSR program first, then call DOS

TSRStart:
push WORD [v21HandlerSegment]       ; Push the far address of the original 
push WORD [v21HandlerOffset]        ;   INT 21h handler onto the stack
retf                                ; Jump to it!


[SECTION .data]
v21HandlerSegment dw 0000h
v21HandlerOffset  dw 0000h

Когда я собираю это и выполняю в DOS, вместо возврата к приглашению DOS система зависает (никаких действий не происходит, за исключением того, что аппаратный курсор просто мигает ниже последнего приглашения). Я предполагаю, что мусор памяти может выполняться, но вы понимаете, в чем дело.

Может ли кто-нибудь помочь разобраться, в чем проблема с этим кодом, и / или дать общий совет по кодированию TSR в DOS? Заранее спасибо, любая помощь очень ценится!

1 Ответ

4 голосов
/ 29 июля 2011

Я понял это. Посмотрев еще пару источников, я обнаружил, что этот код:

push WORD [v21HandlerSegment]       ; Push the far address of the original 
push WORD [v21HandlerOffset]        ;   INT 21h handler onto the stack

должно быть примерно так:

push WORD [CS:v21HandlerSegment]       ; Push the far address of the original 
push WORD [CS:v21HandlerOffset]        ;   INT 21h handler onto the stack

потому что эти ссылки на память ссылаются на сегмент данных, который не настроен из вызывающей стороны TSR. Так что в основном я ссылался на данные из другого блока данных ...

Этого также можно добиться, поместив CS в DS (а затем вернув исходное значение DS) следующим образом:

push DS
push CS
pop DS
; Memory references....
pop DS
...