Page 2 of 2

Re: C and the GNU assembler: how to deal with structs?

Posted: Thu Oct 31, 2019 1:12 am
by ~
That's what you are doing.

You are thinking in assembler and implementing in C finally to increase portability of the assembly.

An idea is that you could create macros to select the size of data automatically depending whether the program is compiled for 16, 32 or 64 bits, and it would make your code portable further as now you won't need to change offset macros just for a global change in machine word size.

Re: C and the GNU assembler: how to deal with structs?

Posted: Thu Oct 31, 2019 12:34 pm
by nullplan
~ wrote:You are thinking in assembler and implementing in C finally to increase portability of the assembly.
I wouldn't go around assuming what other people are thinking. Unless you can read minds, you're liable to offend people.

Besides, the above is not a good strategy. C is not a high-level assembler. You do things very differently between the two. Reading long disassembly listings, I find I'm having trouble understanding loops, when in C there's no issue at all. On the contrary, I'm often thinking in C even when I have to implement something in assembler.

And the different architectures are not just different in word size. AMD64 and i386 have completely different ABIs. Not to mention the fact that some of us might have the ambition to one day branch out beyond the PC. Good luck writing your macros so they can accommodate PowerPC.

Re: C and the GNU assembler: how to deal with structs?

Posted: Thu Oct 31, 2019 9:45 pm
by ~
I always keep my OS code ready to be assembled to 32 and 64-bit modes (I check it often), even to 8088 and 386 16-bit. Anything that doesn't assemble or throws a warning, is a way to improve my code a big step more, as it lets me see what isn't really well thought in code, and just make it portable (for example use 0xFFFFFFFF instead of -1 as choosing between something like EAX and RAX without being absolutely specific will become nonportable).

Non-portable instructions like PUSHA/POPA can also be resolved through macros across all modes to generate compatible code instead without leaving it abandoned.

So the only thing left is separating the code into the parts that are just not portable across modes but that can be selected for each one; and the code that is so generic that can be ported with automatic macros to 16, 32 or 64-bit modes with absolutely no modifications (most of the code is like that); even to other platforms.

To take assembler portability beyond the PC, I plan to take the CPU instruction syntax and overall machine platform structure of my preferred architecture to any other as the absolute minimum that must always be present to recycle my work infinitely.

Re: C and the GNU assembler: how to deal with structs?

Posted: Thu Oct 31, 2019 10:58 pm
by Ethin
~ wrote:I always keep my OS code ready to be assembled to 32 and 64-bit modes (I check it often), even to 8088 and 386 16-bit. Anything that doesn't assemble or throws a warning, is a way to improve my code a big step more, as it lets me see what isn't really well thought in code, and just make it portable (for example use 0xFFFFFFFF instead of -1 as choosing between something like EAX and RAX without being absolutely specific will become nonportable).

Non-portable instructions like PUSHA/POPA can also be resolved through macros across all modes to generate compatible code instead without leaving it abandoned.

So the only thing left is separating the code into the parts that are just not portable across modes but that can be selected for each one; and the code that is so generic that can be ported with automatic macros to 16, 32 or 64-bit modes with absolutely no modifications (most of the code is like that); even to other platforms.

To take assembler portability beyond the PC, I plan to take the CPU instruction syntax and overall machine platform structure of my preferred architecture to any other as the absolute minimum that must always be present to recycle my work infinitely.
I'm certainly no expert at assembly but I doubt this strategy will work. There is no standard for defining what instructions an ISA may have. You cannot make macros that can handle every possible architecture you plan to port your code to, and you can't 100-percent guarantee that an instruction will be present on another platform, even if it is virtually the 'standard'. Platforms are allowed to define any instruction they so please -- and even make those instructions do whatever they want.

Re: C and the GNU assembler: how to deal with structs?

Posted: Fri Nov 01, 2019 12:50 am
by iansjack
I'd be interested to see how your paging code assembles on an 8088.

Re: C and the GNU assembler: how to deal with structs?

Posted: Fri Nov 01, 2019 4:12 am
by nullplan
~ wrote:I always keep my OS code ready to be assembled to 32 and 64-bit modes (I check it often), even to 8088 and 386 16-bit. Anything that doesn't assemble or throws a warning, is a way to improve my code a big step more, as it lets me see what isn't really well thought in code, and just make it portable (for example use 0xFFFFFFFF instead of -1 as choosing between something like EAX and RAX without being absolutely specific will become nonportable).

Non-portable instructions like PUSHA/POPA can also be resolved through macros across all modes to generate compatible code instead without leaving it abandoned.

So the only thing left is separating the code into the parts that are just not portable across modes but that can be selected for each one; and the code that is so generic that can be ported with automatic macros to 16, 32 or 64-bit modes with absolutely no modifications (most of the code is like that); even to other platforms.

To take assembler portability beyond the PC, I plan to take the CPU instruction syntax and overall machine platform structure of my preferred architecture to any other as the absolute minimum that must always be present to recycle my work infinitely.
Well, OK, so for one thing, you have no way to take advantage of different register files (you do know AMD64 has sixteen GPRs, right? And PowerPC has 32), it also could only possibly come into usefulness for portable code. That is, all the stuff you might reasonably use C for. Assembler is generally used for the unportable stuff, and even there, a lot can be done in C.

So, I guess what I'm asking is: Did you just re-invent a high-level assembler? Because C started with that idea in the late 70ies and look where it is now.

Re: C and the GNU assembler: how to deal with structs?

Posted: Sat Nov 02, 2019 9:30 am
by eekee
nullplan wrote:So, I guess what I'm asking is: Did you just re-invent a high-level assembler? Because C started with that idea in the late 70ies and look where it is now.
Lots of people love to think of C as a high-level assembler, (including myself,) but it started out with modifications of an interpreted language. Around 1969, Ken Thompson took BCPL and adapted it to his minimalist tastes, producing B. Using B, Thompson, Dennis Ritchie, and others found certain tasks would be much more convenient with a type system, and I guess they wanted the performance of a compiled system, so Ritchie produced the first C compiler. I don't think Unix was translated to C for 2 or 3 years. (Somewhere, I have a copy of Ritchie's own writings on the origin of C. I'll share it when I find it.)

I guess the tradition of using C as a high-level assembler took shape in the 80s & 90s with the slow conversion of assembly-language programmers to C. I know many programmers didn't want to convert, thinking all high-level languages hopelessly inefficient for the small computers they worked on. Change happened inexorably, Fortran C and Pascal displaced assembler, and C displaced the other two, perhaps because it's more structured than Fortran and more low-level than Pascal. Fortran's lack of structure made it the bad boy of the bunch, but it was for a time considered the fastest language. Pascal was just too prissy; "Real programmers don't eat quiche." ;) All along, a major driving force was the connection in the minds of many programmers between low-level coding and efficiency, which was a very strong belief whether it was true or not. The belief was no doubt reinforced by the obvious gross inefficiencies of so much 90s software. Here's an interesting article on the inherent inherent inefficiencies of object-oriented languages. In the 90s, ignoring these problems, OO became a sort of God worshipped for the wonderous benefits it would miraculously bestow. In some circles you couldn't speak a bad word about OO! Of course, Real Programmers couldn't stand it, but, distrusting this ridiculous propaganda, they kept to their own doctrine of low-level = good, and made C fit their purposes. They needed a high-level language, even a structured one, because they're writing more complex programs for more complex machines, but hardcore subcultures keep the hardcore spirit. (I'm looking back as someone who was recently a member of such a subculture. ;)) It's funny how the roots of the subculture have been forgotten; they once considered both C and Unix as bloated and slow.

Anyway, I think I've drifted way off topic even though I'm not sure what the topic even is any more! :lol: I do know that some of the points raised on the original topic made me worry, possibly without reason. You just have to know the ABI your compiler conforms to, don't you? Given that, you could easily generate offsets from the C struct declaration. Write a script in Perl or whatever, run it from the makefile... Any thoughts of portability here merely consist of supporting the various different ABIs your compilers may produce, not some mystic version of "code quality".