Re: HLA and embedded controllers
- From: "randyhyde@xxxxxxxxxxxxx" <randyhyde@xxxxxxxxxxxxx>
- Date: 31 Oct 2006 21:50:12 -0800
vid512@xxxxxxxxx wrote:
in my library i always tell user to always place "jc error" behind
call.
for lazy users, you can also extremely easily implement "try-catch"
macros, in this style:
try
libcall stream.read.dec2ud
libcall stream.read.blank
libcall stream.read.string
...
catch ERR_END_OF_FILE
user HAS to have some error catching, otherwise he will never write
secure and bugfree code, regardless of design
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.
2) The try..endtry/raise approach lets you easily pass exceptions up aNot true, it handles exception it wants to handle, and pass others to
call tree. With the CF/EAX (or other return value) approach, every
library routine that calls another library routine has to meticulously
test for all possible exceptions that could be generated and carefully
pass them back up to their callers.
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.
Not only is there opportunity for error here, but it's a lot of extra code to write, test,all extra code is one "jc .rc" behind every call. it's VERY little
debug, and execute that wouldn't be otherwise needed.
extra code for 100% error catching. top level needs some "jc error" and
"error: <print error message>". This quarantees same you do, with least
overhead possible, neatly usable from lowlevel.
You're trying to convince me of something I abandoned about a decade
ago because people were failing to do all the tests. It's not like
CF/EAX is a new idea. I gave up on it because of the problems
associated with it.
3) The try..endtry/raise approach is a bit more generic. Though yousame way with my design. routines doesn't need to know about error
wouldn't want to use exception handling as a general-purpose control
structure, it's really nice for bailing out of some low-level code and
immediately popping up to a higher level in the call tree under
exceptional conditions. For example, in HLA v2.0 I use the exception
handling mechanism to catch syntax errors at low-levels in the call
tree and then an appropriate try..endtry sequence handles that syntax
error much higher up in the call tree. This works out great when
routines that wind up getting called in the middle of the call sequence
don't have a clue about the possibility of that error and might be used
for code for which that error couldn't occur. As a result, the code is
much cleaner.
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.
4) Using try..endtry/raise is *much* easier on the end programmer. Theagain, you had misconception about my library design. EVERY function
whole point of a standard library is to make life easier on the
programmer. If they've got to go to the effort of testing every little
function call's error return status, that's painful. Again, in the
default case, they don't have to do the test -- the default exception
handler can take over.
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.
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. For example, when passing control to the caller,
it has to clean up the stack, reset the environment, etc. And that's
not always just the case of jumping to the end of the function (indeed,
I suspect that's not even the most common case for sophisticated
library routines).
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.
For those who like macros, they are as easy to use as
yours (i believe), with less overhead. and you also understand how they
work.
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.
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.
no, i mean you need .NET just to *run* new versions of MASM, not toMost people who actually write assembly code using MASM aren't writinghttp://webster.cs.ucr.edu/AsmTools/MASM/index.htmlyou are forgetting ambigous syntax, and that new MASM requires .NET
framework (~20MB) to run,
.NET code. At least, not yet. So I'm not particularly worried about it.
Of course, someday soon we'll be hearing from Rene about the ".NET
pioneers" who demonstrate how to write .NET applications using assembly
language, etc., etc.
write .NET in asm. altough it's pretty possible and documented, .NET
"assembly" language is called MSIL, google it.
But few people do that. So what's the big deal?
Again, MASM v6 will continue to get used and pushed for writingthat's sick... just because they are used to it.
assembly apps (COFF/OMF). I've seen attempts at using COFF->ELF
converters to use MASM to write Linux apps, but I have no idea how
successful those attempts have been.
It really doesn't matter what you think or what I think about it.
That's the way it is. And MASM really *is* a decent assembler. Far more
powerful than most others. More powerful than FASM, for example, in
many respects.
I haven't looked at FASM's macro facilities in about a year, sonow FASM is lacking just inline macros - and that's a big lacking.
maybe things *have* changed, but back thing MASM's macro facilities
were still more capable than FASM's.
but besides, FASM is stronger. 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.
Also FASM's macro
overloading allows you to overload instructions, impossible in MASM.
Of course, people who overload instructions are just sick :-)
MASM provides the macro facilities. I use them. What's so "unnatural"you are redefining language. you can aswell redefine FASM to accept
about that?
simple NASM-style macros. and then use NASM style macros. FASM provides
facilities for this. Is it natural?
Sure, why not?
The whole point of a macro system is to create user-extensible
statements in the assembly language. The fact that someone else creates
their own extensions that you don't agree with doesn't make it
"unnatural" in the least.
I believe my exception system is almost as powerfull (doesn't catch
GPFs... yet), with little less overhead and easier to use in pure
assembly
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.
Last time I checked, MASM allowed macro functions, a host of stringmacro functions = inline macros, yes
operations, type/constant operations, and other useful stuff like that,
which FASM does not. Now some of this may have been added to FASM since
string functions - FASM has only concatenation and symbol->string, yes.
Others can be achieved using slow dirty way, with "load" and "store".
Not best, but this keeps syntax little cleaner.
Not if you use those functions frequently :-)
For string operations, you really do need length, instr, concat,
substr, and comparisons. With those primitives, you can easily
synthesize most other interesting string functions. Tomasz should
consider those, at the minimum.
FASM is designed to combine small pack of powerful features to
accomplish task. Not to implement every single feature in compiler.
OTOH, it should implement a minimalist set that lets you do anything
you want. For example, FASM probably doesn't need all the string
handling functions found in the HLA compile-time language (probably
over 100 of them, counting the pattern matching routines), but it
really should have the five function sets I've mentioned above.
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. Indeed, one
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.
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.
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?
String manipulation operations (on text EQU values):virtual at 0
1) string length
db string, 0
length = $
end virtual
Okay.
2) string concatenation"#" operator
Okay.
3) substringugly, compile-time-slow load/store
Ouch.
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.
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.
1) Determine if a macro parameter (or text equate) is a literalpossible with combinations of simpler features. Altough i don't
constant or a memory address.
understand what you mean by "literal"
A literal constant is something like
12345
"hello world"
3.14159
as opposed to a symbolic constant defined with "=" or an equate.
2) Determine if a literal constant is numeric or text or stringif arg eqtype ""
(surrounded by quotes).
1) Determine if a symbol is a variable, procedure, equate, or otherthere is nothing like "procedure" to processor, thus not to assembler.
class
Forgive me. Statement label.
compile-time variable is placeholder for value, thus it is treated like
any number. by run-time variable, you mean label, eg. placeholder for
memory address holding variable, eg. number again.
In FASM, procedures are just things (optionally) built by macros. this
way is more flexible, and allows you to build in such way, that you can
see if some label is name of procedure. (label = placeholder for
address of start of procedure) i
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.
2) If the object is a memory operand, return the size of that operandyes, first one i agree. it's is kinda hard to find size associated to
(e.g., dword).
label. but size associated to label is not critical part of assembler
syntax, it's just helper to catch probable error. kind of heuristical
thing, which predicts that "mov eax, [variable]" with variable defined
as "variable db something" is error
And it would be nice to ask how "variable" was declared. That's
basically what I'm asking for. Something that will tell me "dd", "dw",
"db", "statement label", whatever.
Of course not. The real fun part happens when you try to implementquoted string constant is easy to detect. assembler itself doesn't know
HLA's stdout.put macro (note: no "s", as in "puts" here):
stdout.put( "Uns32var: ", uns32Var, " charVar:", chVar, " stringVar: ",
stringVar, nl );
anything about size of variable. simply because there are no variables.
there just labels, which are placeholder for numbers.
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). 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.
if you want to
create something you would call variable, you can use macros for that.
Or I could use db, dw, or dd?
and if you define variables (not just labels) with these macros, it's
pretty easy to find the type
Sure. That's my plan.
And as I've said, it's been pretty easy to convince Tomasz of things I've needed inconvicing tomasz is FAR from pretty easy, you either need be right by
the past, so it shouldn't be too hard this time around, either.
luck, or be right because you understand FASM design.
Well, I would argue that having the string functions I've mentioned,
plus the ability to expose internal symbol table information such as
size information, is something the assembler should do. It's not that
hard to add (the information is there, just need to make it available
somehow). And the end result is that people can write *much* more
powerful macros. Without facilities such as these, it's pretty
difficult to claim that FASM's macro facilities are comparable to
MASM's.
Like MASM and TASM, it is a high-level assembler. Hence its name.from my point of view, HLA is higher level than MASM and TASM which are
Actually, the term "High-level assembler" has been around since the
late 1960s. And it fits quite well into that category. See David
Solomon's book on assemblers for details.
"high level assemblers"
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.
So do many other assembly programmers. I used to be that way, too. Iyes, it may help in learning ASM to *start* with using abstarcted HLL
hated the high-level facilities in MASM when they were introduced in
the early 1990s. But regardless of what I thought at the time (and what
you think today), most programmers getting into assembly prefer them.
And it is certainly the case that students making the transition from
HLL to assembly find it easier and faster to make that transition if
they get to leverage some of their HLL knowledge when learning
assembly.
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? That's really their choice, not
your's or mine. They can't claim that they're writing traditional
assembly language if they use those statements in their assembly
programs (though they can claim they're writing "high-level assembly
language"), but just because you don't like those statements doesn't
mean they should abandon them. There are good reasons (readability and
maintainability) for using such statements in an assembly language
program. That's why, for example, most Win32/MASM32 programs use those
statements. I'd hardly claim that people who are writing the MASM32
programs I've seen couldn't be called "assembly language programmers"
because they've refused to abandon those statements.
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?
coding. thinking the program flow using structured programming
(abstraction/subset of gotos) is different than thinking program flow
in ASM (or any goto-language).
Sure, but *really good* assembly programmers can look at a high-level
assembly language statement and *know* the code it generates. They can
still think in low-level terms, but write in high-level code so that
other people can more easily read and modify their code.
Most people fail to realize this, they
never learn thinking the flow the goto-way, and they end up
hand-compiling structured-programming abstractions to ASM.
For many reasons other than ignorance, as you suggest here.
Writing structured code in assembly (even when not writing high-level
assembly) is pretty important if you want to create readable and
maintainable code.
For these,
using HLL macros is really best, but then they are NOT assembly coders.
They are high-level assembly coders. What's the big deal? Are you sure
your code is so much better than that?
Let me offer you some anecdotal evidence here. I am currently in the
process of rewriting the HLA stdlib source code. One of the big changes
I'm making is eliminating most of the high-level statements found in
the source code. This is being done *exactly* to satisfy complaints
from people such as yourself who wouldn't consider using the library if
it contained high-level assembly statements. When going through the
code, about the *only* major difference I'm finding between the
original high-level assembly code and the new pure assembly code that
would make a difference at the object code level is that I've
substituted statements like
if( esi = 0 ) then
raise (ex.AttemptToRefNULL );
endif;
with
test( esi, esi );
jz labelAtEndOfFunction;
.
.
.
labelAtEndOfFunction:
raise( ex.AttemptToRefNULL );
These types of changes are the *only* ones that are producing
significantly better code (no need to jump over the raise in the common
case). Note, btw, that HLA *does* generate the test instruction,
that's not what's being improved here, it's the flow that is being
improved.
In almost every other case, the "hand compilation" of the high-level
statements produces the exact code I would have written as an assembly
programmer. This is not because the HLA code generation was amazingly
good, but because I wrote that high-level code *knowing* exactly what
machine instructions it would generate and I picked the high-level code
according. It would be pretty hard for you to convince me that I don't
know assembly language and I'm not writing in the "assembly way" when I
do this.
generally i agree. type 3 coders can do without any slowdowns. But toThat abstraction is only speed/sizeI see three generic levels of programmers here.
disadvantage C has over ASM.
1. , 2., 3.
become type 3, you HAVE to write lowlevel way, COMPLETELY without any
HLL structures, at least for some time.
Of course. Skim through AoA sometime. You'll discover that this is
exactly how I teach assembly language programming.
And this is something that HLA
tends to prevent it's users from.
How is that? Again, read AoA sometime.
Even though not designed to. if
someone wants to learn asm, and thus become type 3, he has to go
without HLL structuring.
Which you most certainly can do in HLA. What's your point?
You make the mistake of assuming everyone who uses HLA is in the firstI believe HLA mistakens people who are willing to go from type 2 to
category I've listed above. There are certainly some people who never
grow beyond that point, but the bottom line is that there are lots of
HLA programmers who've grown into the second and third categories, as
well.
type 3.
???
Not sure I follow what you're trying to say here.
lot about FASM was herehope i already explained FASM design to you. to be sure, once more:
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.
NASM is the assembler for which this is true. FASM, not so much.
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?
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.
Then again, it's not like you *absolutely* need macro functions. They
are nice and convenient, but there is little you can do with them that
cannot be done with standard macros. You'll notice I didn't add funcros
to my list of necessary things. It is a nice addition that assemblers
like TASM and MASM have (HLA's macros also fall into this category, but
HLA's macro expansion is completely different from all these other
assemblers, so there really isn't a need to differentiate "statement"
macros and funcros). But it's not necessary to achieve what I want to
achieve with FASM.
All what you mentioned is abstraction over processor working,
completely possible to be added with macros.
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.
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.
Cheers,
Randy Hyde
.
- Follow-Ups:
- Re: HLA and embedded controllers
- From: Betov
- Re: HLA and embedded controllers
- References:
- Re: HLA and embedded controllers
- From: randyhyde@xxxxxxxxxxxxx
- Re: HLA and embedded controllers
- From: vid512@xxxxxxxxx
- Re: HLA and embedded controllers
- Prev by Date: Re: Couple basic questions
- Next by Date: Re: HLA and embedded controllers
- Previous by thread: Re: HLA and embedded controllers
- Next by thread: Re: HLA and embedded controllers
- Index(es):
Relevant Pages
|