Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
My OS can handle jumping a new task but it can't handle one dying. Right now, I'm essentially injecting the assembly code with a pointer and the first process I created was just CD21F4 (interrupt 33, hlt) so I made a pointer to the new page (temp) and set
When the scheduler decides to switch from the kernel to the task, I get the interrupt 33 call, it prints a message, but then refuses to halt on return. If I remove the message from the interrupt, it will just return from the interrupt and continue to execute until it crosses the page barrier and gives a page fault. If the message is retained within the interrupt, then it does some really weird **** when it hits the instruction after the hlt (which it should never do anyway). So why isn't it halting at the hlt, or how should I loop the process at the end, since I can't handle one dying yet (and won't, until I make sure that I can sustain them)?
I'll be damned, I didn't know that. I should've guessed. Anyway, I've been trying to avoid the HLT instruction now by looping so I wrote this little NASM program:
and when I execute it goes totally haywire (still fires the interrupt all right, but doesn't loop correctly or something). So what would a better loop strategy be? Or, at least, what am I doing wrong?
Ok, so you have a relative jump here with 32-bit offset, which makes little sense since 8 bit offset would do just as well. But other than that, it _seems_ ok.
Anyway, are you sure you return everything into such a state that the interrupt can be safely fired again? I find it quite likely that the problem is somewhere else.
Anyway, I'd try to find a way to include your assembler generated code directly into your kernel. One option is to simply put a label before and after the asm-code (maybe compile it into .data section?) then link it normally, and use the labels to find it and copy it where you want it. That way you avoid manually typing bytes.
...which assembles as EB FE. Add the INT instruction (CD 21) so you get *temp = 0xFEEB21CD, a lovely little 4 byte program. ;D
If you do want to call the function again, adjust the 1-byte offset two backwards, to EB FC. Giving:
*temp = 0xFCEB21CD
for the same result, but in less code...
Are we optimizing a 7-byte program to a 4-byte program now? What's gotten into us? The point was that it didn't work...
My personal guess is that you wreck the stack in some way, or don't realise that your program is in fact doing as it should (might not apply, but I have seen numerous people doing that).
Candy wrote:Are we optimizing a 7-byte program to a 4-byte program now? What's gotten into us? The point was that it didn't work...
Heh. Well, I thought the problem might be he wasn't expecting a continuous stream of INT 33's -- the fact that the code could also be optimized was supposed to be secondary.
I'm sure the fact that I'm obsessive-compulsive about wasted RAM has nothing to do with it... [You try squeezing useful programs into 64K of address space for a few years, see how your sanity stands up...]
Maybe I'm missing something here, but why is it necessary to modify the instruction stream just to kill a process? Why not implement a system call for this purpose? The process makes the system call, the kernel gets control and realizes that it shouldn't schedule that process any more, cleans it up, and it never runs again... Your user-mode run-time library should be responsible for making the call after "main" (or its equivalent) returns.
Top three reasons why my OS project died:
Too much overtime at work
Got married
My brain got stuck in an infinite loop while trying to design the memory manager