Making x86 Assembly Language Portable

Programming, for all ages and all languages.
Post Reply
User avatar
~
Member
Member
Posts: 1226
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Making x86 Assembly Language Portable

Post by ~ »

After a lot of development in x86 assembly language and after development efforts of my RealC language (which is basically x86 Assembly with C syntax instead of AT&T or Intel one), I have developed a small project that allows making assembly language much more portable.

For example, I can select automatically the maximum size of the general-purpose registers or machine word size. In can also cautiously treat registers r8 to r15 as memory variables so that most of the code that use them doesn't break but just downgrades to 16 or 32-bit words.

Now I can do something like:

Code: Select all

xor wideax,wideax

push wideax

rep inswide
rep outswide

awide rep stoswide  ;instead of a32 rep stosd, for Unreal Mode for example

;...etc....
The following is the main and starting skeleton of the idea I have.

Main ''x86 Portable Project'' Page
Main ''x86 Portable Project'' Page
Main ''x86 Portable Project'' Page
Main ''x86 Portable Project'' Page

Image Text recording for 0000000__x86_Portable.asm
Image Text recording for 0000000__x86_Portable.asm
Image Text recording for 0000000__x86_Portable.asm
Image Text recording for 0000000__x86_Portable.asm

Live source code:
http://www.archefire.org/_PROJECTS_/x86_Portable/v2016-06-15/src/
http://www.archefire.org/_PROJECTS_/x86_Portable/v2016-06-15/src/
http://www.archefire.org/_PROJECTS_/x86_Portable/v2016-06-15/src/
http://www.archefire.org/_PROJECTS_/x86_Portable/v2016-06-15/src/


Here is the source code, although the text recording and the real source code should be used instead because the following will surely get outdated, but I put it just for convenience, to show the initial state of this project:

Code: Select all

;Set the default mode of x86 Portable to work under
;16-bit Unreal Mode (with access to 4 GB of address space):
;;
 %ixdefine _x86_Portable__PLATFORMBITS_ 1632


x86_Portable_START:

;Include a JMP instruction so that we can include this source file
;anywhere in a NASM/YASM assembly source code without causing failures
;due to the embedded data bytes here:
;;
 align 16
 jmp x86_Portable_END
 align 16

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%if _x86_Portable__PLATFORMBITS_==16     ;16-bit 8086 code

 %ixdefine wideword    word
 %ixdefine wideword_SZ 2

 %ixdefine wideax    ax
 %ixdefine widecx    cx
 %ixdefine widedx    dx
 %ixdefine widebx    bx
 %ixdefine widesp    sp
 %ixdefine widebp    bp
 %ixdefine widesi    si
 %ixdefine widedi    di

 %ixdefine _r8       word[__r8]
 %ixdefine _r9       word[__r9]
 %ixdefine _r10      word[__r10]
 %ixdefine _r11      word[__r11]
 %ixdefine _r12      word[__r12]
 %ixdefine _r13      word[__r13]
 %ixdefine _r14      word[__r14]
 %ixdefine _r15      word[__r15]

 __r8  dw 0
 __r9  dw 0
 __r10 dw 0
 __r11 dw 0
 __r12 dw 0
 __r13 dw 0
 __r14 dw 0
 __r15 dw 0


 %ixdefine awide
 %ixdefine owide


 %ixdefine cmpswide  cmpsw
 %ixdefine lodswide  lodsw
 %ixdefine stoswide  stosw
 %ixdefine movswide  movsw
 %ixdefine inswide   insw
 %ixdefine outswide  outsw


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%elif _x86_Portable__PLATFORMBITS_==1632   ;16-bit Unreal Mode

 %ixdefine wideword    dword
 %ixdefine wideword_SZ 4

 %ixdefine wideax    eax
 %ixdefine widecx    ecx
 %ixdefine widedx    edx
 %ixdefine widebx    ebx
 %ixdefine widesp    esp
 %ixdefine widebp    ebp
 %ixdefine widesi    esi
 %ixdefine widedi    edi

 %ixdefine _r8       dword[__r8]
 %ixdefine _r9       dword[__r9]
 %ixdefine _r10      dword[__r10]
 %ixdefine _r11      dword[__r11]
 %ixdefine _r12      dword[__r12]
 %ixdefine _r13      dword[__r13]
 %ixdefine _r14      dword[__r14]
 %ixdefine _r15      dword[__r15]

 __r8  dd 0
 __r9  dd 0
 __r10 dd 0
 __r11 dd 0
 __r12 dd 0
 __r13 dd 0
 __r14 dd 0
 __r15 dd 0


 %ixdefine awide     a32
 %ixdefine owide     o32


 %ixdefine cmpswide  cmpsd
 %ixdefine lodswide  lodsd
 %ixdefine stoswide  stosd
 %ixdefine movswide  movsd
 %ixdefine inswide   insd
 %ixdefine outswide  outsd


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%elif _x86_Portable__PLATFORMBITS_==32    ;32 bit x86 Protected Mode code

 %ixdefine wideword    dword
 %ixdefine wideword_SZ 4

 %ixdefine wideax    eax
 %ixdefine widecx    ecx
 %ixdefine widedx    edx
 %ixdefine widebx    ebx
 %ixdefine widesp    esp
 %ixdefine widebp    ebp
 %ixdefine widesi    esi
 %ixdefine widedi    edi

 %ixdefine _r8       dword[__r8]
 %ixdefine _r9       dword[__r9]
 %ixdefine _r10      dword[__r10]
 %ixdefine _r11      dword[__r11]
 %ixdefine _r12      dword[__r12]
 %ixdefine _r13      dword[__r13]
 %ixdefine _r14      dword[__r14]
 %ixdefine _r15      dword[__r15]

 __r8  dd 0
 __r9  dd 0
 __r10 dd 0
 __r11 dd 0
 __r12 dd 0
 __r13 dd 0
 __r14 dd 0
 __r15 dd 0


 %ixdefine awide
 %ixdefine owide


 %ixdefine cmpswide  cmpsd
 %ixdefine lodswide  lodsd
 %ixdefine stoswide  stosd
 %ixdefine movswide  movsd
 %ixdefine inswide   insd
 %ixdefine outswide  outsd


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%elif _x86_Portable__PLATFORMBITS_==64       ;64-bit Long Mode code

 %ixdefine wideword    qword
 %ixdefine wideword_SZ 8

 %ixdefine wideax    rax
 %ixdefine widecx    rcx
 %ixdefine widedx    rdx
 %ixdefine widebx    rbx
 %ixdefine widesp    rsp
 %ixdefine widebp    rbp
 %ixdefine widesi    rsi
 %ixdefine widedi    rdi

 %ixdefine _r8       r8
 %ixdefine _r9       r9
 %ixdefine _r10      r10
 %ixdefine _r11      r11
 %ixdefine _r12      r12
 %ixdefine _r13      r13
 %ixdefine _r14      r14
 %ixdefine _r15      r15


 %ixdefine awide
 %ixdefine owide


 %ixdefine cmpswide  cmpsq
 %ixdefine lodswide  lodsq
 %ixdefine stoswide  stosq
 %ixdefine movswide  movsq
 %ixdefine inswide   insd
 %ixdefine outswide  outsd



%endif

x86_Portable_END:




;EOF
Last edited by ~ on Thu Jun 16, 2016 1:12 pm, edited 1 time in total.
YouTube:
http://youtube.com/@AltComp126

My x86 emulator/kernel project and software tools/documentation:
http://master.dl.sourceforge.net/projec ... 7z?viasf=1
alexfru
Member
Member
Posts: 1111
Joined: Tue Mar 04, 2014 5:27 am

Re: Making x86 Assembly Language Portable

Post by alexfru »

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.
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Making x86 Assembly Language Portable

Post by iansjack »

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.
User avatar
~
Member
Member
Posts: 1226
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: Making x86 Assembly Language Portable

Post by ~ »

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: Select all

//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.
YouTube:
http://youtube.com/@AltComp126

My x86 emulator/kernel project and software tools/documentation:
http://master.dl.sourceforge.net/projec ... 7z?viasf=1
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Making x86 Assembly Language Portable

Post by iansjack »

GCC lets you use binary literals as do several other C compilers. (Although hex is really just a super form of binary and is better for most purposes.)

I've no problem with you inventing a new language, it's just of no use to me.
User avatar
~
Member
Member
Posts: 1226
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: Making x86 Assembly Language Portable

Post by ~ »

iansjack wrote:GCC lets you use binary literals as do several other C compilers. (Although hex is really just a super form of binary and is better for most purposes.)

I've no problem with you inventing a new language, it's just of no use to me.
That's good to know. I have tried several times to use binary literals like "00000000b" and it fails. It's probably a recent version of GCC or G++.

If there was a language that integrated portability in itself in the syntax and keywords without using any other external resources directly down to the actual details of the underlying machine to accounting for them in a platform-independent way, then there would probably be no need for cross compilers for that, and linkers would only be used to link object files and import/export stuff, but they would be less used.


I think that the actual programming language is the best place to take care of all hardware platform-dependent details, and even software ones, and select them automatically with the possibility to also do so manually.

In this way, we can translate from one to another without adding more stuff.

I don't think that a linker, preprocessor, run-time library or header files are really thought to solve differences between platforms. They must have been thought to define libraries with a complete degree of flexibility and some version/OS/environment detection.

But if they are used like that to take care of the different hardware details is because there's no language that properly integrates those details in a portable/adjustable way in its syntax and instructions themselves.

Anyway, with a fully-portable assembly language with C syntax, the C environment itself can be made even more portable without modifying the language, but also using it to implement portable applications that are natively compiled, which don't really take care of hardware details in a truly portable way (as evidenced by the constant use of C and assembly in important quantities).
Last edited by ~ on Thu Jun 16, 2016 12:24 pm, edited 1 time in total.
YouTube:
http://youtube.com/@AltComp126

My x86 emulator/kernel project and software tools/documentation:
http://master.dl.sourceforge.net/projec ... 7z?viasf=1
Techel
Member
Member
Posts: 215
Joined: Fri Jan 30, 2015 4:57 pm
Location: Germany
Contact:

Re: Making x86 Assembly Language Portable

Post by Techel »

C++14 has binary literals:

Code: Select all

0b1010101
embryo2
Member
Member
Posts: 397
Joined: Wed Jun 03, 2015 5:03 am

Re: Making x86 Assembly Language Portable

Post by embryo2 »

iansjack wrote:I've no problem with you inventing a new language, it's just of no use to me.
It's developer's inertia. We are too lazy to learn new ways of doing things just because we can do things with the knowledge we already have. That's why new language or a tool should be very impressive to excite developers and penetrate their laziness armor.
My previous account (embryo) was accidentally deleted, so I have no chance but to use something new. But may be it was a good lesson about software reliability :)
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Making x86 Assembly Language Portable

Post by iansjack »

I'm sorry, but I think that is a silly analysis of my position. Just because someone comes up with a new language doesn't mean every developer has to jump on a bandwagon to use it.

I judge new tools by what they can offer me. I've never been in favour of the various wrappers round assembly to make it a half-way house to a high-level language and this one offers me nothing new. I think it misses the whole point of using assembly if you imply that the differences between 16-, 32-, and 64-bit code can be covered by a handful of macros. I use assembler when I want to do things that can't be done in a high-level language or when I want to optimize small portions of code. I can't see this fulfilling either of those needs.

It's not a question of inertia or laziness; it is a question of choosing tools critically.
User avatar
~
Member
Member
Posts: 1226
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: Making x86 Assembly Language Portable

Post by ~ »

iansjack wrote:I'm sorry, but I think that is a silly analysis of my position. Just because someone comes up with a new language doesn't mean every developer has to jump on a bandwagon to use it.

I judge new tools by what they can offer me. I've never been in favour of the various wrappers round assembly to make it a half-way house to a high-level language and this one offers me nothing new. I think it misses the whole point of using assembly if you imply that the differences between 16-, 32-, and 64-bit code can be covered by a handful of macros. I use assembler when I want to do things that can't be done in a high-level language or when I want to optimize small portions of code. I can't see this fulfilling either of those needs.

It's not a question of inertia or laziness; it is a question of choosing tools critically.
It's excellent to know that the code of normal applications written fully in x86 assembly can be directly ported if just it's well thought and if the low and high level details are kept separated. It shows how well designed the x86 CPUs and its machine code is implemented, and I'm just taking advantage of those resources.

This header file is to be used when the code is produced by the compiler. The concepts that it is handling are powerful enough as to not need more definitions to make the actual x86 bassembly language, portable. The problem at hand requires as much and as little as this in its root. In other words, it seems that CISC CPUs need very little from the point of view of native programming languages to be used, to make the code work without changes between all modes. The x86 CPU is the one that needs the least work to make it portable between its modes, apparently.

The RealC compiler handles things like "wideax" and "wideword" on its own since they are part of the language. It isn't really thought to generate too much additional code.


If a portable and truly low-level assembly language like RealC proves to be useful and well designed after a long period of time, then it will show how little is missing to make x86 machine language fully portable among modes through compiling the code for the right CPU mode.

It's just the beginning of a portability project (an assembly header file to handle differences and a compiler that can use C syntax with the level of assembly, which implies that it will also mix the C syntax with assembly syntax). This is the beginning, it's brief yet powerful because of the highly optimized x86 design. There's not much else to add until I think about more things to make portable.

I use assembly language to program at all levels. I can tell you that there are certain parts and tasks that are better suited by this language than by raw Assembly, specially if you need to use memory variables in IF constructs in specific ways and you don't want to use a compiler just for that but at the same time if it's hard to maintain in raw Assembly if you didn't have IFs.

Also, there are things that should be left in a low-level subsystem in the program, not mix such functions with the regular application code, or else it won't be portable either. If there are things like the need to handle 64 bits in pure 16-bit code, but at the same time we need to port the exact same program to 32 and 64-bit platforms, then there's no doubt that we need to include such functionality to the low level, non-portable engine of the program, to allow making the rest of the application fully portable.

Programming contains infinite needs and tasks, and as such there are things that the compiler won't be able to do properly and intelligently, and one of those things is determining what things to put in the low-level engine/s of the program and what to put in the fully portable parts of the, unless it's designed within the structure of the language itself, not the libraries nor the runtime but the language specification that will be used to write code, and even then it would only cover the most vital default cases so it would always be necessary to make the development of the low-level engine of each aplication manually as it's always normal, which ALWAYS exists in all programs, just because of them being machine code, as well as the rest of high-level, perfectly and fully portable functions.


It promotes code cleanliness a lot and you can keep using Assembly without a problem since the compiler produces ASM files. It also promotes using the language that corresponds directly to each task instead of another less suited one. In the base, there's no need to use more than Assembly, RealC (portable Assembly), C, and C++ at most.

There are other tasks that would more likely require data mining languages (to act depending on the data found), query languages (like SQL) and tagged languages like HTML and XML for presentation and simple description, but they are normally implemented in ASM/C/C++.
YouTube:
http://youtube.com/@AltComp126

My x86 emulator/kernel project and software tools/documentation:
http://master.dl.sourceforge.net/projec ... 7z?viasf=1
User avatar
~
Member
Member
Posts: 1226
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: Making x86 Assembly Language Portable

Post by ~ »

The x86 CPU is capable of automatically selecting the full word/register width for the current execution mode.

So why not implement the exact same thing for Assembly language source code so that the aseembler can also find out and select the full word width when we specifically want it in an easy way, as easily as the CPU itself?

Why not turn features like that into the features of a programming language so it doesn't lag behind of the run-time optimizations of the CPU, from its source code programming counterpart?

That's also extremely critical, but it shows how much computing is getting empoverished, unoptimized and even ignorant compared to the rest of sciences, which would treat things like this with much more seriousness. It's for abandoned or ignored details like that, that programs are much bulkier from their source code.

If we are realizing this fact, the solution should be used, and probably NASM and YASM could make use of this to integrate it directly into the assembler to make future code much more portable to get on par with the CPU (using wideword, wideword_SZ, and wide** registers to automatically select the full width when we use those).

...I should probably use aliases for RAX, RCX, RDX, RBX, etc... or maybe not. I should probably use the wider specific 64-bit registers in the low-level engine of the application to avoid breaking an application code.
YouTube:
http://youtube.com/@AltComp126

My x86 emulator/kernel project and software tools/documentation:
http://master.dl.sourceforge.net/projec ... 7z?viasf=1
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Making x86 Assembly Language Portable

Post by Combuster »

Iansjack is completely right.

So you made some small improvements to a steam locomotive. Power to you. Nevertheless they have zero use left other than being a gimmick.

However, do you think that people claiming that a utter lack of steam locomotives means the end of the world should not be stuck in an institute? Because that is exactly what you're doing here.

and unlike dementia, I hope your case is curable
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Making x86 Assembly Language Portable

Post by Solar »

embryo2 wrote:
iansjack wrote:I've no problem with you inventing a new language, it's just of no use to me.
It's developer's inertia. We are too lazy to learn new ways of doing things just because we can do things with the knowledge we already have. That's why new language or a tool should be very impressive to excite developers and penetrate their laziness armor.
That might be true for hobbyist / lab developers who might pick up a new language for its "exciting" value alone.

You will find that many developers, especially those outside academics, tend to have a much more practical approach, where "exciting" doesn't show up in the equation.

There are only so many hours in a day, and there are problems to be solved. There are languages solving those problems. Trying a new language brings several problems:
  • You don't know how well it can be applied to the problem, since it's new and there is little previous experience. You might end up in a dead end, having wasted time and effort on something that turns out to be inferior.
  • You don't know the language as well as what you did before. Initial code will be clumsy, probably less efficient at solving the problem than established languages / technologies, and you will have to invest time and effort to perhaps break even.
  • There is no readily available experience in the field. You won't find instruction material, tutors, let alone programmers skilled in the language. You are on your own. And anyone new to the team will first have to be trained in the new language before becoming effective.
  • You do not know if the language will actually take off, or remain a niche. You will have to leave additional documentation behind if your solution is supposed to be maintainable in the future. You might end up with a "dead" toolchain that is no longer supported, or breaking changes requiring additional effort in maintaining your solution.
That list is by no means complete. You can deride it as "developer inertia". But it's not lazyness, or an inability to learn, but a business / architecture decision. Return on investment.

That is why, for all their deficits, C++ and Java are here to stay. Their capabilities and limitations are well understood. There is a huge pool of documentation, tutors, and developers existing. (Chicken and egg: The existing codebase is huge, so people train for it, increasing the codebase.) Well-developed toolchains exist, and can be relied on to be supported well into the next decade. People can be hired who can get up-to-speed with an existing codebase in very short time.

Any new language needs to be disruptively effective to break through all that. Not because it's "exciting" or "impressive", but because it is a good architectural decision. Because it solves real problems in a really applicable way. Which, as I hope I have made clear, goes well beyond technical applicability.

----

PS: All of the above applies to operating systems, as well...
Every good solution is obvious once you've found it.
embryo2
Member
Member
Posts: 397
Joined: Wed Jun 03, 2015 5:03 am

Re: Making x86 Assembly Language Portable

Post by embryo2 »

iansjack wrote:I judge new tools by what they can offer me.
The idea is as such - you can have a continuum of gradually increasing abstraction instead of a few independent and separate abstraction levels. You can move freely along a road instead of jumping over a ladder.

If a particular road has some stones and dirt on it then it doesn't mean there can't be any better road. Proposed language is not ideal, but even in it's current state it can be used in some projects (not a big share, of course). But the idea can be used extensively in new tools and languages where the percentage of involved developers could be really noticeable. So, while the tool can't offer personally to you, it can potentially offer to many other people.

P.S. If you are unhappy about the word "laziness" then the next answer is also for you.
My previous account (embryo) was accidentally deleted, so I have no chance but to use something new. But may be it was a good lesson about software reliability :)
embryo2
Member
Member
Posts: 397
Joined: Wed Jun 03, 2015 5:03 am

Re: Making x86 Assembly Language Portable

Post by embryo2 »

Solar wrote:You will find that many developers, especially those outside academics, tend to have a much more practical approach, where "exciting" doesn't show up in the equation.
Excitement and laziness are the exact words that match the situation with "more practical" people.

What is the laziness? It's an evolutionarily evolved way of keeping resources safe for some better use. "Practical" people just do the same - they preserve the time they have for something they think is better. A job just must be done or you'll be fired, so "practical" people define their goal as "serious" and without any "excitement". But in the end it's just the same old way to "cut the costs" that a child uses when preserves his time for more exciting things than stupid "practical" and "serious" stuff.
Solar wrote:Trying a new language brings several problems:
  • You don't know how well it can be applied to the problem, since it's new and there is little previous experience. You might end up in a dead end, having wasted time and effort on something that turns out to be inferior.
  • You don't know the language as well as what you did before. Initial code will be clumsy, probably less efficient at solving the problem than established languages / technologies, and you will have to invest time and effort to perhaps break even.
  • There is no readily available experience in the field. You won't find instruction material, tutors, let alone programmers skilled in the language. You are on your own. And anyone new to the team will first have to be trained in the new language before becoming effective.
  • You do not know if the language will actually take off, or remain a niche. You will have to leave additional documentation behind if your solution is supposed to be maintainable in the future. You might end up with a "dead" toolchain that is no longer supported, or breaking changes requiring additional effort in maintaining your solution.
That list is by no means complete. You can deride it as "developer inertia". But it's not lazyness, or an inability to learn, but a business / architecture decision. Return on investment.
Of course, "seriuos" people can plan their actions. But less serious people can propose a list like this:
  • You can know how well it can be applied to the problem, despite it's new and there is little previous experience. You might end up in a dead end, having wasted time and effort on something that turns out to be inferior, but you certainly won't take the prize in all cases when something turns out to be superior.
  • You don't know the language as well as what you did before. Initial code will be clumsy, probably less efficient at solving the problem than established languages / technologies, and you will have to invest time and effort to perhaps break even. But it was exactly the same way when you had invested 10-15 years of your life in education. Or may be we should ask ourselves if it's perhaps break even?
  • There is no readily available experience in the field. You won't find instruction material, tutors, let alone programmers skilled in the language. You are on your own. And anyone new to the team will first have to be trained in the new language before becoming effective. But what about the benefit of being out of a crowd? Could Ford earn his billions doing the same stuff every college boy can do?
  • You do not know if the language will actually take off, or remain a niche. You will have to leave additional documentation behind if your solution is supposed to be maintainable in the future. You might end up with a "dead" toolchain that is no longer supported, or breaking changes requiring additional effort in maintaining your solution. So, may be every Edisson just have to stop playing with his inventions because it's probably could require some efforts to be spent? There's so much tedious work in the world and it should be done despite of any excitement, but it seems such job looks more attractive for serious people, because making inventions still requires "additional documentation", can be "no longer supported" and generally require "additional effort".
Solar wrote:That is why, for all their deficits, C++ and Java are here to stay.
No. They are still here because the alternatives are too weak. There's no excitement in them. And the excitement is another term we can discuss. Fo some "very serious" people the excitement is about finding a way to get a lot of money. For a child the excitement is about finding a beautiful shell on a beach. And for a developer the excitement can be of two kinds - to find a lot of free time with the help of a new technology and (second) to find a beauty in the process of doing the same well known things. Every person decides on his own what excites him, but when the person forgets about the excitement of beauty then his life becomes too dumb and senseless because of complete transition to the state of a biological automat without any idea about such things as feelings and emotions.
Solar wrote:Any new language needs to be disruptively effective to break through all that. Not because it's "exciting" or "impressive", but because it is a good architectural decision. Because it solves real problems in a really applicable way. Which, as I hope I have made clear, goes well beyond technical applicability.
Yes, you made it clear - any new language needs to be disruptively more profitable to excite some people. But how do you think such a transition can be made without intermediary small steps? It's a simple and very technical question - how can you get more money without trying many ways to get more money? Pure automat, only binary logic - profitable or not. And the logic tells me that there are venture capitalists who understand the technical perspective of the "excitement" and often they even are ready to invest. But why? There are so many problems ahead!
My previous account (embryo) was accidentally deleted, so I have no chance but to use something new. But may be it was a good lesson about software reliability :)
Post Reply