Hi Shikhin,
Shikhin wrote:I think I fixed that in the
latest revision of the Gist. The LBA is now stored at 0x503, while the block (for int 0x13) is stored at 0x507.
I can't find the original info, but I've found something else that suggests the byte at 500h is part of the BDA, stating that it holds a PrtScr key status byte
http://computer-programming-forum.com/4 ... 3602b7.htm. It may be that on some machines pressing that key could overwrite the stored drive number, so if I was you I'd move the storage array up by a byte, which will align all the contents more neatly into the bargain (though the microscopic speed gains in accessing them won't be recognisable).
Unfortunately, I still haven't gotten into the habit of creating virtual drives, putting a MBR on it, and putting Selfer into a VBR. It took a lot of experimentation to get it working with a pen drive in the first case -- right now, it's a bit too tough to do it again. Could you test if it's completely fixed, now?
I didn't test it before as I didn't want any bug writing to the flash drive if things went wrong, but as you've changed it it should be fine now. I'll test it now, but I can already see that it will work as that bug's gone. I wouldn't use the LBA version with virtual drives at all as it would take up a lot of space storing it all - the idea is to use it on real hardware which is a much more rewarding environment to work in, just so long as you don't damage it. QEMU lets you test everything in an emulator from a real flash drive first though, so you can get the best of both worlds.
What I do is start with a new flash drive and go into the MBR using a hex editor. I look at the partition table, and usually there's just the one entry specifying a FAT32 partition. I reduce the size of the FAT32 partition and create a new partition to sit in the reclaimed space. Bytes 05h-07h in the FAT32 partition's entry need to be changed to a new top CHS address for the partition. Bytes 0Ch-0Fh also need to be changed to the start LBA of the new partition minus the value that's already sitting in bytes 08h-0Bh. With larger flash drives (e.g. 16GB) the new CHS value is likely to be FE FF FF.
The second table entry will start with 80h followed by the CHS for the start of the new partition, then perhaps 82h (any value that Windows doesn't care for will do) followed by the CHS for the end of the new partition. The next four bytes are the LBA for the start of the new partition and the four bytes after that are the size of that partition. Use the original top of the original partition as the new top of the new partition - don't move it upwards even if the size of the drive suggests there's more space above there as there may be a good reason for that space not being used.
The next step is to open the drive as a logical drive instead of a physical drive and to put in a new number of sectors for the FAT32 partition at 20h of the BPB (this will be the same value as used in the last four bytes of the first partition table entry). The FAT32 partition can then be formatted in Windows to make it fit the reduced space properly. The only other thing you need is standard MBR code to boot up the bootable partition and point DS:SI at the correct table entry. Oh, and you obviously have to paste Selfer into the right place as well.
The new partition should start at an LBA location which is a multiple of 1024 so that wear can be measured more easily. Some flash drives take seconds to save when you use the BIOS, so if the one you're using is unresponsive, it's really best to avoid using it for anything that saves through the BIOS. I've tried a number of different types and Sandisk ones respond well: I prefer the type that only stick out a few millimetres as they're 99.9% less likely to be leant on sufficiently hard by the user to do damage. 200MB would be a good size for a multifloppy partition, though I use nearer a gigabyte. It really depends on how much you intend to use Selfer: for building a few tools on top of it you won't need more than 200MB, but for a serious attempt to build an OS with it you'd want a lot more. With my OS I tend to plug in two or three flash drives plus an SD card and sometimes a USB floppy disk drive as well, and the BIOS allows me to boot my OS from any of these and then for the booted one to boot up any other version of itself from any of the other drives (which often means that they boot using drive numbers 82h, 83h and 84h, 81h being used for the internal hard drive). I can also use any version of my OS to boot up an MBR on the same or another drive, and to do so with the debugger active. That kind of functionality could also be added to Selfer, though of course it always depends on the BIOS of the machine you're using as to whether all these things are going to be possible on it - some may restrict you to using a single flash drive.
I have no clue on that error -- since I assume the state of a lot of registers in Selfer (e.g. "this was set to X here, that was set to X there, this xor that is zero, and oh! neat, it's also required in a BIOS call, and the BIOS call isn't expected to touch that register, so wait, I can inc it here, and I get 1 in the register!"), a small little error in the dummy entry could cause very much unexpected behavior.
I still don't understand the problem so I'll have to look at it carefully. The only thing wrong in the dummy table entry was the LBA, so it should simply have loaded in the wrong sectors without causing any other problems, and yet the result was that it saved sectors and moved the cursor to the right when x was pressed. I'll have to explore it to find out exactly why that happened because putting in the right LBA value shouldn't be able to cure it, even though it appears to do just that. It's just possible it was loading in something with a nop at 7E00 and leading to it running something that caused havoc.
However, for Selfer, we don't have the space to not trust the BIOS.
Moving the saving of DL and the LBA ahead of it would still be safer, and if it takes more bytes to do so, there are some that can be won back:-
Code: Select all
push bp
push si
push ds
push es
call bx
.RetRun:
pop es
pop ds
pop si
pop bp
BP and SI can be done in one go with a single byte, along with all the other registers, and restored in the same manner. I see that pushad gets a prefix and takes two bytes, so I'm guessing there's a pusha or pushaw instruction that doesn't generate the prefix.
Also, if you look above the cmp al, 'M' part of the program, there are five jumps to .Next which use three bytes for their jump rather than two. If you put in a label just above the jmp .Next in the .IncrementPointer part of the program, the five jumps to .Next higher up can be diverted to that new label instead which they can reach with just two bytes instead of three, thereby saving five bytes.
Heh, I thought you had written an extension to Selfer to add a neat debugger. A little disappoint, there.
It could be added to Selfer - it was written in machine code and a modified version could be typed in while using Selfer. Alternatively it could be treated as a binary blob and code could be added to Selfer to load it into the place in memory where it's designed to sit (00080000h). That would probably be the best way to do it as it would be easier to upgrade it to later versions (the current version can only handle real mode and a text screen as was designed primarily to help debug MBRs and VBRs) - there's probably no need to be too much of a purist about everything being written through Selfer when it's effectively been written in the same manner already and so there's no harm in avoiding the pointless task of typing it all in again.
I'm not too sure what standard specifies having the name of the partition at 0x03? Or is that simply a suggestion to make storing multiple versions of Selfer neater?
If names are to show up in the list, they have to go somewhere so a place must be chosen. If there's no BPB, there's no telling where any name will be, but I just decided always to put 11 bytes of some kind of name in at 03h with all my VBRs to make it easy for anyone looking at them through a hex editor to find out what they are. 8 bytes or even just 6 bytes of a name would do the job though, and if there are only 6 they could start at 05h instead and have exactly enough room for a far jump to go in front of them to make CS=0, so no space is wasted. The bytes at 03h and 04h would also conveniently be zeros and would therefore display neatly as spaces instead of random mess.
As for a fancy MBR to do that, I suppose one could extend Selfer such that it does that itself. You appear to be a born machine code programmer, so I'd imagine you can do it, right?
You don't need a fancy MBR to do it - the MBR only needs to boot up the first subpartition and doesn't need to know anything about subpartitions at all. It would then be for extra code in the second (or some later) sector of Selfer to provide the means to display a list of subpartitions and their contents while offering to boot any of them which are bootable. At that point, Selfer behaves like a fancy MBR when booting up other versions of itself.
Amazing screenshot, anyhoo.
Thanks, but it's really fairly simple code which could potentially be added to Selfer, so what I might now try to do (if it doesn't take up too much time) is build a second sector for Selfer which does all that stuff, relying on using autorun (putting a nop at 7E00) to patch a jump into the two nops in Selfer (which are currently still in the wrong place) to extend the functionality.