flat assembler
Message board for the users of flat assembler.
Index
> DOS > TSRs |
Author |
|
windwakr 19 Aug 2010, 03:53
You're writing the address to the current segment.
Code: org 100h push 0 pop es mov word[es:8*4], pit_isr mov word[es:8*4+2], cs mov ah, 0x31 mov al, 0 mov dx, 1 int 0x21 pit_isr: cli mov ah, 0xe mov al, 'f' mov bl, 7 int 0x10 mov al, 0x20 out 0x20, al sti iret I think it would also be wise to stop interrupts while changing the IVT. |
|||
19 Aug 2010, 03:53 |
|
sinsi 19 Aug 2010, 05:59
DX ia the number of paragraphs to keep, this needs to be PSP (16 paragraphs) plus code, I don't think 1 is enough.
If you are hooking the timer, it is best to call/jmp to the original ISR as well. |
|||
19 Aug 2010, 05:59 |
|
windwakr 19 Aug 2010, 15:55
EDIT: I get it now, ignore this post.
sinsi wrote: DX ia the number of paragraphs to keep, this needs to be PSP (16 paragraphs) plus code, I don't think 1 is enough. Must be a bug in DOSBox. Even this runs fine in it: Code: org 100h push 0 pop es mov word[es:8*4], pit_isr mov word[es:8*4+2], cs mov ah, 0x31 mov al, 0 mov dx, 1 int 0x21 times 40000 db 0 pit_isr: cli mov ah, 0xe mov al, 'f' mov bl, 7 int 0x10 mov al, 0x20 out 0x20, al sti iret Last edited by windwakr on 20 Aug 2010, 00:29; edited 2 times in total |
|||
19 Aug 2010, 15:55 |
|
Tyler 19 Aug 2010, 16:04
Is there any way to hook task creation in DOS?
My idea was basically TSR every task that is created, then switch between them and the DOS kernel, creating a RM multitasking OS. > If you are hooking the timer, it is best to call/jmp to the original ISR as well. If I'm not going to return to the task that was running, I can't do that, not now. The other ISR will either iret, or will call another that will iret. Maybe later, I'll just push the next task onto the stack, then call the ISR that will iret. But for now, that's just extra complexity. 1 works because: The minimum number of paragraphs which will remain resident is 11h for DOS 2.x and 06h for DOS 3.0+. |
|||
19 Aug 2010, 16:04 |
|
edfed 19 Aug 2010, 16:22
the TSR should save registers, and load next registers.
then, you need a structure, containing a list of tasks. of course, this list should be managed in order to create and destroy tasks. then, a list of TSS, and various TSS TSS can be located in the PSP if you want. but it can be better to separate the tss from the applicatoin adress space, then, locate it at 1000h:0 for example Code: mainlist: current dd 0 ;task0linear dd @f-$-4 dd task0 dd task1 dd task2 @@: task0: .eax dd ? .ebx dd ? .ecx dd ? .edx dd ? .edi dd ? .esi dd ? .ebp dd ? .esp dd ? .eflags dd ? .cs dw ? .ds dw ? .es dw ? .fs dw ? .gs dw ? .ss dw ? task1: .eax dd ? .ebx dd ? .ecx dd ? .edx dd ? .edi dd ? .esi dd ? .ebp dd ? .esp dd ? .eflags dd ? .cs dw ? .ds dw ? .es dw ? .fs dw ? .gs dw ? .ss dw ? task2: .eax dd ? .ebx dd ? .ecx dd ? .edx dd ? .edi dd ? .esi dd ? .ebp dd ? .esp dd ? .eflags dd ? .cs dw ? .ds dw ? .es dw ? .fs dw ? .gs dw ? .ss dw ? of course, this example of tss is not the example from IA32 hardware TSS. then, each task switch is jut a succesion of data transfert from regs to memory, and from memory to reg. and |
|||
19 Aug 2010, 16:22 |
|
Tyler 19 Aug 2010, 16:48
> of course, this list should be managed in order to create and destroy tasks.
That's the hard part. How do I know when a task is created or destroyed? |
|||
19 Aug 2010, 16:48 |
|
edfed 19 Aug 2010, 18:57
in fact, it is simple if there is only one task list, and of a limited size.
for example, limit the task list to 1000 tasks. then, you will know exactlly the maximal memory requirement. [tss =! ia32 tss] tasklist = rd 1000 [tss] + dd current + dd size = rd 1002 = rb 4008 one tss = rd 9 + rw 6 = rd 12 = rb 48 * 1000 = 48 000 + 4008 = 52 002 bytes then, you still know that tak manager datas will be in a separate segment of 64 k... let expand the maximum, to reach 64kbytesnow, to create a task, you will need a pointer to the current task, and the pit will switch at a given frequency. for example of 1kHz. then, it will switch the 1000 tasks in 1 second. or 2 tasks in 2 milliseconds. to create a task, you will need to check for maximum, if no task can be added, then, report the error. if the task can be added, check the adress of last task, add the pointer to the new task, and fill the corresponding tss with the initial state for the task. ones it is ok, load the task in memory where the system wants it to be loaded (from memory manager) and it is ok for a new task. to delete a task, the task will return a end message to the system, by the intermediate of the psp for example, or an interrupt, abd the system will simply, delete the task pointer. then, if the task is deleted, it will be a hard process to update everything. everyt task after the one deleted are shifted by one position, and the count of task is decremented. but when it will be the time to create a new task, it will be harder to find the first free tss, and assign it in the list. then, a bitmap will be necessary to scan the 1000 tss and find the first free. then, 125 bytes, 1bit = 1tss, 1 = occupied, 0 = free. it gives the size for a task list for 1024 tss of: tasklist= rd 2+1024 = 4102 bytes + 1024* tss = rd 12*1000 = 53254 bytes + bitmap = rb 128 = 53382 bytes maybe there is enough free memory for the task manager in this task segment. but doing this with hardware is a kind difficult too. and the legend says that it is slower. |
|||
19 Aug 2010, 18:57 |
|
edfed 19 Aug 2010, 20:44
oups!!!
i forgot one important thing, EIP. i tell the use of 32 bit registers because it is supported by real mode on 90% of the still existing machines... and because it is protected mode compliant. |
|||
19 Aug 2010, 20:44 |
|
sinsi 19 Aug 2010, 23:18
@windwakr: it doesn't work properly, even under DOS.
If you take out the code to print the character, it seems to run OK, but try running a program after - DOS will load it and overwrite the isr, freezing the computer. |
|||
19 Aug 2010, 23:18 |
|
edfed 21 Aug 2010, 14:03
you should restore the origianl interrupt before to quit the program, then, dos will not crash.
for the TSR, i am trying to do it with stacks. the INT8 is there just to switch tasks from a task list. services will be under int80h. the task creator will: save current task state create the stack for the task create the psp for the task push psp iret (flags,cs,ip) push int80.end (ip) push parameters on the new stack save the stack restore current stack ret to int80h.end the task switch will do: save context on stack save current task increment current stask restore current stack restore context from stack jmp to int80h.end int80h will do: movzx eax,al shl eax,2 mov eax,[int80h.func+eax] or eax,eax je .end call ax .end: iret .func is a table of 256 dwords. parameter from al will be the number of the function. every functions used by int80h are 32bit near pointers inside the code segment. then, when asking for a service, only near calls and rets are used. for the task manager, there are many problems really difficult to manage when thinking about limits, then, if limits are ignored, it will be easyer. to alloc memory, the first simple trick is to just give a number (segment), increment it by a number of parapgraph desired, and this new number as free memory base. if memory comes to the limit of VGA video memory (0a000h) it will end memory allocation and return an error. but it is not a good method, the best one will be to seek free memory from a bit map, and free the memory by clearing bits corresponding to memory sectors. it is really a complex problem with many dimensions. there the code just because it is lot of work for nothing if you just hit escape key, it will end the program, if you hit n (new task) key, it will not end, but it will crach when hit escape. that's because there are many bugs. that's all, it will be corrected later.
|
|||||||||||
21 Aug 2010, 14:03 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.