This header file is to make for a simpler translator for a RealC compiler, but also to select the full width of registers automatically, as well as including the a32 or o32 prefixes where needed.
You can see what's happening at all times with this and you can choose to use automatic or manual combinations of instructions freely.
You can use binary numbers unlike C, C++ and above (as far as I know something like 11111111b cannot be used in standard C).In this way I can port the exact same application code to 4 different modes, so if I design the code well I can efficiently use the same implementation in pure 16-bit mode, in 16-bit Unreal Mode with 32-bit instructions, in 32-bit mode and in 64-bit mode.
The good thing is that the compiler always outputs to NASM/YASM assembly code. Currently it takes a list of all the CSM files of the project (containing C-like source code) and returns an ASM file for each CSM file with ASM extension.
I could rewrite a full-Assembly project in RealC and it could become more manageable.
alexfru wrote:
RealC? C syntax? lol. I wish there was RealC++. Human-perceptible, that is. I've had quite a bit of fun with C++ ODR violation at work today. The source code looks OK at first sight, no compiler diagnostic, but things don't quite work.
Yes, I think I'm sure now that it will be the right thing to present my code, documentation and tutorials in Assembly and RealC for the lowest-level code, to make it more portable.
To create a language that lokks like C++ to translate directly to clean and brief Assembly, we would need to start finding out which are the simplest techniques that C++ actually uses internally, that translate directly between the ideas, the C++ source code and the Assembly translation keeping the same basic structure. With the simplest elements and techniques that behave more naturally and conveniently like objects than as procedural code, we could build such language and compiler to manage them as well without the need of a more complex compiler, linker and support run-time library, because we would be using implicit functionality that is always present (it will need experience and creativity).Just like in 64-bit mode and higher-level languages like C, the use of segment registers shouldn't be normally present in normal code, just in another set of wrapper functions that take care of them to keep clean the rest of the code base so it can work the exact same for pure 16-bit, 16/32-bit Real/Unreal Mode, 32 and 64-bit modes.
RealC can directly switch between C syntax and NASM/YASM inline assembly for single-line or multiple-line code, like this:
Code:
//This is a binary variable with the full register width of the
//currently selected CPU mode to use for assembling the code:
///
wideword GPR_registers_clear=0;
function clear_GPR_registers()
{
asm {
xor wideax,wideax
xor widecx,widecx
xor widedx,widedx
xor widebx,widebx
xor widesp,widesp
xor widebp,widebp
xor widesi,widesi
xor widedi,widedi
}
//The code below can produce
//mov wideword[__r8],0, etc..., for 16 and 32-bit mode,
//or directly "xor r8,r8", etc... in 64-bit mode:
///
$R8=0;
$R9=0;
$R10=0;
$R11=0;
$R12=0;
$R13=0;
$R14=0;
$R15=0;
wideword[GPR_registers_clear]++;
}
One of the most important and heaviest features not found in regular NASM is the capability to gather many memory variables enclosed in brackets [] and gather constants correctly from one same instruction referencing a single memory address, to solve a nested expression involving + - * / %, bitwise and logical operators in the same code line.
Personally, to perform type cast I would, for each variable, reserve as much space as the biggest type to cast to, and then reading the whole variable or overwriting it for type-casting it would be much more efficient. It's manual but it's simple enough as to be done manually in this way.
I think that I will implement x86_Portable_SIZEOF_** for being able to also get the size of basic known data types.iansjack wrote:
The point of assembler, IMO, is to get as close to the hardware as possible. I don't see the point in the compromises necessary in this sort of half-way house towards a proper high-level language. Use C if you can't cope with assembler and the techniques necessary for different processor modes.
The point is to really make writing low-level Assembly code as stable, predictable, portable and simple as a scripting language, like JavaScript, which will simplify its usage. The point is scripting low-level programming to make it more practical but still equally clean and efficient.
I can cope with assembler, even if I still don't know everything there is to understand to implement the most clever and space-efficient optimizations.
This language is good at separating the tasks that are implemented the cleanest in C to implement them in C, the tasks that are implemented the cleanest in pure Assembly to implement them in pure Assembly, the tasks that are implemented the cleanest in portable Assembly (RealC) in RealC, the tasks that are implemented the cleanest in C++ to implement them in C++. From there it's easy to see which other languages really correspond to other tasks by nature, and prioritize the use of the proper language for a proper task, in its genuine form.
This language is actually a set of techniques to make the lowest-level code directly portable and still controlling the real low-level details. It's easy to know that "wideword" will resolve to 16, 32 or 64 bits. So it could be a lot more convenient to use it instead of C or raw Assembly, for tasks and applications mainly geared to the actual lower-level tasks of a system. It's direct as Assembly and portable as C, but it's simpler and allows for all the manual options than those, in those areas (direct access, portability and simplicity).I could rewrite a full-Assembly project in RealC and it could become more manageable.
The point is:
- Being able to write much more complex code more easily, but while actually still continuing to keep the small footprint of assembly since we are really programming in it with a sort of pseudocode that can be translated to Assembly.
- Keep direct and full control of absolutely all low level aspects of the machine without additional layers to compile while using more human-readable syntax. It's extremely useful for the general code's application. We could as well use an
asm{} block from start to end in all source files, enclosing the whole code there and write directly in assembly, without using the portable wide**** register and word names, but the code would be less portable between modes.
- Distinguish the simplest techniques and elements that can be directly integrated in Assembly code to make it portable without using much higher-level compilers and a linkers, to compile without changes to the main application using the same source code.
- Being able to write full application programs in Assembly without getting ugly code when dealing with very complex conditional decisions that would implement an IF, loops, or other conditionals.
- It now allows being about to port the same Assembly code, like important legacy demos and applications to all CPU modes if we think carefully about how to write the program. It it's well-designed, it would be easy to port something like a DOS system, from 16 bits to 32 and 64 bits, and it would still be programmed in Assembly/RealC.
I can say that this combination allows to generate more complex Assembly code.
I have written all of my test kernels in pure Assembly and a bit of RealC, and I haven't needed a linker and I still can export and import functions at run time.
It minimizes the need for a linker a lot. I guess that such minimization of using a linker and being able to only use a small compiler/language and standard NASM/YASM/Intel syntax simplifies things while getting close to the machine.