VOGONS

Common searches


Reply 20 of 42, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

well your chaining a hardware triggered isr with a software isr (0xc8), when you just just call it directly without doing an int call. I'd replace the int c8/eoi/sti/iret with a jump to the old interrupt routine.

also an STI before IRET is meaningless, IRET pops the flags from the interrupt frame on the stack.

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: http://mega-tokyo.com ]-/\--

Reply 21 of 42, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

The most significant problem that I see is calling DOS file functions before IRQ 0 has been acknowledged. No IRQ can occur while IRQ 0 is in service because it has the highest priority. Floppy drive controllers use IRQ 6, some hard drive controllers use IRQ 15, and so trying to write to drives while IRQ 0 is in service can cause malfunction at best or a system hang at worst. You can get away with it in DOSBox because drive controllers are not emulated, but not so much in more strict emulations or on real systems.

That said, managing IRQ 0 differently would avoid the problem with drive IRQs and not hold up IRQ 0 (which normally occurs ~18.2 times per second) while the memory dump is in progress. The idea is to have your IRQ 0 handler call the original IRQ 0 handler, which will signal EOI, and *then* perform the memory dump to disk if the "hot key" is being pressed. Of course this leaves open the possibility of recursion (i.e. IRQ 0 occuring while memory dumping is in progress), but that can be managed with a non-reentrancy flag that is set when the memory dumping begins and cleared when it is complete.

Reply 22 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

@bloodycactus:
Yeah after testing, it turned out all CLI/STI instructions were pointless. I put them there because of instructions on how to build a TSR I found on YouTube. It's hard to find decent info on this subject. Thanks for helping out. Do you mean I should use a far jump instead of an interrupt call to activate the redirected interrupt?

@ripsaw8080:
I am not sure I fully understand what you just wrote.

Also, I am posting updated code here:
https://github.com/PeterSwinkels/Memory-Dumpi … TSR-for-MS-DOS/

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 23 of 42, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

Ive written trs + sys drivers (ansi, umb, other ram stuff) so if you have specific questions, ask. I dont know how good youtube tutorials could be, I would think a written one would be better, I dunno.

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: http://mega-tokyo.com ]-/\--

Reply 24 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

@BloodyCactus: I don't think the medium itself matters much. I think it's the quality of the information provided that matters. Anyway the only specific question I have right now is whether you have any suggestions as how I could improve my code.

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 25 of 42, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author
Peter Swinkels wrote on 2021-06-21, 07:32:

@ripsaw8080:
I am not sure I fully understand what you just wrote.

The point is that you should call the original IRQ 0 handler before your memory dumping process, not after, but then you need some simple logic to deal with recursion.

Here is an example of the handler code using your style. I have to guess a bit at NASM's requirements as I don't use it:

TSR:

INT RedirectedTo ; Calls the redirected interrupt, which signals End-Of-Interrupt

PUSHA ; Saves the registers.
PUSH DS ;

PUSH CS ; Restores the data segment register.
POP DS ;

CMP BYTE [Dumping], 0x00 ; Skips memory dumping if already in progress.
JNE SKIP ;

IN AL, 0x60 ; Skips memory dumping unless the F12 key is being pressed.
CMP AL, 0x58 ;
JNE SKIP ;

MOV BYTE [Dumping], 0x01 ; Set non-reentrancy flag.

%INCLUDE "Memdump.asm" ; Includes the TSR's main body.

CLI ; Ensure interrupt does not occur until IRET.

MOV BYTE [Dumping], 0x00 ; Clear non-reentrancy flag.

SKIP:

POP DS ; Restores the registers.
POPA ;

IRET ; Returns.

Dumping DB 0x00

Note that the CLI in this case might not be necessary but is a safeguard to prevent recursion, and the signaling of EOI is removed because calling the original handler does it. Also moved the key test out of the memory dumping code and into the handler code to work better with the non-reentrancy flag. While here I noticed your use of the FS segment register is problematic because any software that modifies FS will cause your program to mess up, so I use a different method to restore DS.

Reply 26 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

Yeah, I know I took a risk using the FS register. Thank you for your suggestions I will look into this further when I have the time.

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 27 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

Okay, I removed the use of the FS register to store the data segment and added a check to prevent the program from trying to perform a dump while one is already in progress.

https://github.com/PeterSwinkels/Memory-Dumpi … -TSR-for-MS-DOS

Are there any other changes you would recommend?

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 28 of 42, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

You missed the most important part of calling the original IRQ 0 handler BEFORE the dump process, and adding the recursion flag doesn't really do anything without that.

The truth is that writing active TSRs that call DOS functions is actually kind of a pain. DOS itself can be interrupted by an interrupt, and there are parts of DOS that are not reentrant, so the "InDOS" flag is provided to warn TSRs not to call DOS while the flag is set. DOSBox's emulated DOS lets you get away without dealing with reentrancy because its internal callbacks are uninterruptable, but in real DOS it's not so easy. The details are somewhat complicated, so instead of trying to explain further I will just link to information here.

Reply 29 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

I had to read that article a few times. There's a lot of technical stuff I never dealt with before in there. As far as I understand it only the first few paragraphs are relevant in my case. According to those I need to:

1. Call DOS function 34h (int 0x21, ah = 0x34)
2. Save the address returned in es:bx.
3. Check the byte (InDos) at that address and the one immediately preceding it (critical error.)
4. If both are zero my TSR can safely call DOS functions otherwise it should just skip everything and allow other code to resume.

Correct?

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 30 of 42, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie
Peter Swinkels wrote on 2021-06-23, 08:12:
I had to read that article a few times. There's a lot of technical stuff I never dealt with before in there. As far as I underst […]
Show full quote

I had to read that article a few times. There's a lot of technical stuff I never dealt with before in there. As far as I understand it only the first few paragraphs are relevant in my case. According to those I need to:

1. Call DOS function 34h (int 0x21, ah = 0x34)
2. Save the address returned in es:bx.
3. Check the byte (InDos) at that address and the one immediately preceding it (critical error.)
4. If both are zero my TSR can safely call DOS functions otherwise it should just skip everything and allow other code to resume.

Correct?

yes. I threw the indos/crit check into my tsr scaffold I wrote. This forceable puts the tsr into umb out of the way if it exists (no need to loadhi/lh it) and will hook + detach.

this is nasm code, as an example hooks int 0x11 but does nothing. you can use this if you want to shove somehthing into umb memory as tsr. its straight out of my ansi driver.

[bits 16]
[org 0x100]

%define w word
%define d dword

%macro proc16 1
[section .text]
align 2, db 0x90
%1:
%endmacro

[section .text]

start:
jmp setup_isr
db 0x90
alignb 2, db 0x90
;; we are at 0x104 so buffered enough for indos_buffer

indos_buffer equ start
old_int_11: dd 0

my_interrupt:
;; test indos
push ds
push bx
lds bx,[cs: indos_buffer]
xor ax,ax
xor ax,w[bx]
pop bx
pop ds
jnz .finish_isr

;; do work here
nop
nop

.finish_isr:
jmp far [cs: old_int_11]

;; paragraph align for tsr memory block
alignb 0x10, db 0
end_tsr_part:

proc16 setup_isr
mov ax,cs
mov ds,ax
mov es,ax
mov sp,end_stack
mov bx,sp
add bx,15
shr bx,4
mov ah,0x4A
int 0x21

;; hook int11 as example
mov ax,0x3511
int 0x21

Show last 240 lines
	mov w[old_int_11+2],es
mov w[old_int_11+0],bx

;; test it is ourself or someone else
mov di,bx
mov si,my_interrupt
mov cx,setup_isr
sub cx,si
repe cmpsb
jnz .go_resident

;; its us, so detach int 11
mov dx,w[es: old_int_11+0]
mov ds,w[es: old_int_11+2]
mov ax,0x2511
int 0x21

;; free tsr memory
mov ah,0x49
int 0x21

mov ax,cs
mov ds,ax

mov dx,msg_unhook
mov ah,9
int 0x21

;; quit
mov ah,0x4C
int 0x21

.go_resident:
call setup_tsr_memory_block
;; tsr code block is in BP

mov ds,bp

;; setup insdos buffer
mov ah,0x34
int 0x21
;; dos version dependant, 3.1+ lets hope we dont wrap segments...
dec bx
mov w[indos_buffer+2],es
mov w[indos_buffer+0],bx

mov ax,0x2511
mov dx,my_interrupt
int 0x21

;; free environment
mov ax,cs
mov ds,ax

mov es,w[0x2C]
mov ah,0x49
int 0x21

mov dx,msg_hook
mov ah,9
int 0x21

mov ax,cs
cmp ax,bp
jz .tsr_low_memory

;; only free ourself if we are not ourselves (tsr in umb)
mov ah,0x49
int 0x21

mov ah,0x4C
int 0x21

.tsr_low_memory:
;; go tsr
mov dx,setup_isr ;; already aligned correctly for tsr
mov ah,0x31
int 0x21

proc16 setup_tsr_memory_block
push ds
pop es

mov bp,ds

mov ax,0x3000
int 0x21
cmp al,5
jb .nd0

push ax

;; chain umb
mov ax,0x5803
mov bx,1
int 0x21

pop ax

.nd0:
cmp al,3
jb .alloc_low

;; last fit allocation strategy
mov ax,0x5801
mov bx,2
int 0x21

call alloc_block
jc .nd90

mov es,ax

;; if its not umb, dont use it!
cmp ax,0xA000
jae .alloc_is_good

;; free
mov ah,0x49
int 0x21

mov ax,cs
mov es,ax

.alloc_low:
;; reset mem strategy to low
call reset_alloc_low
call alloc_block
jc .nd90

;; is our block below our cs
mov bx,cs
cmp ax,bx
jb .alloc_is_good

mov es,ax
mov ah,0x49
int 0x21
mov ax,cs
mov es,ax
jmp .nd90

.alloc_is_good:
mov bp,ax

.nd90:
;; fail!
call reset_alloc_low

;; free up old environment blocks
mov es,w[cs: 0x2c]
mov ah,0x49
int 0x21


;; set owner to itself so dos does not free it up
mov ax,bp
dec ax
mov es,ax
inc ax
mov w[es: 1], ax

;; own memory
mov ax,cs
mov ds,ax

;; lets do a MCB fudge for naming
mov si,mytsr_name
mov di,8
mov cx,4
rep movsw

;; copy down
mov ax,cs
mov ds,ax
mov es,bp
cmp ax,bp
jz .skip_move

xor si,si
xor di,di
mov cx,end_tsr_part
shr cx,1
rep movsw

.skip_move:
mov ax,cs
mov ds,ax
mov es,ax
ret


proc16 alloc_block
;; try and allocate upper memory
mov ax,0x4800
mov bx,end_tsr_part ;- 0x100
shr bx,1
shr bx,1
shr bx,1
shr bx,1
int 0x21
ret

proc16 reset_alloc_low
mov ax,0x3000
int 0x21
cmp al,5
jb .nd99

push ax
;; unchain UMB's
mov ax,0x5803
xor bx,bx
int 0x21
pop ax

.nd99:
;; reset allocation strategy
cmp al,3
jb .nd100
mov ax,0x5801
xor bx,bx
int 0x21

.nd100:
ret

[section .data]
;; MCB name, must be 8 characters here
mytsr_name: db 'myTSR',0,0,0

msg_hook: db 'We have hooked int 0x11. Run again to remove',0x0d,0x0a,'$'
msg_unhook: db 'We have unhooked int 0x11 and removed TSR',0x0d,0x0a,'$'

[section .bss]
align 2
resw 128
end_stack:

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: http://mega-tokyo.com ]-/\--

Reply 31 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

I added a check for the critical error and InDOS flags. How does this look: https://github.com/PeterSwinkels/Memory-Dumpi … DOS/upload/main ?

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 32 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

It seems the link I posted wasn't the right one... https://github.com/PeterSwinkels/Memory-Dumpi … -TSR-for-MS-DOS

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 33 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

@bloodycactus:

I hadn't noticed you had posted far more code than I thought at first. Therefore I didn't notice the code dealing with loading into umb/hooking/unhooking. I kind of let the matter slide into the background and forgot about it. I did notice you mentioned your scaffold having those functions though.

Right now I don't feel like it, but I intend to try implementing those features in my code. Would you still be willing to test the tsr and provide feedback? (Once I gave implementing those features a shot.)

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 34 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

Okay, I see your code is a lot more advanced than I had expected. Here's a list of interrupts you appear to be using which I never used:

int 21,48 - allocate memory
int 21,49 - free allocated memory
int 21,4a - modify allocated memory block (setlblock)
int 21,9 - I see your tsr communicates with the user. 😀
int 21,30 - MS-DOS version.
int 21,58 - Get/set memory allocation strategy.

Alright, it would be nice if my TSR communicated with the user. But are DOS version checking and memory allocation/deallocation really necessary?

And I see a lot of macros...

[bits 16]
[org 0x100]

%define w word
%define d dword

%macro proc16 1
[section .text]
align 2, db 0x90
%1:
%endmacro

[section .text]

alignb 0x10, db 0

[section .data]
mytsr_name: db 'myTSR',0,0,0

msg_hook: db 'We have hooked int 0x11. Run again to remove',0x0d,0x0a,'$'
msg_unhook: db 'We have unhooked int 0x11 and removed TSR',0x0d,0x0a,'$'

[section .bss]
align 2
resw 128
end_stack:

I see you use sections and alignment too. What is bss?

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 35 of 42, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

bss is uninitialised data. stuff that does not need to be stored in the program (so its not compiled into the exec) taking up space no disk.

proc16 macro is just to keep call/jump alignments word aligned (its not really a thing but its nice on some processors are faster when word aligned).

All the memory calls are necessary if you want to move things into UMB and allocate/deallocate and just play nice with the system.

when a COM loads, its given ALL the free memory in a system, so you need (4A) to resisze your existant memory block and release up the rest of memory your holding.

A TSR also does not need to keep its environment block, so its good to free that up as well.

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: http://mega-tokyo.com ]-/\--

Reply 36 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

Okay, for anyone who cares:
I finally got around to making a few updates such as adding messages to the program. Link:

https://github.com/PeterSwinkels/Memory-Dumpi … -TSR-for-MS-DOS

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 37 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member
Image1.png
Filename
Image1.png
File size
11.88 KiB
Views
169 views
File license
Public domain

I see your 475 byte tsr scaffold (myTSR) is using over 4 kb - is it supposed to be using that much? Also, I haven't (yet?) added any memory management to my mmdmptsr.com program, but according to MS-DOS it's not taking up all memory as you can see in the screenshot. And yes, this is actual MS-DOS 6.22 running DOSBox.

Image2.png
Filename
Image2.png
File size
13.42 KiB
Views
169 views
File license
Public domain

As you can see, the memory management function (int 0x21, ah=0x49) should only be used in combination with (ah=0x48) according to HelpPC, but I don't see a call to that particular function in your TSR anywhere.

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 38 of 42, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

well my tsr code is very refined. I dont know what you did but it shouldnt be running like 4kb etc. as for your program not taking up all memory.. thats because youve gone tsr. when its loads it has everything, when you call terminate + stay resident it resizes. you can call 0x49 on any valid memory block in the system, that includes the environment block.

--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: http://mega-tokyo.com ]-/\--

Reply 39 of 42, by Peter Swinkels

User metadata
Rank Member
Rank
Member

I did not modify your code in any way. I just assembled it using Nasm. Okay, I will look into 0x49 when I have the time.

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels