Hi
I want this programm resident in to memory and be active With a key in other Programs
Mouse_IN proc near
mov al,4
mov bh,0
int 10h
mov bh,0
mov bl,1001b
mov ah,0Bh
int 10h
mov ax,0
int 33h
mov ax,01h
int 33h
lable1:
mov ah,10h
int 16h
cmp ah,50h ;DownArrow key
je lable2
cmp ah,4Dh ;RightArrow key
je lable3
cmp ah,4Bh ;LeftArrow key
je lable4
cmp ah,48h ;upArrow key
jne test_something_else
; Moved up
mov ax,03h
int 33h
dec dx
mov ax,04h
int 33h
cmp dx,0
jne lable1
lable2:; Moved Down
mov ax,03h
int 33h
inc dx
mov ax,04h
int 33h
cmp dx,184
jne lable1
lable3:; Moved right
mov ax,03h
int 33h
inc cx
mov ax,04h
int 33h
cmp dx,0
jne lable1
lable4:; Moved left
mov ax,03h
int 33h
dec cx
mov ax,04h
int 33h
cmp dx,305
jne lable1
test_something_else:
;------------ end of program
mov ax, 4c00h
int 21h
iret
Mouse_IN endp
How do I add the key؟
.model small
.stack
.code
start:
; mov ax, datasg
; mov ds, ax
;------------ ur programm
mov al,3
mov bh,0
int 10h
; set es to "0000":
mov ax, 0
mov es, ax
; calculate vector address for interrupt 100h:
mov ah,35
mov al,100
int 21h
mov ah,25h
mov al,100
mov dx,offset Mouse_IN
int 21h
mov ah,31h
mov dx,60h
int 21h
; copy segment into interrupt vector:
mov ax, cs
mov es:[bx], ax
int 100 ; test newly created interrupt.
; jmp loop1
Mouse_IN proc near
mov al,4
mov bh,0
int 10h
mov bh,0
mov bl,1001b
mov ah,0Bh
int 10h
mov ax,0
int 33h
mov ax,01h
int 33h
lable1:
mov ah,10h
int 16h
cmp ah,50h ;DownArrow key
je lable2
cmp ah,4Dh ;RightArrow key
je lable3
cmp ah,4Bh ;LeftArrow key
je lable4
cmp ah,48h ;upArrow key
jne test_something_else
; Moved up
mov ax,03h
int 33h
dec dx
mov ax,04h
int 33h
cmp dx,0
jne lable1
lable2:; Moved Down
mov ax,03h
int 33h
inc dx
mov ax,04h
int 33h
cmp dx,184
jne lable1
lable3:; Moved right
mov ax,03h
int 33h
inc cx
mov ax,04h
int 33h
cmp dx,0
jne lable1
lable4:; Moved left
mov ax,03h
int 33h
dec cx
mov ax,04h
int 33h
cmp dx,305
jne lable1
test_something_else:
;------------ end of program
mov ax, 4c00h
int 21h
iret
Mouse_IN endp
end start
what you are talking about is a DOS concept that is obsolete
they were called TSR's - for Terminate and Stay Resident
there are a few approaches to this, the simplest is to run a program and "terminate" with INT 27h
you set the DX register to the address of the last byte to be resident (+1) and executed INT 27h
the CS register had to be in the PSP segment, as i recall
so, most TSR's were executed as .COM programs - not .EXE's
an updated function, INT 21h, function 31h replaced INT 27h, but the old method was still used a lot
another method was to install the program in config.sys as a .SYS device driver
i haven't tried this in a win32 environment, nor do i care to - lol
but, i suspect the program will only remain resident for the life of the console window under which it was opened
under win32, you would use a completely different approach
something along the line of a Native Service would be the "right" way to do it
a simpler method might be to run a hidden window, message-only window, or something similar
it depends on what you want to accomplish
Hi majid1605,
Dave is exactly right: don't waste your time with writing obsolete 16 bit DOS programs. DOS was a Real Mode operating system, while the modern operating systems (Windows, UNIX, MacOS etc.) are using the Protected Mode. That's another approach.
You should download the MASM32 package, reading the extensive documentation and trying the hole bunch of examples. That will lead you in the right direction and is much more fun.
Gunther
deleted
Thanks for your tips. :t
I know that this method is outdated .but i need to use the DOS programming in DosBox :( .And the program should have the following features:
1- memory resident
2-be active With a key in other Programs.For Example F1
I mean if another program press the F key, mouse program be run
Quote from: dedndave on January 12, 2013, 03:49:01 AM
what you are talking about is a DOS concept that is obsolete
Well, under DOS it is NOT obsolete.
Quote
but, i suspect the program will only remain resident for the life of the console window under which it was opened
Yes, correct guess.
Quote
under win32, you would use a completely different approach
something along the line of a Native Service would be the "right" way to do it
a simpler method might be to run a hidden window, message-only window, or something similar
Pretty off-topic. The post is in the DOS forum, so why do you propose a boring Windows approach?
Scheiße - where's my iggy button
Hi japheth,
Quote from: japheth on January 12, 2013, 07:05:06 AM
Well, under DOS it is NOT obsolete.
under DOS is it not obsolete. The question is: is a single tasking OS state of the art?
Gunther
Quote from: Gunther on January 12, 2013, 08:01:49 AM
under DOS is it not obsolete. The question is: is a single tasking OS state of the art?
IMO the level of modernity of DOS is NOT AT ALL the question. If I may use your words: the question is: has DOS still a purpose today?
And the answer to this question definitely is: yes. At least for those people who are interested in assembly language and want to use or play with privileged instructions or talk directly to the hardware. Because DOS is by far the simplest platform to do exactly these things.
From this MY point of view it's more "obsolete" to code a Win32 desktop applications in assembly language ( and using the native Win32 API ) than to code a DOS TSR.
deleted
Quote from: nidud on January 12, 2013, 08:50:07 AM
The minimum for a TSR is around 1000 lines of code, so it is somewhat extensive
Hi,
In response to some people having specific problems
I have written small TSR's. I can't find the smallest,
but one has 125 lines of code. Assembles to 218 bytes.
That was to fix a clock problem. The smallest was to
fix a Y2K problem.
Cheers,
Steve N.
Here is some shorter code for a TSR. It's Tasm, but easily converted to Masm.
It works under cmd in XP.
I noticed your code seemed to mess with the command buffer.
I have a lot of other 16 bit code that you might could use.
; saver.asm Com program Modified 6/13/2002
;
; Screen saver (blanks screen) COM file..
; Only works in 80x25 screen modes (2,3,7) [could easily be adapted/others]
; Uses F-8 key to activate, un-install by typing name of program again
;
; **** ADJUSTABLE time interval to pop up
;
; Program can be uninstalled
;
;
.SEQ ; store segment sequentially as they appear
.286 ; use 80286+ code
.MODEL tiny ; TINY model to make it a .COM program
;* Macros *
StAlloc MACRO sizew ; macro to allocate stack, size "sizew" words
MOV BX,((sizew*2)+15) SHR 4 ; BX = size in paragraphs
MOV AH,48h ; allocate memory function
INT 21h ; call DOS
CLI ; freeze interrupts
MOV SS,AX ; set stack segment to allocated segment returned in AX
MOV SP,sizew*2-2 ; set stack pointer to end of segment (goes top down)
STI ; restore interrupts
ENDM
StDeAlloc MACRO ; macro to deallocate stack
MOV AX,SS
MOV ES,AX
MOV AH,49h ; call DOS deallocate block function
INT 21h
ENDM
;* Code Segment *
code SEGMENT PARA PUBLIC 'CODE' ; code segment
ASSUME CS:code, DS:code, ES:code, SS:code ; assume CS->"code" etc.
ORG 100h ; start assembling at offset 0h (default)
;* Program Start *
start: ; label for start of program
JMP init
;* Procedures *
; Save screen and display (init) screen saver logo
ScreenSaver PROC NEAR
MOV AX,CS
MOV ES,AX
MOV DI,OFFSET ScrData
MOV DS,CS:ScrAddress
XOR SI,SI
CLD
MOV CX,2000
REP MOVSW ; save screen
MOV CS:SSOn,1
MOV AH,0Fh
INT 10h ; get current page in BH
MOV AH,03h
INT 10h ; get old cursor size
MOV CS:OldCursor,CX
MOV AH,01h
MOV CX,0100h
INT 10h ; hide cursor
CALL RunSaver ; clear screen
CALL DrawSaver ; draw logo
RET
ENDP
; Restore screen and deinitialize screen saver
RemoveSaver PROC NEAR
MOV ES,CS:ScrAddress
XOR DI,DI
MOV AX,CS
MOV DS,AX
MOV SI,OFFSET ScrData
CLD
MOV CX,2000
REP MOVSW
MOV CS:SSOn,0
MOV AH,01h
MOV CX,CS:OldCursor
INT 10h ; restore cursor
RET
ENDP
; Re-hide screen to cover any writing
RunSaver PROC NEAR
MOV ES,CS:ScrAddress
XOR DI,DI
MOV CX,2000
XOR AX,AX
REP STOSW
RET
ENDP
; Find parts of screen that were changed and save to virtual screen
DeltaSaver PROC NEAR
CLD
MOV DS,CS:ScrAddress
XOR SI,SI ; DS:SI -> physical screen
MOV AX,CS
MOV ES,AX
MOV DI,OFFSET ScrData ; ES:DI -> virtual screen
XOR BH,BH ; row 0
ds_nextrow:
MOV CX,80
CMP BH,CS:Row
JZ ds_check ; if row of copyright string handle separately
ds_loop:
LODSW
CMP AX,0 ; check if still zero (as set by screen saver)
JZ ds_again
MOV ES:[DI],AX ; set to new value
ds_again:
INC DI
INC DI
LOOP ds_loop
ds_new:
INC BH
CMP BH,25
JNZ ds_nextrow
RET
ds_check:
MOV BP,OFFSET Copyright
MOV BL,CS:Color
ds_loop2:
LODSW
CMP AL,ES:[BP]
JNZ ds_delta
CMP AH,BL
JZ ds_ok
ds_delta:
MOV ES:[DI],AX
ds_ok:
INC DI
INC DI
INC BP
LOOP ds_loop2
JMP SHORT ds_new
ENDP
; Draw copyright string
DrawSaver PROC NEAR
MOV AX,WORD PTR CS:Row2
MOV WORD PTR CS:Row,AX ; now safe to copy incremented data
MOV AH,CS:Row
MOV AL,160
MUL AH
MOV DI,AX
MOV AX,CS
MOV DS,AX
MOV SI,OFFSET CS:Copyright
MOV AH,CS:Color
ds_write:
LODSB
OR AL,AL
JZ ds_donemsg
STOSW
JMP SHORT ds_write
ds_donemsg:
RET
ENDP
; move message and change color
IncSaver PROC NEAR
MOV AX,WORD PTR CS:Row2 ; AL = row, AH = attribute
ADD AX,101h ; increment both
CMP AL,25
JNZ is_rowset
XOR AL,AL
is_rowset:
CMP AH,16
JNZ is_colset
MOV AH,1
is_colset:
MOV WORD PTR CS:Row2,AX
RET
ENDP
; INT 09h interrupt handler
; checks for hotkey combinations and deinstalls or activates program if found
Int09Handler PROC FAR
PUSHF
CALL CS:OldInt09 ; call old handler
PUSHA
PUSH DS
PUSH ES
MOV AX,40h
MOV ES,AX
MOV DI,ES:[1Ah]
CMP DI,ES:[1Ch] ; quit if no keys in keyboard buffer
JZ i9_exit
MOV CS:SSTimer,0 ; zero timer for screen saver
CMP CS:SSOn,0
JZ i9_skip
CALL RemoveSaver ; if screen saver active, restore screen
i9_skip:
MOV DI,ES:[DI] ; get key in keyboard buffer
CMP DI,4200h ; check for F8 , zeroes needed after scan code
JNZ i9_exit
PUSH DI
PUSH ES
CALL ScreenSaver ; startup screen saver
POP ES
POP DI
i9_remove:
INC WORD PTR ES:[1Ah]
INC WORD PTR ES:[1Ah] ; remove key from buffer
CMP WORD PTR ES:[1Ah],3Eh
JNZ i9_exit
MOV WORD PTR ES:[1Ah],1Eh ; wrap around if required
i9_exit:
POP ES
POP DS
POPA
IRET
ENDP
; INT 1Ch interrupt handler
; activates screen saver when timeout occurs
Int1CHandler PROC FAR
PUSHF
CALL CS:OldInt1C
PUSHA
PUSH DS
PUSH ES
CMP CS:SSOn,0
JZ i1c_off
CALL DeltaSaver ; store changes to virtual screen
CALL RunSaver ; blank screen
CALL DrawSaver ; draw message or graphic
i1c_off:
MOV AL,CS:Timer1
DEC AL
MOV CS:Timer1,AL
JNZ i1c_exit
MOV AH,18
MOV AL,CS:Timer2
DEC AL
JNZ i1c_not19
INC AH
MOV AL,5
i1c_not19:
MOV CS:Timer2,AL
MOV CS:Timer1,AH
CMP CS:SSOn,0
JZ i1c_count
CALL IncSaver
JMP SHORT i1c_exit
i1c_count:
MOV AX,CS:SSTimer
INC AX
MOV CS:SSTimer,AX
CMP AX,180 ; 3 minutes (min x 60 secs)
JNZ i1c_exit
XOR AX,AX
MOV CS:SSTimer,AX ; set to zero
CALL ScreenSaver ; startup screen saver
i1c_exit:
POP ES
POP DS
POPA
IRET
ENDP
; TSR data
ScrAddress DW 0
OldCursor DW 0
OldInt09 DD 0
OldInt1C DD 0
SSTimer DW 0
SSOn DB 0
Timer1 DB 18
Timer2 DB 5
ScrData DW 2000 DUP (?)
Row DB 0
Color DB 1
Row2 DB 0
Color2 DB 1
Copyright DB 'è The Kennedy Family',0
Sig DB 'VXSS'
TSR_end LABEL BYTE
; * Main Program *
init:
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV BX,OFFSET code_end
ADD BX,15
SHR BX,4
MOV AH,4AH
INT 21H ; free unneeded memory given to program
StAlloc 50h ; allocate stack (saves memory on disk)
XOR AX,AX
MOV ES,AX
PUSH DS
MOV DS,ES:[26h]
CMP WORD PTR DS:Sig,'XV'
JNZ i_skip
CMP WORD PTR DS:Sig+2,'SS'
JNZ i_skip
MOV AX,WORD PTR DS:OldInt09
MOV BX,WORD PTR DS:OldInt09+2
CLI
MOV ES:[24h],AX
MOV ES:[26h],BX
MOV AX,WORD PTR DS:OldInt1C
MOV BX,WORD PTR DS:OldInt1C+2
MOV ES:[70h],AX
MOV ES:[72h],BX
STI
MOV AX,DS
MOV ES,AX
MOV AH,49h
INT 21h
POP DS
MOV AH,09h
MOV DX,OFFSET Deinstall
INT 21h
StDeAlloc
MOV AX,4C00h
INT 21h
i_skip:
POP DS
MOV AX,0B800h
CMP BYTE PTR ES:[0449h],7 ; check if current mode @ 0:449 is 7 (mono)
JNZ i_gotmode
MOV AX,0B000h
i_gotmode:
MOV ScrAddress,AX ; store screen address
MOV AX,ES:[24h]
MOV BX,ES:[26h]
MOV WORD PTR OldInt09,AX
MOV WORD PTR OldInt09+2,BX ; save old interrupt 09h
MOV AX,OFFSET Int09Handler
MOV BX,CS
CLI
MOV ES:[24h],AX
MOV ES:[26h],BX
STI
MOV AX,ES:[70h]
MOV BX,ES:[72h]
MOV WORD PTR OldInt1C,AX
MOV WORD PTR OldInt1C+2,BX ; save old interrupt 1Ch
MOV AX,OFFSET Int1CHandler
MOV BX,CS
CLI
MOV ES:[70h],AX
MOV ES:[72h],BX
STI
MOV AH,49h
MOV ES,CS:[2Ch]
INT 21h ; deallocate environment block
MOV AH,09h
MOV DX,OFFSET Install
INT 21h ; display message
StDeAlloc ; deallocate stack
MOV DX,OFFSET TSR_end
ADD DX,15
SHR DX,4
MOV AX,3100h
INT 21h ; go TSR, exit with errorlevel 0
;* Data Area *
; main program data
Install DB 13,10,'Screen Saver now installed - press F8 to activate.'
DB 13,10,'Type Saver again to un-install.',13,10,10,'$'
Deinstall DB 13,10,'Screen Saver un-installed Ok.',13,10,10,'$'
;* End Program *
code_end LABEL BYTE ; mark end of code segment (end of program)
code ENDS ; end code segment "code"
END start ; end program, start execution at "start:"
Hi japheth,
Quote from: japheth on January 12, 2013, 08:33:39 AM
And the answer to this question definitely is: yes. At least for those people who are interested in assembly language and want to use or play with privileged instructions or talk directly to the hardware. Because DOS is by far the simplest platform to do exactly these things.
no doubts about that. Hardware access is very simple under plain DOS. On the other hand, the memory management (memory above 1 MB) is very complicated under DOS. One has to deal with XMS, EMS and the like. Not the right playground for beginners.
Gunther
Steve,
Could post some of your TSR code ?
Andy
here is a ram drive device driver i wrote long ago
you build it as a TINY model program, then rename it to .SYS
the resident code is 256 bytes :biggrin:
(not including the drive, of course)
detailed instructions are at the end of the source file
this is version 3.0
version 1.0 - i wrote in 1989 :lol:
This is a code sample for resident program
; You may customize this and other start-up templates;
; The location of this template is c:\emu8086\inc\0_com_template.txt
org 100h
TITLE A24TSTNM (CoM) Resident program
BIODATA SEGMENT AT 4OH ;BIOS data aTEA
;ORG 17H
KBSTAT DB ? ;Keyboard 8tatu8 byEe
BIODATA ENDS
;---------------------------------------------------------------------
CODESG SEGMENT PARA
ASSUME CS:CODESG,DS:BIODATA
;ORG 1OOH
BEGIN:
jMP Bl0INIT ;Jump Lo initialization
SAVINT9 DD ? ;INt 09H addresa
AlOTEST:
PUSH AX ;Save regigtere
PUSH CX
PUSH DS
MOv AX,BIODATA ;SegmenE addrese of
MOV DS,AX ; BIOS daEa area
MOV AL,KBSTAT ;Gee keyboard flag
TEST AL,00100000b ;Nurnlock state?
JZ A3oEXIT ;No, exit
mov dx,96
IN AL,dx ;Get keyatroke from port
CMP AL,71 ;Scan code < 71?
JL A3oEXIT ; yea, exiE
CMP AL,83 ;Scan code > 83?
JG A3OEXIT ; yes, exiE,
;Must be from numeric kQlTad
MOV AL,10110110b ;Set frequency
OUT 43H,AL
MOV AX,1000
OUT 42H,AL
MOV AL,AH
OUT 42H,AL
IN AL,61H ;Turn on apeaker
MOV AH,AL
OR AL,03
ouT 61H,AL
MOV CX,9000 ;Set duralion
A2OPAUSE:
LOOP A2OPAUSE
MOV AL,AH ;Turn off speaker
out 61H,AL
A3OEXIT:
POP DS ;Restore regiatera
POP CX
POP AX
JMP CS:SAVINT9 ;Resume INT 09H
; Initializat,ion routine:
Bl0INIT: ; -----------
CLI ;Preven! further inEerruPts
MOV AH,35H ;Get addrees of INT 09H
MOV AL,09H ; in ES:BX
INT 21H
MOv WORD PTR SAVINT9,BX ; and save it
MOv WORD PTR SAVINT9+2,ES
MOV AH,25H
MOV AL,09H ;Set nen addresg for INT 09lt
MOV DX,OFFSET AlOTEST ; in AlOTEST
INT 21H
MOV AH,31H ;Req[ue6t st,ay reEident
MOV DX,OFFSET Bl0INIT ;Set size of resident portion
STI ;ResEore interruptg
INT 21H
CODESG ENDS
END BEGIN
ret
Unfortunately, the masm does not work .This code is written in IBM PC Assembly Language and Programming (1998) :bgrin:
deleted
deleted
Quote from: Magnum on January 12, 2013, 02:46:20 PM
Steve,
Could post some of your TSR code ?
Hi Andy,
Sure. Doing a search turned up the Y2K program.
Mildly editted.
PAGE ,132
TITLE PAST2.ASM
COMMENT |
Based on jw work. and noting pr remarks,
here is a slightly tested version. Probably still too
simple, but it passed tests a) and b) above.
|
; Steve N 17 October 2003
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,ES:NOTHING
ORG 100H ; COM file opening
START:
JMP INSTALL
NOP ; Fill to 104H
WayBackIt:
CMP AH,02AH
JNZ FallThru ; None of our business...
PUSHF ; Emulate an interrupt
CALL DWORD PTR CS:[100H]
SUB CX,0AH ; Fn 2A dosen't care about flags (thank you)
IRET ; Interrupt return (with bogus flags)
FallThru: ; Just let DOS do its thing.
JMP DWORD PTR CS:[100H]
INSTALL:
MOV AL,021H ; Get DOS interrupt vector
MOV AH,035H ; DOS get interrupt vector Fn
INT 21H
MOV WORD PTR DS:[100H],BX
MOV WORD PTR DS:[102H],ES
MOV DX,OFFSET WayBackIt ; Interrupt handler segment in DS, offset in DX.
MOV AH,025H ; DOS set interrupt vector Fn (Don't do by hand).
INT 21H
MOV DX,12H ; Size to Keep (could get fancy, but KISS).
MOV AX,3100H ; DOS Keep program and return code of 0
INT 21H
CODE ENDS
END START
And the clock program. Again names deleted. It looks
like I deleted the debug code at the time, so who knows
what all that was about.
PAGE ,132
TITLE TSR to create synchronize 200LX clocks.
NAME Clocks
COMMENT *
COM file TSR to create synchronize 200LX clocks. Based on
discussions on the HPLX mailing list. N G had a problem
with the BIOS clock being delayed after running 1-2-3 macros.
9-13 February 2005
*
.XCREF
.XLIST
INCLUDE DEFMS.ASM ; System Call MACRO and MS-DOS definitions
DOSF_GETPSP EQU 62H ; Get Program Segment Prefix
.LIST ; from Heath/Zenith software.
.CREF
DEBUG EQU 1 ; should be self-documenting..
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants.
; In a COM program all segments are the same.
.186 ; Should be okay, test for 200LX before installing.
CODE SEGMENT
ORG 100H
ASSUME CS:CODE,DS:NOTHING
START:
JMP INSTALL
OldInt1C DD 0
Counter DW 10920
NewInt1C:
PUSHF
DEC CS:[Counter]
JLE Synch
POPF
JMP DWORD PTR CS:[OldInt1C] ; rejoin timer interrupt chain
Synch:
PUSHA
MOV AH,4BH ; This is the 200LX synch
INT 15H
MOV CS:[Counter],10920 ; reset to ten minutes
POPA
POPF
JMP DWORD PTR CS:[OldInt1C] ; rejoin timer interrupt chain
INSTALL:
ASSUME CS:CODE,DS:CODE
CLD
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Check for 200LX, won't work on anything else.
; Test200:
; Make sure we are on a 100LX family machine.
mov ax,4dd4h
int 15h
cmp bx,'HP' ; HP machine?
jne msg_exit ; No
cmp ch,1 ; palmtop?
jne msg_exit ; No
cmp cl,2 ; later than the 95LX?
jb msg_exit ; No
JMP msg_exit2
msg_exit:
mov dx, offset not100lx_msg
SCALL OUTSTR
MOV AL,1 ; Show error
SCALL EXIT
msg_exit2:
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Get old int 1CH
MOV AL,1CH ; Function 35 interrupt 1C
SCALL GIVEC ; Get Interrupt VECtor
MOV WORD PTR [OldInt1C],BX ; Int 1C is BIOS clock tick
MOV AX,ES ; Returns in ES:BX
MOV WORD PTR [OldInt1C+2],AX
; Store new int 1C
MOV DX,OFFSET NewInt1C ; clock tick service routine
; DS:DX points to new handler
MOV AL,1CH ; Point to NewInt1c
SCALL SIVEC ; Set Interrupt VECtor
; - - -
; Free the environment (similar to Waite Group code {or others}).
SCALL GETPSP
MOV ES,BX ; Set ES to the PSP
XOR AX,AX
XCHG AX,ES:[2CH] ; Zap environment segment in PSP
; and put env seg in AX.
TEST AX,0FFH
JZ Hunh ; Hard to see how this could ever
; happen.
MOV ES,AX ; Point ES to environment.
SCALL DEALLOC ; Free the environment block.
Hunh:
; - - -
; Here we can copy code into the PSP DTA (command line) to
; free up another bunch of bytes.
; - - -
MOV DX,OFFSET MSG
SCALL OUTSTR
MOV AL,0 ; Show no error
MOV DX,13H ; Paragraphs to keep (HEX NOT DECIMAL!)
SCALL KEEPPRC ; Keep process
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Data area for the installation.
MSG DB 'Installed Clock Synch TSR.$'
Not100LX_msg db ' TSR is intended for an HP 100/200LX'
DB ' machine!',13,'$'
CODE ENDS
END START
Hm. Looking at it, it does do one sneaky thing. So may
not be best as an example.
Regards,
Steve N.
Quote from: majid1605 on January 12, 2013, 03:13:49 AM
I want this programm resident in to memory and be active With a key in other Programs
That particular code as it stands, and called in response to a hardware interrupt, is likely to have problems with reentrancy. I'm not sure about the mouse driver but BIOS code is generally not reentrant, so to avoid problems with this you must ensure that any BIOS ISR you call was not executing at the time the user pressed the key that activated the code.
Another problem is that the code is calling a BIOS function that waits for a key to become available.
And another problem is that your code popping up and changing the video mode without preserving/restoring the mode and display buffer contents could present a serious problem for any "other programs".
A better approach would be for your TSR to hook the keyboard hardware interrupt or keyboard intercept and capture the keystrokes from the handler, and use the current video mode and/or preserve/restore the video state (and do this without reentrant BIOS calls).
Quote from: japheth on January 12, 2013, 08:33:39 AM
Quote from: Gunther on January 12, 2013, 08:01:49 AM
under DOS is it not obsolete. The question is: is a single tasking OS state of the art?
IMO the level of modernity of DOS is NOT AT ALL the question. If I may use your words: the question is: has DOS still a purpose today?
And the answer to this question definitely is: yes. At least for those people who are interested in assembly language and want to use or play with privileged instructions or talk directly to the hardware. Because DOS is by far the simplest platform to do exactly these things.
From this MY point of view it's more "obsolete" to code a Win32 desktop applications in assembly language ( and using the native Win32 API ) than to code a DOS TSR.
http://en.wikipedia.org/wiki/DOS#DOS_under_OS.2F2_and_Windows
http://en.wikipedia.org/wiki/BIOS#Overclocking
If you think about it, there really is no such thing as any multitasking O.S.
I stand corrected. I just found this. I would like to try it. :t
In the mid-1980s Microsoft developed a multitasking version of DOS.[5][6] This version of DOS is generally referred to as "European MS-DOS 4" because it was developed for ICL and licensed to several European companies. It was never released to the general public or any other OEMs. This version of DOS supports preemptive multitasking, shared memory, device helper services and New Executable ("NE") format executables. None of these features were used in later versions of DOS but they were used to form the basis of the OS/2 1.0 kernel. This version of DOS is distinct from the widely released PC DOS 4.0 which was developed by IBM and based upon DOS 3.3.
If you start more than one program, the CPU is making decisions as to what to run and in what order.
This is true of any O.S., I am amazed the clock doesn't lose more time even with it's own power supply.
For me, "dropping to Dos" (should be "where speed is important") is an important feature.
For example, deleting only .obj and .map files quickly out of a host of other extensions.
Even M.S. MVPs frequently recommend using cmd or Run commands, and many admin kits have command line programs.
Rambling over.
Hi,
Oops, used an include file. This should be what is
necessary.
DOSF_OUTSTR EQU 9 ; Output string
DOSF_EXIT EQU 76 ; Exit
; 04CH
DOSF_GIVEC EQU 53 ; Set/get interrupt vector
; 035H
DOSF_SIVEC EQU 37 ; Set interrupt vecter
;025H
DOSF_DEALLOC EQU 73 ; Deallocate block
DOSF_KEEPPRC EQU 49 ; Keep process
; Macro for dealing with system software interrupts
;
; Syntax is:
;
; SCALL foo
;
; The result is a system call to DOSF_foo
;
SCALL MACRO ARG
MOV AH,DOSF_&ARG
INT 21H
ENDM
Habits, oh well.
Regards,
Steve
I am typing using Maxthon browser which I am testing.
(Supposed to be the best in terms of HTML 5.0 compliancy.)
Thanks gentlemen for the code.
Steve,
Your code is short and I will study it.
I prefer using Tasm, don't think it will take much work converting it.
Andy
Hi Andy,
Quote from: Magnum on January 13, 2013, 12:38:01 AM
I prefer using Tasm, don't think it will take much work converting it.
Andy
yes, TASM code can be easy converted into MASM code.
Gunther
i never had any luck with "SEGMENT AT" on older versions of MASM
haven't tried it on newer versions
BIODATA SEGMENT AT 4OH ;BIOS data area
ORG 17H
KBSTAT DB ? ;Keyboard status byte
BIODATA ENDS
but, all you really need is the 40h and the offset of 17h
you can do that with EQUates
as for the clock TSR, i wrote something similar, but as a device driver
CLOCK$ is the actual DOS device name - a character device
by doing it that way, it automatically comes up with the right date and time
no need for the DATE/TIME commands
if you set the DOS date or time with DATE/TIME, the driver sets the RTC
i see the CLOCK$ device doesn't seem to be supported under win32 :P
QuoteTo allow a clock board to be integrated into the system for TIME and DATE,
the CLOCK$ device is used. This device defines and performs functions like any
other character device (most functions will be reset done bit, reset error bit,
and return). When a read or write to this device occurs, 6 bytes are
transferred. The first 2 bytes are a word, which is the count of days since
01-01-80. The third byte is minutes, the fourth is hours, the fifth is
hundredths of a second, and the sixth is seconds.
of course, the RTC boards used in XT's varied
so - you had to write the I/O stuff to match your board - lol
for an AT-class machine, it is standardized at 70h/71h
EDIT: the device name for CLOCK$ is "CLOCK$ ", and the attribute is 8008h
Quote from: dedndave on January 13, 2013, 02:15:37 AM
i never had any luck with "SEGMENT AT" on older versions of MASM
haven't tried it on newer versions
Hi,
Really? What kind of problems? What version? The
following is fine with MASM Version 3.0.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BIOSSEG SEGMENT AT 40H ; BIOS Data area
ORG 6CH
ClockTic DD ? ; 55 ms timer ticks since midnight
BIOSSEG ENDS
As for the date and time, you can use the BIOS interrupt
1AH to read the RTC. I posted some code in the old forum.
Or I could post it again here.
According to the TASM documentation I have, there
should be no translation required, unless you want to use
their "Ideal Mode". But as I only have the, rather old,
documentation and not TASM itself, if you encounter any
problems, please post your corrections.
Cheers,
Steve N.
yah - it probably doesn't make sense to write a CLOCK$ driver for AT-class machines
Steve,
I assembled and ran your program.
It takes up 1152 bytes, but I can't figure out what it does besides going resident.
Andy
Quote from: Magnum on January 13, 2013, 03:51:34 AM
Steve,
I assembled and ran your program.
It takes up 1152 bytes, but I can't figure out what it does besides going resident.
Hi Andy,
The first program, PAST2.ASM, subtracts 10 years
from the DOS date function. CLOCKS.ASM is a program
to update the current time on the HP 200LX palmtop
computer using the RTC to update the DOS time. It
shouldn't go resident on other computers.
Regards,
Steve
What specifically do you mean by Dos date function ?
Since it subtracts 10 years, I thought when I did date at the command line, it would show 2003. :t
that TSR won't be applicable
it is meant to fix a specific issue on a specific machine
but - it does show you a "format" for a TSR
Hi,
The command prompt (CMD) on Win32 systems do not use
DOS functions. You would need to find a DOS program that
reports the date. WordPerfect, Lotus 1-2-3, or the like. You
might be able to run COMMAND.COM, and then see if DATE
is changed. It is/was an internal command. But that would
be a bit of a long shot.
Regards,
Steve
Quote from: nidud on January 12, 2013, 08:50:07 AM
The minimum for a TSR is around 1000 lines of code, so it is somewhat extensive
How did you arrive at this number? The upper end of the TSRs that I have done was around 1500 lines total, with the typical being well under 1000, and the smallest being around 100. Here is a TSR in 100 lines, with a resident size of 384 bytes without freeing the PSP.
;==============================================================================
; ShiftLoc.asm
; Acts as shift lock for upper digit keys (scan codes 2 - 11)
; Toggle with Ctrl + R Shift
;==============================================================================
code SEGMENT
ASSUME cs:code,ds:code
ORG 100h
entry:
jmp loadSL
oldVector dd ? ; old System Services vector
activeFlag db 0 ; set when ShiftLoc is active
slShiftFlag db 0 ; set when ShiftLoc sets BIOS flag
keyIsr:
push ax
push bx
push ds
push es
push cs
pop ds
; keyboard intercept ?
cmp ah, 4fh
jne jumpOut
; set up access to BIOS shift flags byte
mov bx, 40h
mov es, bx
mov bx, 17h
; BIOS R Shift flag forced at last call ?
cmp slShiftFlag, 1
jne chkRShiftKey
and BYTE PTR es:[BX], 0feh ; reset R Shift flag
mov slShiftFlag,0
chkRShiftKey:
cmp al, 36h ; R Shift
jne chkCtrlKey
test BYTE PTR es:[BX], 4 ; Ctrl flag ?
jz chkCtrlKey
xor activeFlag, 1 ; toggle flag
jmp jumpOut
chkCtrlKey:
cmp al, 1dh ; Ctrl
jne chkActiveFlag
test BYTE PTR es:[BX], 1 ; R Shift flag ?
jz chkActiveFlag
xor activeFlag, 1 ; toggle flag
jmp jumpOut
chkActiveflag:
cmp activeFlag, 1
jne jumpOut
; scan code 2 - 11 ?
cmp al, 2
jb jumpOut
cmp al, 11
ja jumpOut
; test R Shift flag before setting it
test BYTE PTR es:[BX], 1
jnz jumpOut
or BYTE PTR es:[BX], 1
mov slShiftFlag, 1
jumpOut:
pop es
pop ds
pop bx
pop ax
jmp DWORD PTR cs:oldVector
loadSL:
mov ax, 3515h ; get the old Int 15h vector
int 21h
mov WORD PTR oldVector,bx ; and save it
mov WORD PTR oldVector[2], es
mov ax, 2515h ; set the new vector
lea dx, keyIsr ; entry point label
int 21h
mov bx, 2Ch ; point to correct location in PSP
mov es, WORD PTR [bx] ; get environment block segment
mov ah, 49h ; free environment block to minimize
int 21h ; resident size
lea dx,loadSL ; point past end of resident part
int 27h ; TSR without return code
code ENDS
END entry
Hi,
Just to show the TSR at work. First without PAST2.COM
The partial results from MEM /C.
Memory below 640KB (conventional memory)
Name Size in Decimal Size in Hex
------------- --------------------- -------------
DOS 37024 ( 36.2K) 90A0
COMMAND 4976 ( 4.9K) 1370
VBEXT 16672 ( 16.3K) 4120
APPEND 6528 ( 6.4K) 1980
DOSKEY 4480 ( 4.4K) 1180
FREE 192 ( 0.2K) C0
FREE 80 ( 0.1K) 50
FREE 224 ( 0.2K) E0
FREE 575200 (561.7K) 8C6E0
Total FREE: 575696 (562.2K)
And the reported date by the editor is 13 January 2013.
Now, after running PAST2.COM, MEM /C shows it loaded into
memory. (Looks like I didn't get the installed size right in
the code. Pity.)
Memory below 640KB (conventional memory)
Name Size in Decimal Size in Hex
------------- --------------------- -------------
DOS 37024 ( 36.2K) 90A0
COMMAND 4976 ( 4.9K) 1370
VBEXT 16672 ( 16.3K) 4120
APPEND 6528 ( 6.4K) 1980
DOSKEY 4480 ( 4.4K) 1180
PAST2 576 ( 0.6K) 240
FREE 192 ( 0.2K) C0
FREE 80 ( 0.1K) 50
FREE 224 ( 0.2K) E0
FREE 574592 (561.1K) 8C480
Total FREE: 575088 (561.6K)
And the reported date is 13 January 2003. Ta Da!
Cheers,
Steve N.
deleted
A little screensaver (http://www.abreojosensamblador.net/Productos/AOE/html/Pags/Cap12.html#TSRSalvPantFoco) in msdos, comments in spanish, sorry
Where is the Macros_N.inc file to assemble the examples ?
Here's also a little TSR: http://www.japheth.de/Download/DOS/filemon.zip (http://www.japheth.de/Download/DOS/filemon.zip)
It hooks DOS interrupt 21h and logs certain file-related calls onto the "debug terminal" via OutputDebugString(). The Win32 API is accessed with the help of a Win32 dll ( VDD ); hence it works in NTVDM only!
Quote from: Magnum on January 15, 2013, 05:08:44 AM
Where is the Macros_N.inc file to assemble the examples ?
This is what you need. I guess that it does not work well inside a WXP cmd, but yes inside dosbox.
japheth, it is hard to download files from your site...
This is filemon, a character in a comic of humor :bgrin:
(http://t2.gstatic.com/images?q=tbn:ANd9GcQ8uvA1uw3MFNYFerkSpirbHK3Vi-iyQIvXbImT0o1-wVQn1fI2CQ)
Quote from: avcaballero on January 15, 2013, 08:23:22 PM
japheth, it is hard to download files from your site...
Is it a physical or psychical problem?
You have sense of humor, eh? ... I can't access because of spyware/malware warning. Surely my antivirus is wrong (my fault with no doubt)... Never mind
Thanks guys
what this promlem my code?
.model small
.stack
.code
start:
mouse proc near
mou:
push ax
push dx
push cx
mov al,4
mov bh,0
int 10h
mov bh,0
mov bl,1001b
mov ah,0Bh
int 10h
mov ax,0
int 33h
mov ax,01h
int 33h
;mov dx,101h
;mov cx,161h
lable1:
mov ah,10h
int 16h
cmp ah,50h ;DownArrow key
je lable2
cmp ah,4Dh ;RightArrow key
je lable3
cmp ah,4Bh ;LeftArrow key
je lable4
cmp ah,48h ;upArrow key
jne test_something_else
; Moved up
mov ax,03h
int 33h
dec dx
mov ax,04h
int 33h
cmp dx,0
jne lable1
lable2:; Moved Down
mov ax,03h
int 33h
inc dx
mov ax,04h
int 33h
cmp dx,184
jne lable1
lable3:; Moved right
mov ax,03h
int 33h
inc cx
mov ax,04h
int 33h
cmp dx,0
jne lable1
lable4:; Moved left
mov ax,03h
int 33h
dec cx
mov ax,04h
int 33h
cmp dx,305
jne lable1
test_something_else:
;------------ end of program
pop cx
pop dx
pop ax
iret
end mou
mouse endp
mov ah,25h
mov al,100
mov dx,offset mouse
int 21h
mov ah,31h
mov dx,offset mou
;mov dx, offset
int 21h
;in al,60h
int 09h
ah,0
int 16h
; cmp al,4Dh ;RightArrow key
int 10h
cmp ah,3Bh ;DownArrow key
jne NotRunMouse
int 64h
NotRunMouse:
mov ax, 4c00h
int 21h
end start
I want my code to be amended and just tell me what is my code problems?
The F key to activate the MouseProgram in another program
Quote from: majid1605 on January 29, 2013, 10:37:39 AM
I want my code to be amended and just tell me what is my code problems?
There are a LOT of problems in your code.
A brief glance reveals that to extend this program is clearly "beyond your league" ( that's how one of the moderators described this phenomenon once, so I guess it's the official term ).
A somewhat experienced ASMer could probably fix the errors and feed you with the result, but you won't learn much then.
My advise: start with something much simpler and then advance carefully.
This is working code.
Please study it and understand it because it does what you have been asking for.
Andy
; saver.asm Com program Orig. File Creation 6/13/2002 AK
; Minor modification on 1/29/13
; Screen saver (blanks screen) COM file..
; Only works in 80x25 screen modes (2,3,7) [could easily be adapted/others]
; Uses F-8 key to activate, un-install by typing name of program again
;
; **** ADJUSTABLE time interval to pop up
;
; ;
;
;
.SEQ ; store segment sequentially as they appear
.286 ; use 80286+ code
.MODEL tiny ; TINY model to make it a .COM program
;* Macros *
StAlloc MACRO sizew ; macro to allocate stack, size "sizew" words
MOV BX,((sizew*2)+15) SHR 4 ; BX = size in paragraphs
MOV AH,48h ; allocate memory function
INT 21h ; call DOS
CLI ; freeze interrupts
MOV SS,AX ; set stack segment to allocated segment returned in AX
MOV SP,sizew*2-2 ; set stack pointer to end of segment (goes top down)
STI ; restore interrupts
ENDM
StDeAlloc MACRO ; macro to deallocate stack
MOV AX,SS
MOV ES,AX
MOV AH,49h ; call DOS deallocate block function
INT 21h
ENDM
;* Code Segment *
code SEGMENT PARA PUBLIC 'CODE' ; code segment
ASSUME CS:code, DS:code, ES:code, SS:code ; assume CS->"code" etc.
ORG 100h ; start assembling at offset 0h (default)
;* Program Start *
start: ; label for start of program
JMP init
;* Procedures *
; Save screen and display (init) screen saver logo
ScreenSaver PROC NEAR
MOV AX,CS
MOV ES,AX
MOV DI,OFFSET ScrData
MOV DS,CS:ScrAddress
XOR SI,SI
CLD
MOV CX,2000
REP MOVSW ; save screen
MOV CS:SSOn,1
MOV AH,0Fh
INT 10h ; get current page in BH
MOV AH,03h
INT 10h ; get old cursor size
MOV CS:OldCursor,CX
MOV AH,01h
MOV CX,0100h
INT 10h ; hide cursor
CALL RunSaver ; clear screen
CALL DrawSaver ; draw logo
RET
ENDP
; Restore screen and deinitialize screen saver
RemoveSaver PROC NEAR
MOV ES,CS:ScrAddress
XOR DI,DI
MOV AX,CS
MOV DS,AX
MOV SI,OFFSET ScrData
CLD
MOV CX,2000
REP MOVSW
MOV CS:SSOn,0
MOV AH,01h
MOV CX,CS:OldCursor
INT 10h ; restore cursor
RET
ENDP
; Re-hide screen to cover any writing
RunSaver PROC NEAR
MOV ES,CS:ScrAddress
XOR DI,DI
MOV CX,2000
XOR AX,AX
REP STOSW
RET
ENDP
; Find parts of screen that were changed and save to virtual screen
DeltaSaver PROC NEAR
CLD
MOV DS,CS:ScrAddress
XOR SI,SI ; DS:SI -> physical screen
MOV AX,CS
MOV ES,AX
MOV DI,OFFSET ScrData ; ES:DI -> virtual screen
XOR BH,BH ; row 0
ds_nextrow:
MOV CX,80
CMP BH,CS:Row
JZ ds_check ; if row of copyright string handle separately
ds_loop:
LODSW
CMP AX,0 ; check if still zero (as set by screen saver)
JZ ds_again
MOV ES:[DI],AX ; set to new value
ds_again:
INC DI
INC DI
LOOP ds_loop
ds_new:
INC BH
CMP BH,25
JNZ ds_nextrow
RET
ds_check:
MOV BP,OFFSET Copyright
MOV BL,CS:Color
ds_loop2:
LODSW
CMP AL,ES:[BP]
JNZ ds_delta
CMP AH,BL
JZ ds_ok
ds_delta:
MOV ES:[DI],AX
ds_ok:
INC DI
INC DI
INC BP
LOOP ds_loop2
JMP SHORT ds_new
ENDP
; Draw copyright string
DrawSaver PROC NEAR
MOV AX,WORD PTR CS:Row2
MOV WORD PTR CS:Row,AX ; now safe to copy incremented data
MOV AH,CS:Row
MOV AL,160
MUL AH
MOV DI,AX
MOV AX,CS
MOV DS,AX
MOV SI,OFFSET CS:Copyright
MOV AH,CS:Color
ds_write:
LODSB
OR AL,AL
JZ ds_donemsg
STOSW
JMP SHORT ds_write
ds_donemsg:
RET
ENDP
; move message and change color
IncSaver PROC NEAR
MOV AX,WORD PTR CS:Row2 ; AL = row, AH = attribute
ADD AX,101h ; increment both
CMP AL,25
JNZ is_rowset
XOR AL,AL
is_rowset:
CMP AH,16
JNZ is_colset
MOV AH,1
is_colset:
MOV WORD PTR CS:Row2,AX
RET
ENDP
; INT 09h interrupt handler
; checks for hotkey combinations and deinstalls or activates program if found
Int09Handler PROC FAR
PUSHF
CALL CS:OldInt09 ; call old handler
PUSHA
PUSH DS
PUSH ES
MOV AX,40h
MOV ES,AX
MOV DI,ES:[1Ah]
CMP DI,ES:[1Ch] ; quit if no keys in keyboard buffer
JZ i9_exit
MOV CS:SSTimer,0 ; zero timer for screen saver
CMP CS:SSOn,0
JZ i9_skip
CALL RemoveSaver ; if screen saver active, restore screen
i9_skip:
MOV DI,ES:[DI] ; get key in keyboard buffer
CMP DI,4200h ; check for F8 , zeroes needed after scan code
JNZ i9_exit
PUSH DI
PUSH ES
CALL ScreenSaver ; startup screen saver
POP ES
POP DI
i9_remove:
INC WORD PTR ES:[1Ah]
INC WORD PTR ES:[1Ah] ; remove key from buffer
CMP WORD PTR ES:[1Ah],3Eh
JNZ i9_exit
MOV WORD PTR ES:[1Ah],1Eh ; wrap around if required
i9_exit:
POP ES
POP DS
POPA
IRET
ENDP
; INT 1Ch interrupt handler
; activates screen saver when timeout occurs
Int1CHandler PROC FAR
PUSHF
CALL CS:OldInt1C
PUSHA
PUSH DS
PUSH ES
CMP CS:SSOn,0
JZ i1c_off
CALL DeltaSaver ; store changes to virtual screen
CALL RunSaver ; blank screen
CALL DrawSaver ; draw message or graphic
i1c_off:
MOV AL,CS:Timer1
DEC AL
MOV CS:Timer1,AL
JNZ i1c_exit
MOV AH,18
MOV AL,CS:Timer2
DEC AL
JNZ i1c_not19
INC AH
MOV AL,5
i1c_not19:
MOV CS:Timer2,AL
MOV CS:Timer1,AH
CMP CS:SSOn,0
JZ i1c_count
CALL IncSaver
JMP SHORT i1c_exit
i1c_count:
MOV AX,CS:SSTimer
INC AX
MOV CS:SSTimer,AX
CMP AX,180 ; 3 minutes (min x 60 secs)
JNZ i1c_exit
XOR AX,AX
MOV CS:SSTimer,AX ; set to zero
CALL ScreenSaver ; startup screen saver
i1c_exit:
POP ES
POP DS
POPA
IRET
ENDP
; TSR data
ScrAddress DW 0
OldCursor DW 0
OldInt09 DD 0
OldInt1C DD 0
SSTimer DW 0
SSOn DB 0
Timer1 DB 18
Timer2 DB 5
ScrData DW 2000 DUP (?)
Row DB 0
Color DB 1
Row2 DB 0
Color2 DB 1
Copyright DB 'è Hello, I am a Hotkey popup TSR',0
Sig DB 'VXSS'
TSR_end LABEL BYTE
; * Main Program *
init:
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV BX,OFFSET code_end
ADD BX,15
SHR BX,4
MOV AH,4AH
INT 21H ; free unneeded memory given to program
StAlloc 50h ; allocate stack (saves memory on disk)
XOR AX,AX
MOV ES,AX
PUSH DS
MOV DS,ES:[26h]
CMP WORD PTR DS:Sig,'XV'
JNZ i_skip
CMP WORD PTR DS:Sig+2,'SS'
JNZ i_skip
MOV AX,WORD PTR DS:OldInt09
MOV BX,WORD PTR DS:OldInt09+2
CLI
MOV ES:[24h],AX
MOV ES:[26h],BX
MOV AX,WORD PTR DS:OldInt1C
MOV BX,WORD PTR DS:OldInt1C+2
MOV ES:[70h],AX
MOV ES:[72h],BX
STI
MOV AX,DS
MOV ES,AX
MOV AH,49h
INT 21h
POP DS
MOV AH,09h
MOV DX,OFFSET Deinstall
INT 21h
StDeAlloc
MOV AX,4C00h
INT 21h
i_skip:
POP DS
MOV AX,0B800h
CMP BYTE PTR ES:[0449h],7 ; check if current mode @ 0:449 is 7 (mono)
JNZ i_gotmode
MOV AX,0B000h
i_gotmode:
MOV ScrAddress,AX ; store screen address
MOV AX,ES:[24h]
MOV BX,ES:[26h]
MOV WORD PTR OldInt09,AX
MOV WORD PTR OldInt09+2,BX ; save old interrupt 09h
MOV AX,OFFSET Int09Handler
MOV BX,CS
CLI
MOV ES:[24h],AX
MOV ES:[26h],BX
STI
MOV AX,ES:[70h]
MOV BX,ES:[72h]
MOV WORD PTR OldInt1C,AX
MOV WORD PTR OldInt1C+2,BX ; save old interrupt 1Ch
MOV AX,OFFSET Int1CHandler
MOV BX,CS
CLI
MOV ES:[70h],AX
MOV ES:[72h],BX
STI
MOV AH,49h
MOV ES,CS:[2Ch]
INT 21h ; deallocate environment block
MOV AH,09h
MOV DX,OFFSET Install
INT 21h ; display message
StDeAlloc ; deallocate stack
MOV DX,OFFSET TSR_end
ADD DX,15
SHR DX,4
MOV AX,3100h
INT 21h ; go TSR, exit with errorlevel 0
;* Data Area *
; main program data
Install DB 13,10,'Screen Saver now installed - press F8 to activate.'
DB 13,10,'Type Saver again to un-install.',13,10,10,'$'
Deinstall DB 13,10,'Screen Saver un-installed Ok.',13,10,10,'$'
;* End Program *
code_end LABEL BYTE ; mark end of code segment (end of program)
code ENDS ; end code segment "code"
END start ; end program, start execution at "start:"