Re: HLA and embedded controllers



True, but if you make it onerous, people will stop doing it. Witness
how many C programs don't bother checking for NULL on each return from
malloc.
yes, mainly becayse it's not just checking for NULL. Sometimes it's 0,
sometimes non-0, sometimes 1, sometimes -1, sometimes <0, sometimes
7FFFFFFFh, sometimes call to routine that checks for error.
For me, error catching and passing is same everywhere. You don't need
to know which error are you passing.

Not true, it handles exception it wants to handle, and pass others to
upper level.
Uh, it has to test the return code in order to pass that exception back
on up. Extra code. Extra effort. No such test is necessary with SEH.
You only put the exception handler code where you want to catch the
exception.
again, all extra code is jc per call.
in your design, it's initializing and uninitializing of handler per
procedure. But note that these routines are not portable.
So I have chosen this way...

same way with my design. routines doesn't need to know about error
codes they pass to upper levels. only about those they handle somehow.
But they *do* need to know something. Such as the fact that the code
*does* return an error code. And they have to have the specialized code
to test for that error and clean up after themselves before returning
to their caller. And this has to be done for every call that is made in
the code. None of this is necessary with SEH.
you say your SEH can perform cleanup? close opened files, free
allocated memory? because if no, then this way of usage you are
propagating is pushing people to leaky coding.

again, you had misconception about my library design. EVERY function
return error status in CF,
Not true. Not every function can fail. And if you start setting or
clearing the carry flag on return just to be consistent, you're
bloating up the code and making it more difficult to read and maintain.
Not every function cal fail, but every function returns error status in
CF. And every call needs to be checked. One extra instructions per call
in pure assembly. Few extra lines per procedure in macro-driven
assembly (like yours).


and when CF=1, then EAX=code. all pain is
one "jc .rc" behind every call - really not much. ".rc" is label that
sets CF and returns (with current value of EAX).
The pain is the "behind every call". If you make a lot of library
calls, that can get real painful, real fast. And don't forget that it's
not just a JC instruction.

That JC has to have a target that does something reasonable.
you could read my article i posted there. Something reasonable:
- if there is nothing allocated, it jumps to ".rc" label in epiloque
code, which cleans up stack, restores registers, and returns CF=1.
- if there is something allocated / handle opened, it frees it. How is
this solved in your design, without having to manually test error
status somehow?

Easiest possible with
pure assembly.
Not at all. The easiest possible thing is to allow the user to do
nothing at all. That's the beauty of SEH. They only have to put code in
when they *explicitly* want to handle the exception.
yours "nothing at all" means piece of platform-dependant code per
procedure. Which is NOT a good idea in *pure* assembly that should be
portable.

The other nice thing about SEH is that you only execute the code when
you want to trap an exception. In your case, you've got to execute all
those JC instructions even when an exceptional condition does not
occur, and even when you don't particularly want to handle the
exception at the current level.
well... ~2 extra clocks per call? do you really care about it

There *is* a reason that try..catch..etc. caught on in languages like
C++, replacing the old "errno" test and other abominations in C. It
works a whole lot better and is quite a bit more efficient. Better, it
is less taxing on the programmer to use those facilities.
sure, for C++ it's great thing. Also somewhat stronger than mine. But
C++ is something different than we are discussing here.

For example in FASM you have macro overloading,
which is stronger than MASM's recusive macros.
Unless I don't understand what you mean by macro overloading, I think
you're comparing apples and oranges here.
not at all. if you have macro "abcd" in MASM, and inside it's body you
try
to use "abcd", then same macro is recursively called. in FASM, you
can define "abcd" mutliple times. then if you use, "abcd" in body of
"abcd", previous level of definition is used. When nothing more is
define, "abcd" is left for assembler as instruction/directive.

In FASM way, you can also use recursive macros (redefeine "abcd" in
body before usign it), so it's as strong as MASM, in this area. And you
also can extend definitions.

Also FASM's macro
overloading allows you to overload instructions, impossible in MASM.
Of course, people who overload instructions are just sick :-)
yes i agree. But it also allows you to overload directives. This is one
of biggest problems of MASM. You are given set of directives that work
in particalurat way, and almost cannot change it. And even you can't go
without them.

Nor does it catch any of the other exceptions the OS can raise, e.g.,
division error, file I/O error, illegal instruction, and stuff like
that. You really need to implement the Win32 SEH, or Linux's signals,
to do that.
yes. but when deciding between loosing platform independent routines,
and need for checking this, i've decided that these are NOT so often
cases. btw. i am already planning some kind of static exception handler
unwind data. This is even more advanced than your dynamic-created data.
even MS has already realized that high level procedures always create
same exception frame, and this wastes both time and memory. So these
can be declared static.

I will not implement this since beginning... but it can be added later,
after more important things are there.

This has proven by time as better, often when you don't have something
in MASM, you can't add it.
???
MASM has those string functions I've mentioned and I've been able to
create just about anything I've wanted using MASM macros.
seems you wasn't trying much fancy stuff.
let's say, you want to make "invoke" able to also push 64bit openGL
floats,
in this manner:
invoke GLfunction, [something], double 14.5
how do you do it?

facility missing from MASM (found in NASM and FASM) is the ability to
save a macro context and pop it later on (to share local macro symbols
and stuff like that). By using the string operations, I was able to
synthesize this myself. That's why those string operations are so
important, they let you synthesize stuff like this.
string functions for this? i would need to know your problem more to
understand.
you can make symbol accessible outside macro using equate:
maco a {
local LocSym
LocSym equ LocSym
}
however you are not able to forward-refence such symbol.

in FASM most things are achieved by macro,
And how is that any different from MASM? Of course, MASM has all
those string functions, so the synthesis is probably easier.
string functions are not everything. MASM has builtin procedure style
and builtin procedure calls. When you want to slightly change or add
some behavior, you need to COMPLETELY emulate behavior of procedures
and their calling with macros. Practical example is that 64bit fastcall
standard.

and this allows you to have routines like MASM builtin ones, but also
to have different ones if you need them. If you are not satisfied by
MASMs "invoke"... too bad. If you want to change it's behavior, or
extend it, in FASM, you have free way. FASM way is more flexible.
???
Why can't you do the same thing in MASM if you don't like INVOKE?
because then you must completely emulate entire behavior of INVOKE with
your macro. Just to change or add anything.

4) string comparison (okay, I'm pretty sure FASM already has this)
comparison equal / not-equal supported (in both preprocessing and
assembly time)
comparison greater/smaller only with load/store tricks
This seriously needs to be added.
you are second one to miss it in ~3 years history. But yes, this is a
thing that should be added. problem is HOW to fit such feature into
syntax, so you don't end up using same syntax style for multiple
things. (like MASM with EQU for both symbolic and numeric constants.)

5) index (provide the index of one substring within another)
again just load/store i think
This could actually be synthesized with substr and comparisons. But the
result would be slow and ugly.
you are first to need this i think

A literal constant is something like
12345
"hello world"
3.14159
as opposed to a symbolic constant defined with "=" or an equate.
in FASM "=" always defines numeric constant, and "EQU" always define
symbolic constant. These are checked at completely different levels.
There's more to it, i am not going to explain it now, this post is
already long enough

FASM obviously keeps type information around to differentiate dwords,
words, bytes, and stuff like that. I'd assume that it has something to
differentiate statement labels from the above, too. Making that
information available to a macro would be nice.
It keeps only information needed to properly replace label usage with
number. These are internal thing, for you using label should be same as
typing number.

to introduce some abstractions, like "variables", you have macrosyntax,
i have shown you example.

The assembler obviously *does* know something about the size of
variables, because it reports errors if you try and load a byte object
into a 32-bit register (for example).
yes, as i explained, it's heuristical hint, out-of-design, that makes
it easy to catch common error. for example, NASM has similar design,
but doesn't have this extra. Thus it's even more strict fitting to
design.

It would be nice if the assembler
could make this information available to people writing macros so they
can test their parameters to see if they are correct.
it is already out-of-design enough. To introduce typed variables, you
have macros.

if you want to
create something you would call variable, you can use macros for that.
Or I could use db, dw, or dd?
you can overload data definitions directives "db", "dw", and "dd" with
macro that defines variable, your abstract types:
struc db value {
. db value
.#isMyVar = 1
}
a db 5 ;defines also "a.isMyVar" equal to 1

but using names of data definition directives for variables definition,
makes you unable to just define data, as variable. (it can be
overcomed, but then you have "db" for both simple data definition when
unnamed, and for variable definition when named).

convicing tomasz is FAR from pretty easy, you either need be right by
luck, or be right because you understand FASM design.
Well, I would argue that having the string functions I've mentioned.
on this area, i might agree... these are not doable in some normal way.
i think tomasz should tell his opinion.

How is that? HLA took most of its HLL-like statements from MASM. Lets
see. I added forever..endfor, try..endtry, and maybe one or two other
statements. I did not add a couple of statements that MASM does
support. Semantically, there isn't much difference between the
HLL-like statements the two assemblers support.
i don't know HLA much. but i think you mentioned, you have some strict
typing of variables. when you have pointer variable, do you know what
it points to?

yes, it may help in learning ASM to *start* with using abstarcted HLL
constructs. but to really learn ASM, after they learn enough to go
without these, they must abandon them.
They must certainly get to the point where they know how to write code
without using them, but abandon them?
abandon them for a while, for the sake of learning the other way.
Until you keep using them, you won't learn other style of thinking.

After coder knows both, he is in the right position to decides which
fits him best. ideally, he can use both and choose the better for
specific case. but for this, he must know the assembly way, and to
learn that, he must be forced to code assembly way (to learn it)

otherwise they didn't learn ASM
How do you figure?
If they go back to writing C (or some other HLL) does that mean they
didn't learn ASM?
no, if they can't think their program flow in goto-way, they didn't
learn assembly.

Writing structured code in assembly (even when not writing high-level
assembly) is pretty important if you want to create readable and
maintainable code.
yes, for most people. But it's not good for learning assembly coding

Let me offer you some anecdotal evidence here. I am currently in the
process of rewriting the HLA stdlib source code....
i don't know if you are a good asm coder, haven't seen your codes. due
to your publications, i believe you are. You was able to write code
strucred programming, and goto-driven programming, choosing one that
suits more. And that's why your HLA code was equally efficient. But i
believe you take HLA as learning tool for ASM newcomers. And when you
give them possibility to use something they know, or something they
don't know, which one will they use? And how will they learn goto-flow,
without using it?

Of course. Skim through AoA sometime. You'll discover that this is
exactly how I teach assembly language programming.
i've been browsing it some time ago. Best free book out there on
assembly, sure.

But too much pedagogic for myself - so much theory on the beginning,
that nobody can grasp that. Just learning something, without using it,
is like no learning. So for me, it would be like learning from
reference (which i am forced to, often).

Few years ago, i started writing tutorial exactly the opposite way -
immediately use the thing you learn, and see result. Never got too far,
but i had lot of feedback from happy readers, telling me that this way
it is easier to them to learn.

you can see little older version here: http://decard.net/article.php

And this is something that HLA
tends to prevent it's users from.
How is that? Again, read AoA sometime.
oh, you mean HLA version of AoA. haven't read that. gimme link :]

I believe HLA mistakens people who are willing to go from type 2 to
type 3.
???
Not sure I follow what you're trying to say here.
it gives them possibility not to use goto-way. This in fact in most
cases implies, that they won't use it, IMHO.

FASM *assembler* is symbolic notation of what processor is. processor
knows just instructions and numbers. you have labels to represent
numbers.
Yet, internally, FASM is quite aware of some type information; a direct
contradiction to what you've just said.
again, it's just little out-of-design helper

NASM is the assembler for which this is true. FASM, not so much.
i think this getting out of design was very helpful for handwriting asm
code. but it shouldn't be extended any further, to hurt design more.

FASM *extended syntax* is tool that allows you to built various
abstractions (variables, procedures) atop of this. But it doesn't force
you to use any particular abstraction, and particular implementation of
that abstraction, like high-level assemblers. Thus it is more flexible.
MASM, TASM, and HLA don't force these abstractions on you any more than
FASM does. What makes you think otherwise?
MASM forces you use one specific implementation of HLL directives
(PROC, INVOKE, IF, ...). And it is pain to go to another in MASM

There is one "flaw" to syntax design, which disallows to add inline
macros (macros with EXITM in MASM). Besides, it's best thing out there
i have seen.
So he should create a "funcro" to solve this problem. Different syntax
to overcome the limitations he currently has.
it's more difficult. i can find you some links to discussions, if you
are intersted. btw, i was very actively trying to convice tomasz for
inline macros.

Then again, it's not like you *absolutely* need macro functions.
i was missing them much more than finding substring position at
assembly time.

I would love to see a FASM macro that lets you implement the IF
statement found in MASM, TASM, and HLA. In particular, the processing
of complex boolean expressions involving conjunction and disjunction.
they are in standard FASM distribution, file "include/macro/if.inc".
see: http://board.flatassembler.net/topic.php?t=4608
so Betov was wrong ;)

don't you think such design is better? ;)
I think that FASM needs those string functions I mentioned and the
ability to expose the type information for symbols to macro authors.
:-)
Once I get those facilities, then I'll think about other stuff that I
need.
i was asking about design, not about particular features. yes, FASM
could have those string operations for completness.

PS: wow, this answer took over hour :D

.



Relevant Pages

  • Re: maz v. taz
    ... try to defend your C-Side toy against FASM. ... for dedicated Windows support MASM has many large ... > prefer the lower level approach that assemblers like NASM and FASM ... the very simple reason that its Macros System is not ...
    (alt.lang.asm)
  • Re: Does anyone want to raise a licence issue ?
    ... > try to compete with any of these Assemblers. ... MASM doesn't even try to compete. ... supported longer than RosAsm :-). ... As to the difficulty of using MASM's macros, yes, ...
    (alt.lang.asm)
  • Re: "We Never Use Assembly Language"
    ... that he did not understood what RosAsm Macros ... Once you answered, I provided the MASM ... actual assemblers" as FASM is still about 2.5x faster on the ...
    (alt.lang.asm)
  • Re: HLA is a text converter (text to object code)
    ... See David Salomon's "Assemblers and Loaders" book ... > Since then, we have seen no evolution of Assembly Language, ... > - MASM and TASM Compilers are High Level Assemblers. ... many popular assemblers don't support *macros* today? ...
    (alt.lang.asm)
  • Re: Linker versus assembler
    ... FASM blows away RosAsm in every test I've run. ... MASM (which you also don't ... TASM "aren't actual assemblers" all you want, ...
    (alt.lang.asm)