I'm trying to write a second stage boot loader that basically runs in Real Mode.
I have no problems with handling data so far, but I can see I'm going to have limitations with the code itself.
I need to add code for reading partitions, initializing some hardware, reading and maybe writing files and detection routines for doing stuff more transparent from specific hardware. I'm sure that there will be soon a point where this program will exceed the 64K.
I'm pretty much in the darkness in things like whether the assembler (YASM or NASM) will help me somehow manage far calls and far jumps, etc., or what part of it I should keep track of manually, as I have only ever made small 16-bit binary programs or EXE files using compilers, as well as some regular 32 and 64-bit code.
Does anybody know effective ways to make such a program (raw 16-bit code) stable, manageable, and most importantly, fully reachable for any arbitrary parts of the program itself, no matter if it spans several 64K segments?
16-bit Code > 64K
16-bit Code > 64K
YouTube:
http://youtube.com/@AltComp126
My x86 OS/software:
https://sourceforge.net/projects/api-simple-completa/
Donate to get more food/programming resources/computers:
https://www.paypal.com/donate/?hosted_b ... QS2YTW3V64
http://youtube.com/@AltComp126
My x86 OS/software:
https://sourceforge.net/projects/api-simple-completa/
Donate to get more food/programming resources/computers:
https://www.paypal.com/donate/?hosted_b ... QS2YTW3V64
Re: 16-bit Code > 64K
The easist thing to do is to modularize in time. That is, you set up your code in steps that need to be run. Step1, Step2, Step3. The code for each of those steps gets loaded into separate segments, but each of them is still under 64K. Then you run through them sequentially with one far jump between each (or maybe relocate them sequentially into one segment).
Alternately, to make it manageable, modularize the program into a small number of pieces. (And no, the assembler will not help you out at all.)
You simply must know that function foo() is in segment 1, and use a far call to segment 1:foo. foo() will need to use a far ret to return -- so even calls from within segment 1 to foo() will need to be far calls.
Alternately, to make it manageable, modularize the program into a small number of pieces. (And no, the assembler will not help you out at all.)
You simply must know that function foo() is in segment 1, and use a far call to segment 1:foo. foo() will need to use a far ret to return -- so even calls from within segment 1 to foo() will need to be far calls.
Re: 16-bit Code > 64K
As said the assembler might not be very helpful, you might be lucky to have one that can tell whether a function should be called using far or near call.
What you can do is to split data and code into separate segments if that would help (you then get to the point where the code or data exceeds it's 64K boundary).
If the code exceeds the 64K boundary you want to modularize the loader in some way, perhaps you have device drivers embedded which could go in their own segment. Anyway as you probably realized you want to keep the calls between modules few.
If data exceeds 64K boundary you might want to do a object oriented style keeping the current object directly reachable (fx via the ds register). Keep in mind though that ds in not always the default segment register that is used when accessing memory.
What you can do is to split data and code into separate segments if that would help (you then get to the point where the code or data exceeds it's 64K boundary).
If the code exceeds the 64K boundary you want to modularize the loader in some way, perhaps you have device drivers embedded which could go in their own segment. Anyway as you probably realized you want to keep the calls between modules few.
If data exceeds 64K boundary you might want to do a object oriented style keeping the current object directly reachable (fx via the ds register). Keep in mind though that ds in not always the default segment register that is used when accessing memory.