Hi Shikhin,
"Nasm Selfer.asm -o Selfer.flp -Ox" worked, though Bochs couldn't find it until I changed the file into .img, but I'm there now. (I used the hexdump first though as it's much quicker.)
Shikhin wrote:It goes from red to white; but I can change the color scheme. Try it out.
A bit too much of a contrast there for me, but the best solution would simply be to provide in the manual the address(es) of the byte(s) which control the red colour and let users change it to a colour value they prefer. My guess is that a brighter colour closer to white would look less stark, such as cyan, yellow or magenta (which are twice as bright as blue green and red).
The fix I see is that, after entering one keypress (which isn't any special function like copy/paste), if the user enters "ESC", the first keypress is ignored. I already have two bytes to spare, so I guess I only need two or three more bytes to implement that. Freeing two or three bytes, on the other hand, would be tough...
Esc after one accidental key press should catch most mistakes, so it's a huge improvement.
Yes, moving them to the function keys seems more sensible. I'll do that.
Or let the user change them, though I don't know what values the Function keys return in AL and it may be to expensive to switch to using the scancode values in AH, so I'm guessing that you haven't moved them there yet for that reason. Even so, accidental key presses are more likely to be keys round the edge or next to keys you're meant to be pressing. K, L and ; are probably the least likely keys to be pressed by mistake, so the user could modify the program to use those for copy, paste and run if they know the addresses to write the new values to (which they would be doing from within Selfer and not with the source code).
Shikhin wrote:
[*]It doesn't clear the value of EBP and ESI, which means that the if you "far ret" back into the loop, you land into the same sector. Thus, you can now observe changes and such that you write in the same sector. Obviously, this would mean placing a restriction on the user code -- while, now, you can mess with the stack as much as you want, you'd need to save and restore EBP and ESI. You shouldn't have much of an urge to modify EBP in the first place. If you want to modify ESI, just push and pop it back? This, though, means that you can debug and the like.
So long as the user knows to save and restore them it should be fine. If they are only using BP and SI rather than EBP and ESI, pushing and popping BP an SI would be sufficient. I used to use EBP extensively as a general purpose register, but I now use it primarily to point directly at blocks of local variables so that as many routines as possible can be re-entrant (and without having to move values onto the stack and back off it again), but there's no barrier to this as BP can simply be saved on the stack at the start and restored before the ret.
There's still an awkward limitation in that results can only be seen if they're posted into the sector you're viewing when you press r, but there's a workaround for that as you can use one sector as a debugging space and run the code you're testing with a far call from there with all the results being posted back to the debug sector. Another option would be to write code to display results to a free area of the screen, but it's much easier just to post results into memory and to examine them via the existing display routine.
So, can we call it a day?
It's getting into the area of diminishing returns - more and more work would be needed for less and less gain. The system you've designed for loading and modifying sectors was an interesting experiment, but I think it causes most of the problems, and it would still wear a flash drive excessively. I'd prefer to press w once or twice per session to save all my work in one go and not have things being saved and loaded automatically every time I make a small modification and take a quick look at another sector. Changing that might also win back some space, and limiting the active working zone to the first segment of memory could also simplify things while still leaving plenty of room to develop an operating system. However, the way you've done things is interesting precisely because it's so different form the way I built mine, and the most important thing is that it also works. I think this may well be the right time to stop, so you could maybe round it off by writing a final version of the manual.
The manual's already been written of course, but there are a few things missing from it. The user shouldn't need to understand the code in Selfer at all, but (s)he might like to know which byte(s) need to be changed to modify the display colour and which bytes need to be changed to move the w, k, p and r functions to different keys of their own choosing (so that they can do it within Selfer rather than modifying the source code). The most important missing information is details of where it would be best to patch in a jump/call to make it bypass Selfer's display code and boot up the user's operating system directly (once the user has built enough of an OS for it to support itself), at which point Selfer would serve as a loader.
Oh, and once you've settled on the final version, make sure you comment all your code properly - I still haven't managed to find my way through a lot of it and can't work out how it loads everything in in the first place. I think I'm going to have to look at the machine code in decimal form before I can follow it all...
Oh - that's a big problem! I haven't looked at it in decimal form, but I've done a new experiment in Bochs just to check something and I now realise why I couldn't see where it loads everything at the start - it's because it doesn't load anything at the start at all. The only way to run any OS which you build with Selfer is going to be to use Selfer to scroll down through it first (or at least into the second sector) before you can jump into its code. I thought from my earlier experiments in Bochs that it loaded everything up front, but I realise now that values were simply being retained in memory in Bochs and weren't being loaded in again by Selfer (reset in Bochs is not like pressing the reset button on a real machine as it preserves memory content).
That's it settled then - I think you are going to need to redesign the system for loading & saving code. It needs to load a large chunk of memory on booting (e.g. from 7E00 to FFFF of segment 0) and then to save that whole chunk (plus the bootsector) back to disk when the user presses w. The bootsector will also need to be saved so that it can be modified from within Selfer and for those modifications to remain in place. (I avoided the need for any modifications to the bootsector in BwtSecOS to be saved by making it run the code at the start of the second sector automatically if the second sector starts with a nop, but Selfer in its current form would need to have a jump/call patched into it and for the change to be saved.)
I don't know if you're still going to want to finish this project now as you doubtless have other fish that need frying, but changing the way it saves would make it a lot more flash-drive friendly. What you've already built is already a really good demo though, so the option is there just to declare the job as good enough and leave it as is. It would be hard, but I think there is enough there for someone to build an OS and to patch the bootsector with new load code at some point so that Selfer would effectively be replaced with a loader designed specifically for the new OS - they'd need to write their own display & edit code, then hack the bootsector with it and save the result using their own code too, and then they'd have to hope it all works first go.