At 2004-11-23 14:05, Tony Papadimitriou wrote: >----- Original Message ----- >From: "Jaap van Ganswijk" <> >To: <> >Sent: Tuesday, November 23, 2004 10:09 AM >Subject: Re: [m68HC11] RTS problem >> At 2004-11-21 19:09, wrote: >> >I think the rule is: if you push n bytes then call a jsr, the jsr must rts, >> >then the caller must pull n bytes. One must NEVER jump out of a subroutine >> >with items on the stack.... unless you are writing a 'kernel' or 'task >switcher' >> >or 'coroutines' or other comp-sci. The stack must grow and shrink >> >symmetrically >> >> People that don't understand things like these >> shouldn't program in assembler but should program >> in a language like C which will take care of these >> things. > >I'd go further and say people who don't understand such things should not >program at all until they learn some more about how CPUs work. The notion that >programming in a higher-level language is OK without sufficient knowledge of the >underlying CPU is, to me at least, mistaken. Programming, no matter what the >language, is still based on a machine, and a programmer must know how that >machine works. Perhaps for embedded programming, but not in general: Languages like PHP, Javascript and Java are designed to work on all platforms, so it wouldn't make sense to study how the CPU's work that they run on. >> By the way, nobody should have to program in >> assembler anymore (unless for fun or to write >> task switchers etc.) It's a complete waste of >> human energy and especially in the case of the >> 6811 you can't write much more effective code >> than a good compiler can (perhaps you can squeeze >> out 30% better code, but it will be totally >> unreadable) and ROM is cheap by now. > >Although most will probably agree with you I think your opinion is subjective. >I think it's like driving. Some truck drivers, for example, may find it easier >to drive their trucks than their family car because they're on their truck's >wheel most of their lives and have acquired a 'natural' feel for that vehicle. You shouldn't assume that because there are two choices they are equivalent. Programming in a higher level is programming at a higher level of abstraction, which has advantages and disadvantages, but it's not a random choice. Higher level languages allow one to express it's statements more consize, more powerful and more portable, but you have to learn a higher level language before you can use it. This requires at first quite a hefty investment in learning a higher level language (I also postponed learning C several years back in the middle 80's, although I already knew Basic, Algol, Pascal, Cobol etc.). But once you have mastered C (of better) you can program n-times faster (like 4 times faster) and you can handle n-times bigger/complexer projects (like 8 times). And you can port tried and tested code from CPU to CPU. BTW. I'm not talking about small projects of a couple of hundreds of assembler lines. >Similar with assembly language. If you've been programming in assembly a great >deal more than, say, in C, it actually IS easier to program in assembly language >because you think the solution directly in terms of *that* language. It's easier for some hardware-oriented people because they can visualize how the bits go from register to register through the ALU, affecting the flags etc. But once you get used to a higher level of abstraction languages like C are much faster to program in. (BTW. I currently try to do everything in PHP. C is now to me what assembler used to be. People still programming in assembler are now two steps behind... ;-) >On the >other hand, if you've been programming mostly in C (or other higher-level >language), when you get to program in assembly you natually first think in C and >try to mentally translate the code to assembly. And that doesn't work very well >so it gives the (I believe) misleading impression that assembly programming is >harder. I have programmed in all kinds of assemblers as well and of course I did't write it in C first and then hand-compiled it, but it never hurts to use good high-level programming practices even when it costs a couple of more instructions. >> I consider writing in assembler a modern form >> of torture (often self-torture unfortunately ;-). > >I understand you completely. I feel the same about C when it comes to >microcontrollers. That has more to do with the microcontroller and the compilers I guess than with C. (I'll go into that in other reactions on this list). Greetings, Jaap |
RTS problem
Started by ●November 21, 2004
Reply by ●November 25, 20042004-11-25
Reply by ●November 25, 20042004-11-25
At 2004-11-23 16:36, bart homerson wrote: >I would have to agree with you Tony. When I write the few programs that I do write, for a microcontroller, I always write them in assembly. Just as you said, it's just natural. I once took a look at some C-code and I simply could not figure it out! To me, it wasn't intuitive such as Assembly and Visual Basic are; it didn't "Flow". I am attempting to learn Assembly for X86 processors, yes, your PC. I have been told that it is more efficient than using Visual Basic. This should be interesting. Just my thoughts. I can write in x86 assembler and even know a lot of the differences between all of the architectures by heart: 8086, 8088, 80186, 80286, 80386, i486, pentium etc. and wrote in assembler for most of them, but I really can't recomment it unless you have to write drivers that have to be very small (but they don't have to be anymore). C can be compiled quite efficiently to x86 binary code and it runs perhaps at 50% of it's speed. And then there is always the trick of just hand-optimising those few loops that the processor spends the most time in. A rule of thumb says that every program spends 90% of it's time in just 10% of the code, so when you speed that up with the factor two the total code runs about twice as fast. (I have actually used this technique way back, but why bother on CPU's with the current speeds?) Greetings, Jaap |
Reply by ●November 25, 20042004-11-25
At 2004-11-23 20:35, Paul B. Webster wrote: >On Wed, 2004-11-24 at 02:36, bart homerson wrote: >> I would have to agree with you Tony. When I write the few programs that >> I do write, for a microcontroller, I always write them in assembly. > > My sentiments entirely. Why are you indenting your text? >> I am attempting to learn Assembly for X86 processors, yes, your PC. I >> have been told that it is more efficient than using Visual Basic. This >> should be interesting. Just my thoughts. > > Again, you would be in good company FWIW, that of the few people who >*actually* know how PCs work, viz. Steve Gibson. I'm sure that Steve Gibson has studied the architecture of the x86 quite thoroughly but in the field of computer protection he is considered to be a loud fraud by people knowing more about these things than I. > I had to chuckle where a previous critique stated: > >> It's perfectly legal (but usually bad practice) to push something onto >> the stack before doing the JSR, and have the subroutine reference it. > >... as this is of course, *exactly* how C, Pascal and such function. Indeed, whereby Pascal traditionally uses the reverse order of C ;-) >It went on to say: > >> Advanced programmers sometimes -do- intentionally mess up the stack, >> but they will take additional steps to handle the situation. > >... such as, by using such a language. > > However, I wonder whether (many of) those who malign the use of >assembler, understand or recognise the distinction between "raw" and >*macro* assembler, Of course. I wrote my own assembler (the program that translates the assembler source code) and it had very powerful macro abilities, However I have never used them much, because a macro mainly results in a lot of instructions repeated over and over again all over the code. That isn't what I call byte-efficiency. BTW. In an assembler I wrote for the Zilog Super8 processor I also built a lot of pseudo instructions, like 32-bits adds, composed of several 16 and 8 bit adds. That saved a lot of assembler lines and you can't do that very flexible using macro's. >which latter is I hope, our point of reference and >the use of which begins to resemble "C"? I wouldn't go as far that a macro assembler begins to resemble C. Greetings, Jaap |
|
Reply by ●November 25, 20042004-11-25
At 2004-11-23 20:52, Mark Schultz wrote: >--- In , "Tony Papadimitriou" <tonyp@m...> >wrote: >>> I consider writing in assembler a modern form >>> of torture (often self-torture unfortunately ;-). > >> I understand you completely. I feel the same about C when it comes >> to microcontrollers. > >Ahh, the classic "C vs. asm" argument that tends to pop up in groups >like this periodically. > >FWIW, my own personal preference is to do smaller and/or more cost- >critical, resource-constrained applications in assembly language. >Even the best C compiler cannot produce code to match expertly hand- >optimized assembly code. I assumed that ROM space wasn't a problem and usually it isn't. Most 6811's had 4K internal (EP)ROM already 10 years ago, I think, and a good compiler won't produce much more than 30% extra code for the 6811, so where is the gain? >Some C-only proponents often use as an argument that asm is cryptic, No it's too wordy. The language is very hardware idiocyncrasies dependent. >whereas C tends to be more "self documenting". I could not DISAGREE >more. C is more abstract so the programmer can more exactly express what the more abstract meaning of the program is without having to use the assembler instructions that happen to be available. When you know 6811 as you probably do, you will probably easily read a 6811 assembler program by another programmer, but when I would present you with some Super8, Z80, x86, Alpha, R3000 assembler code? Compare: if (x) { ..do this.. } else { ..do that.. } isn't this code very clear? Now in assembler: lda _x tsta jr z,1f ..do this.. jr 2f 1 ..do that.. 2 (I would have properly indented it, but most programmers probably don't do that...) Anyway, which code is the clearest? > The sad tendency of your typical C programmer to write gawd- >awful constructs like this: > >if (ch=getch()=='\n') { > >drives me nuts. It shouldn't drive you nuts. Just learn the associativity rules: '==' is more associative than '=' so I immediatily see that your code can be rewritten as: if (ch=(getch()=='\n')) { Which is probably not what you intended to write because you are assigning a boolean value to a variable called 'ch'. You probably intended to write: if ((ch=getch())=='\n') { Which makes perfect sense since your read a character into the variable ch and check if it's a newline character. >And this is just a simple example (intended to be >comprehensible while still making my point) of much more complex >assignments-within-expressions-within-evaluations that I see all too >often in "professionally developed" C source. It saves repeating terms from expressions. You could have written the previous expression as: ch=getch(); if (ch=='\n') { But I prefer the concisely written version, because it only once has the term 'ch' in it. >When I write programs in C, I try to avoid complex expressions, or at >least break them up into multiple lines, assembly-language-style. You suffer from what also happens a lot with artists who produce kitsch: They partly adopt a new technology but can't sever the links with past technologies and therefore combine them. The first cast-iron bridges in England were build like they were build from wood. It's a phenomenon often seen when new technology arises: Managers who needed a company WWW site often thought it needed to look like an old medium like a TV-program or a brochure. The true acceptance of new technology goes very slowly and may take a generation change (sorry guys...) >Ok, I'm ranting here, so let me get to my point: I am of the opinion >that the language is not as important as is the style in which one >writes code in any language. Yes, but you can't use bracketing, indentation, local variables, dynamical expressions etc. in assembler. >A properly commented, intelligently >structured C program can be a joy to behold - just as a properly >aligned, well structured assembly program with good label/variable >names can be. Organization, clarity, and consistency in style are >the keys to readability in ANY language. Yes, but you still shouldn't compare programming in a low level language with that in a higher level language. It just isn't the same. And it isn't just a choice. It's like saying that the Quakers (?) in Pennsylvania Dutch Country are also developing technology but in another direction. >One last comment on C in embedded/microcontroller systems - one of >the things I dislike most about your typical C compiler is the >complex (and usually poorly documented) procedure one has to figure >out to get the various memory regions and areas, or even individual >variables, mapped to where you want them to go. Yes, I fully agree with you on this and that is also why I wrote my own assemblers and linker. >The C language >standard does not do a good job of allowing one to attach attributes >to variables indicating where in memory they should go. This task >usually falls to the linker, and of course there is no standard for >linker control 'languages' which means that it differs for every >compiler. Indeed. And it's doubtful if it should be done within the C code itself because it might kill the portability of the code. In C there might be hints (just as with the register 'class') like: Put this in EEPROM, this in battery RAM, this in memory that is still available when the program starts again, this on disk, this in literal space, this ... etc. in the end I identified about 16 different spaces. A next obstacle is BTW. the communication between the downloader and the project to download it to. >This issue has been the single greatest obstacle that I've >encountered in my attempts to utilize the GNU HC11/12 toolset for my >own projects based on these parts. I can imagine that very well... BTW. Anyone want to help make my 6811 compiler, assembler, linker and downloader public (under GPL)? The assembler is actually a family of assemblers and I also have a similar family of disassemblers. BTW. In PHP the problem with assignments within expressions is more or less solved by adding 'and' and 'or' as having the same function as '&&' and '||' but with a lower priority as '=', so you can write: if (ch=getch() and ch=='\n') { In a lot of the code that I write, it's a big improvement. BTW. For a sample of code that I write in PHP: http://www.chipdir.nl/amazon/ (But it's a bit over-commented, because the code is explicitly meant to be used by others.) Greetings, Jaap |
|
Reply by ●November 25, 20042004-11-25
At 2004-11-23 21:54, Donald E Haselwood wrote: >> FWIW, my own personal preference is to do smaller and/or more cost- >> critical, resource-constrained applications in assembly language. >> Even the best C compiler cannot produce code to match expertly hand- >> optimized assembly code. > >Quite true. Over the years the technique I've found most useful is to keep >asm routines small and C-callable (and before C, FORTRAN callable). By >making them C-callable, 1) I can use a quick 'n dirty C mainline to test >them, 2) it forces a uniform organization for passing arguments, stack >useage, and saving registers (which saves >frustration/self-cursing/sanity/...). > >Also, whenever I start to write an asm routine I find there is a temptation to >keeping add more to the routine, which can lead to a monstrosity that is >difficult to debug/test, and has limited reusability. But why still write big subroutines in assembler? With the 6811 the code size of compiled code doesn't have to be much bigger than 30% more so it will also not take 30% more cycles. You shouldn't choose a certain processor when it's speed margin is within the 50% range. Always choose a processor that is at least twice or four times as fast as you think you need. You never know what will turn out to be too slow and you never know what extra functions management and users may want added later. The 30% extra that the compiler add's is much less than what you need to add as a safety margin for the uncertainty. BTW. I have programmed very large projects on microcontrollers like the 6811 and as long as you understand timing issues that extra 30% is never an issue. Greetings, Jaap |
Reply by ●November 25, 20042004-11-25
On Thu, 2004-11-25 at 15:40, Jaap van Ganswijk wrote: > Why are you indenting your text? Because it looks and reads better that way. As someone who has gone on to state that you "can't indent assembler", which is in itself, certainly news to me, I can only assume that you agree that indenting makes computer code more readable, and so it is for English prose. > I'm sure that Steve Gibson has studied the architecture > of the x86 quite thoroughly but in the field of > computer protection he is considered to be a loud > fraud by people knowing more about these things than I. But the question remains, do those critics *actually* know more about these things than Steve Gibson, or are they in turn, merely a further group of equally loud frauds? Wannabees and Know-it-alls are never in short supply, wherever they occur in the food chain. > Of course. I wrote my own assembler (the program that translates > the assembler source code) and it had very powerful macro abilities, > However I have never used them much, because a macro mainly results > in a lot of instructions repeated over and over again all over the > code. That isn't what I call byte-efficiency. Where the alternative is subroutines, extra stack operations and consumption of stack space, it may *well* be byte-efficiency. The first use of macros is to concisely represent code which is *going to be* used again and again. If it was not *necessary* to repeat the code pattern, then you wouldn't *need* the macro. The code comes first, the macro embodies the code. > BTW. In an assembler I wrote for the Zilog Super8 processor I also > built a lot of pseudo instructions, like 32-bits adds, composed > of several 16 and 8 bit adds. That saved a lot of assembler lines > and you can't do that very flexible using macro's. I begin to wonder what you think macros are? What you describe is *exactly* what macros do - the second use of macros is to generate parametric code (often using macros within macros), that is code using similar patterns of instructions which differ by parameter - the actual values or addresses which they contain. Also, using conditional directives, a given macro expansion can contain (entirely) different instructions on different invocations. > I wouldn't go as far that a macro assembler begins to resemble C. Well, macros can build hierarchical structures, which seems to have a lot to do with what C is about. A macro assembler can most certainly build a higher level language, and can like C, be used to generate CPU-independent code. In fact, a properly-constructed macro assembler *is* CPU-independent because at the lowest level it contains only definitions of all the instructions - as macros! One simple little "gadget" that I build some time back - when I *was* actually building things(!) - was a State Machine - a clock, an octal D-latch, and an EPROM. Now the "program" was written in AS09 (MAS09? The host machine - 6809 Exorciser variant - has subsequently died) which was rather funny, as it had *no* microprocessor! Of course, now I would use a 16F84 or an AT90S1200 (because they are still a lot cheaper than an HC05K2). -- Cheers, Paul B. |
Reply by ●November 25, 20042004-11-25
----- Original Message ----- From: "Jaap van Ganswijk" <> To: <> > Perhaps for embedded programming, but not in general: Languages > like PHP, Javascript and Java are designed to work on all platforms, > so it wouldn't make sense to study how the CPU's work that they > run on. You missed my point. Yes, high-level languages have the benefit of being less platform dependent. But, in most systems, e.g., PCs, mainframes, etc. there is a hefty Operating System in the background doing all the dirty work for you. That's what gives you the freedom to use the language without having to know much about the CPU architecture. (Although you still should know, for example, what size integers the host machine has or else porting may be puzzlingly unsuccessful.) With most microcontroller projects, this isn't the case. It's just you (with your C compiler friend at best) and the machine. Not the same scenario. Also, I never claimed higher-level languages should be abolished, on the contrary, I'm a firm believer in their use being increased as nobody seems to use them anymore. But, I'm referring to truly high-level languages. And C isn't it. It wasn't designed to be. My 'complaint' is C, to many, is meant to be the cure to all diseases. As you probably know, C started out as (and still really is) a 'medium-level' language to address a specific problem, in short, to give as much as possible the capabilities of an assembler (which has no restrictions found in nearly all high-level languages) yet have the look-and-feel of a high-level language (e.g., with loop contructs, structured IF-THEN-ELSEs, etc.). That was, so people could write middle-ware like Operating Systems or Compilers (which often need to get down close to the hardware) in that language. Initially, it was never meant to be for writing end-user applications. Each language has its place. With C, somewhere it took the wrong path. From a computer science standpoint, C is actually a bad language for writing high-level applications. Pascal, Modula, and others are far better choices. Unfortunately though, early (mostly) student programmers' show-off attitutes made them use C from their early university years to prove to fellow students that they can do it, i.e., program in a language, which at that time, was considered harder (correctly so) than BASIC or COBOL or FORTRAN or Pascal or Lisp or whatever else was available, just like assembly is still today considered 'harder' than C. (And I'm talking before the time C became a requirement in most CS curricula.) Then inevitably, what most learn in school, they try to stick with for the rest of their lives, so we got a whole generation of C coders many of whom didn't even realize there were other tools for the jobs they were asked to do. And that 'foolishness' spread. The more the people that use a language, the greater the numbers of projects written in it, the greater the demand for new people to learn it to support older projects, and so on. So, today, it's gotten to the point that if you don't know C you're hardly considered a programmer! Amazing! (And in case you wonder, I do know C, I just don't like it for the reasons I mention here, and I avoid it whenever it's in my hand to do so, unless of course there truly is a reason to use it, e.g. modify a Linux kernel or something of that nature!) > >Although most will probably agree with you I think your opinion is subjective. > >I think it's like driving. Some truck drivers, for example, may find it easier > >to drive their trucks than their family car because they're on their truck's > >wheel most of their lives and have acquired a 'natural' feel for that vehicle. > > You shouldn't assume that because there are two choices > they are equivalent. Programming in a higher level is > programming at a higher level of abstraction, which Sorry, abstraction is NOT related to language (although it is more easily implemented with certain high-level languages designed specifically for this purpose). Even if it were, it certainly wouldn't be close to the middle-level C language. Abstraction is conceptual and, as such, it is related to programming methodologies, not language. You can be very abstract in assembly language just as you can be very nonsensical (is that a real word?) or 'spaghetti-like' in C (or BASIC or Pascal or whatever) which are supposed to protect you from programming 'atrocities'. > has advantages and disadvantages, but it's not a random > choice. Higher level languages allow one to express it's > statements more consize, more powerful and more portable, > but you have to learn a higher level language before you > can use it. This requires at first quite a hefty > investment in learning a higher level language (I > also postponed learning C several years back in the > middle 80's, although I already knew Basic, Algol, > Pascal, Cobol etc.). Almost 25 years, three University degrees strictly in Computer Science, and a large assortment of projects in more computer languages than most people would be able to enumerate in a pop-quiz, is more than enough investment to know a little what I'm talking about, even if I can't get others to always agree. We're all entitled to our opinions. > But once you have mastered C (of better) you can program > n-times faster (like 4 times faster) and you can handle > n-times bigger/complexer projects (like 8 times). Again, you fail to understand that what you claim is subjective. It's because YOU can program faster or more easily in C, you think this is a universal rule. Not so. (Example: Can you or I speak Chinese? No! But 5-year Chinese can! Does that make the Chinese language easy or hard?) It doesn't automatically mean your knowledge of C is greater than someone else's who also happens to know assembly language equally well, and *still* find it easier (and possibly faster) to program in assembly, even though s/he know enough C to not 'have to' (according to you it's a self-torture) write in assembly language. > And you can port tried and tested code from CPU to CPU. True to the extent I mentioned earlier, i.e., code depends on an underlying OS or something equivalent, not stand-alone. Raw hardware and just your code will never port as easily as recompiling for the new target processor, except for trivial applications. > BTW. I'm not talking about small projects of a couple > of hundreds of assembler lines. Me neither, I'm talking about complex well-structured thousands-of-lines-of-code programs. > >Similar with assembly language. If you've been programming in assembly a great > >deal more than, say, in C, it actually IS easier to program in assembly language > >because you think the solution directly in terms of *that* language. > > It's easier for some hardware-oriented people because Again, having a heavy Computer Science background, I'm not hardware-oriented in the sense most EE people on this list are (I can't hardly design even the simplest circuits). Of course, I do know all I need to know about CPU internals to the extent that I can design my own CPU from scratch (but then I *must* take it to an EE professional to maybe optimize it and turn it into an actual circuit that works). > they can visualize how the bits go from register to > register through the ALU, affecting the flags etc. > > But once you get used to a higher level of abstraction > languages like C are much faster to program in. > (BTW. I currently try to do everything in PHP. C is now > to me what assembler used to be. People still programming > in assembler are now two steps behind... ;-) To me, C is actually a *very rich* macro-assembler! So, our views our coming closer here, from different ends, but closer none-the-less. > I have programmed in all kinds of assemblers as well and of > course I did't write it in C first and then hand-compiled it, > but it never hurts to use good high-level programming practices > even when it costs a couple of more instructions. I didn't say that you must actually write in another language (I said 'mentally translate'). To give an example, I say that just like when your native tongue is English you think in English no matter how well you have been trained in another foreign language. You still think in your mother language. And it is possible for someone who lives abroad for a long-long time to master another language better than his own, but then this new language becomes your main language, so all your thinking is in that language, and your original language still needs a little work when you try to speak it. (This is actually based on personal experience.) So, it takes extra 'thinking' to speak anything other than your 'currently' native language, it doesn't come out as effortlessly. Similar with programming languages. You tend to think a solution in terms of your favorite or better mastered language, and then mentally 'translate' to the language you must actually use for the project at hand. And this doesn't yield the best results. So, you end up blaming the language instead of the author. > >> I consider writing in assembler a modern form > >> of torture (often self-torture unfortunately ;-). > > > >I understand you completely. I feel the same about C when it comes to > >microcontrollers. > > That has more to do with the microcontroller and the > compilers I guess than with C. (I'll go into that in > other reactions on this list). It is precisely with microcontrollers that this holds, so we agree on that. Like I said earlier, PCs have a rich OS so in a sense your code is really not much more than a series of calls to that OS (I exaggerate a little but I'm trying to get my point across about not being the same scenario with PCs and microcontrollers). Not much 'original' work in PCs in the sense you find in microcontroller projects! With PCs, if the OS can't support it, or else, let you bypass it to do it yourself, you're pretty much stuck! See what I mean? Hope so. To conclude: I'm not bashing C unconditionally, I just think it's the wrong language for certain jobs, one of them being microcontroller code writing (*especially* when we're talking about 8-bit controllers which are small enough to be completely manageable fully in assembly language even by non-expert assembly coders). I wouldn't write a multi-tier airline reservation database application with assembly language (or even C). But I also wouldn't write a 68HC08QT4 application with C, either. Each language has its place. The reason for programmers turning to C originally was to gain the added power high-level languages didn't provide when dealing with hardware or lower level software functions. This is the same reason that drives many of us assembly language proponents to assembly language FOR MICROCONTROLLER JOBS, not everything. We need the extra power that C can't offer to a microcontroller project. > Greetings, > Jaap |
Reply by ●November 25, 20042004-11-25
--- In , Jaap van Ganswijk <ganswijk@x> wrote: >> At 2004-11-23 20:52, Mark Schultz wrote: >> FWIW, my own personal preference is to do smaller and/or more >> cost-critical, resource-constrained applications in assembly >> language. Even the best C compiler cannot produce code to match >> expertly hand-optimized assembly code. > > I assumed that ROM space wasn't a problem and usually it isn't. That's a very poor assumption to make. There are still a lot of *current* microcontrollers on the market that are very code- or RAM-size constrained. This is particularily true for 8-bit families such as the lower-end PIC and AVR devices, as well as half a dozen other MCU families I could cite if asked. There are parts in the aforementioned families that I've encountered that have less than 1K of ROM space, and only 32 bytes of RAM/register space! For such devices, C is not really an option - the overhead imposed by the C runtime (crt0) alone would consume half your program storage! For such ultra low-end devices, assembly language is still the best choice, IMO. I also believe that Jaap mentioned in one of his responses that one should select a device that is at least 2x as "powerful" (~= RAM/ROM space, CPU speed, etc.) as the anticipated need. As an engineer, I would be inclined to agree with that statement, but if I put on my 'managers' hat and look at the project from a marketability and cost-control standpoint, I'd be inclined to argue that assertion. I have been compelled to do firmware design for projects where decisions such as which microcontroller to utilize or how the external support hardware is designed have been made with little or no input from myself. When faced with a situation where the hardware design is just barely sufficient to get the job done, I'll go for the design option that lets me get the most from the hardware - and that almost always means "write it in assembly language". Either that, or throw up my hands, say "it can't be done", and resign. >> Some C-only proponents often use as an argument that asm is >> cryptic... > No it's too wordy. The language is very hardware idiocyncrasies > dependent. >> ...whereas C tends to be more "self documenting". I could not >> DISAGREE more. > C is more abstract so the programmer can more exactly express > what the more abstract meaning of the program is without having > to use the assembler instructions that happen to be available. > When you know 6811 as you probably do, you will probably easily > read a 6811 assembler program by another programmer, but when I > would present you with some Super8, Z80, x86, Alpha, R3000 > assembler code? > > Compare: > > if (x) { > ..do this.. > } > else { > ..do that.. > } > > isn't this code very clear? > > Now in assembler: > > lda _x > tsta > jr z,1f > ..do this.. > jr 2f > 1 > ..do that.. > 2 > > (I would have properly indented it, but most programmers probably > don't do that...) > > Anyway, which code is the clearest? While your point has some validity, your example/contrast is not very fair. I *NEVER* write assembly code in the style you demonstrated. For one thing, any asm program I write almost always has a comment-per-line. I could attempt to illustrate my style here, but the Yahoo message formatter will mess it up, so I have to resort to a textual description. My asm programs always use labels of medium length (typically 10 char max), and jump-points within a given subroutine are always sequentially (or occasionally, alpha) numbered. Almost every statement has a end-of-line comment. I use indentation in the comment field and liberal use of vertical whitespace to illustrate blocking. Every subroutine I write has a standard comment header that describes input and output parameters, variables referenced, estimated stack usage, registers affected, etc. Major sub-sections of code within a routine have one or more lines of block comments that describe overall function. A typical source file generated by myself will consist of more comments (measured in terms of space consumed by the source file) than code. Some of the code that I have recently uploaded to the files section of this group illustrates my asm style; I invite you and others to review it and reach your own conclusions. I should point out that I follow many of the commenting/style rules (with appropriate modifications due to the different environment) in my C (or other HLL) programs. My point in mentioning all of this is that asm source CAN be made to be quite readable - and conversely, C source can be made to be totally unintelligible, a point that I will address in a moment... >> The sad tendency of your typical C programmer to write gawd- >> awful constructs like this: >> >> if (ch=getch()=='\n') { >> >> drives me nuts. > It shouldn't drive you nuts. Just learn the associativity > rules: '==' is more associative than '=' so I immediatily > see that your code can be rewritten as: > > if (ch=(getch()=='\n')) { > > Which is probably not what you intended to write because > you are assigning a boolean value to a variable called 'ch'. You make my point for me. Writing constructs like the one above is a common (and difficult to locate!) source of bugs in a typical C program. And, while I do not disagree with your point that a good programmer should familiarize themselves with the rules of assocativity and precedence in the language they are utilizing, parsing expressions like the one above (for a human) is a lot more difficult than parsing the equivalent: ch = getch(); if (ch == '\n') { The difference in readability is not as easy to see in this trivial example, but it is much more pronounced in more complex expressions. >> When I write programs in C, I try to avoid complex expressions, >> or at least break them up into multiple lines, assembly- >> language-style. > > You suffer from what also happens a lot with artists who produce > kitsch: They partly adopt a new technology but can't sever the > links with past technologies and therefore combine them. Perhaps I should have omitted (or replaced) the phrase "assembly- language style" with something like "...to make the code easier to read". While I can, given time, deduce the operation of a long, complex expression, the time this takes as compared to the lesser time and effort required to figure out the operation of a complex operation broken down into smaller, more discrete steps is considerable. This has less to do with "assembly style" vs "HLL style" and much more to do with "readability". Note that I'm not advocating a reducto ad absurdum approach to this; I have no problems with an expression such as: Scaled = (Sample1 + Sample2) * Slope + Offset; Although I might use a few more ()'s even if they are redundant: Scaled = ((Sample1 + Sample2) * Slope) + Offset; The ()'s make the precedence of operations explicit TO THE READER; they are redundant as far as the compiler is concerned. Mind you, I *would* have a problem with this: Scaled = ((RawValue = (Sample1 + Sample2)) * Slope) + Offset; Assignments don't belong in expressions. Period. Of course, any one of the above (even the one with the stupid assignment-within-expression) is quite readable because I used meaningful variable names; it is fairly obvious what I'm trying to do (scale raw measurements into [presumably] standard units using the classic linear equation y = mx + b). I mention this to make another point about what distinguishes good from bad code - selection of variable names. Also note that I do not 'crowd' the operators right up against the variable names; judicious use of whitespace goes a long way towards enhancing readability. >> Ok, I'm ranting here, so let me get to my point: I am of the >> opinion that the language is not as important as is the style in >> which one writes code in any language. > > Yes, but you can't use bracketing, indentation, local variables, > dynamical expressions etc. in assembler. True, but I can use whitespace, end-of-line comments (which can be indented), and stack-allocated local variables (if the CPU offers direct access to the stack pointer, which the HC11 does but the HC05 and PIC do not) to achieve similar results. Obviously, a HLL will offer better tools for block-structuring than assembly will - that's one of the aspects that makes a HLL a HLL after all. I'm simply trying to reiterate my point that good style - in any language - is the single most important factor in readability. >> One last comment on C in embedded/microcontroller systems - one >> of the things I dislike most about your typical C compiler is the >> complex (and usually poorly documented) procedure one has to >> figure out to get the various memory regions and areas, or even >> individual variables, mapped to where you want them to go. > > Yes, I fully agree with you on this and that is also why I > wrote my own assemblers and linker. > >> The C language standard does not do a good job of allowing one to >> attach attributes to variables (or subroutines - Ed.) indicating >> where in memory they should go. This task usually falls to the >> linker, and of course there is no standard for linker >> control 'languages' which means that it differs for every >> compiler. > > Indeed. And it's doubtful if it should be done within the C code > itself because it might kill the portability of the code. In C > there might be hints (just as with the register 'class') like: > Put this in EEPROM, this in battery RAM, this in memory that > is still available when the program starts again, this on disk, > this in literal space, this ... Many 'better' relocating assemblers support a "section" directive (or equivalent) that allows the programmer to specify, in a fairly portable and abstract way, what region a given block of code should be mapped to. The physical address of each section is still (usually) specified at link-time, but one can create sections with names such as "Page0RAM", "ExternalRAM", "EEPROM", "PrimaryFlash", "BackupFlash", etc. that make it clear where things go. Some C compilers I have encountered provide non-standard #pragma's or even linguistic extensions that allow this sort of control at the source- code (rather than linker) level. I would personally like to see extensions of this nature added to the C standard, or perhaps as an "addendum" to the standard that would be optional and probably only implemented by developers of cross-target compilers. > BTW. Anyone want to help make my 6811 compiler, assembler, linker > and downloader public (under GPL)? Wish I could help, but I got out of the 'application' side of things around the time that Windows became popular. I have made some progress in learning the *nix/posix API's, but I've got a while to go before I could call myself 'proficient'. I suspect that attempting to comprehend Microsoft's (Windows) API's would lead to a nervous breakdown. > BTW. In PHP the problem with assignments within expressions is > more or less solved by adding 'and' and 'or' as having the same > function as '&&' and '||' but with a lower priority as '=', > so you can write: > > if (ch=getch() and ch=='\n') { > > In a lot of the code that I write, it's a big improvement. Yes, I agree. The first HLL I learned (after BASIC) was (Borland's implementation of) Pascal. I only wish that Pascal, or a language similar in structure to it, had become the de-facto HLL standard. Borland's implementation of Pascal offered ways to do almost all of the 'low level' stuff that C is capable of, but with a much less ambiguous syntax. To this day, I still have trouble remembering which of C's operators are bit-wise and which ones are logical (e.g. & vs. &&, | vs. ||, etc.). Borland did away with the 'logical' operators entirely, and opted to make AND, OR, XOR bit-wise, while specifying the value of "TRUE" for relational operators to be -1 (all bits set). This choice eliminated the need for ambiguous bit- wise vs. logical operators. Couple that in with Pascal's usage of English words (AND, OR, XOR) instead of symbols (&, |, ^) for the operators themselves, the end result was a lot more readable. From what little I've seen of PHP, it would seem as if what the designers have done is take C and move it a bit in the Pascal-ish direction. That's a Good Thing in my book. Unfortunately, I've not seen very many PHP compilers made available for microcontroller targets :(. Also, isn't it true (I honestly do not know) that PHP is tokenized/interpreted rather than compiled? If so, this is a Bad Thing, at least as it applies for it's use in embedded systems. Despite all the industry talk about use of Java in embedded systems, it's use is pretty much constrained to high-end systems running almost desktop-PC-capable microprocessors due to the twin overhead- bloaters: object-oriented data dynamisim (-> large RAM requirements) and it's interpreted nature (-> high CPU load). -- Mark |
|
Reply by ●November 25, 20042004-11-25
On Nov 25, 2004, at 12:37 PM, Mark Schultz wrote: > There are still a lot of *current* microcontrollers on the market > that are very code- or RAM-size constrained. This is particularily > true for 8-bit families such as the lower-end PIC and AVR devices, > as well as half a dozen other MCU families I could cite if asked. > There are parts in the aforementioned families that I've encountered > that have less than 1K of ROM space, and only 32 bytes of > RAM/register space! For such devices, C is not really an option - > the overhead imposed by the C runtime (crt0) alone would consume > half your program storage! For such ultra low-end devices, assembly > language is still the best choice, IMO. I don't know what C compiler your statements are based upon but only poor implementations have a "runtime (crt0)" such as you describe. This relates right back to my earlier statement that if one sees stdio.h that one can expect to find the code written by the clueless. My use of embedded C has mostly been with the Introl C-11 compiler. Other than rare situations where it re-reloads a register with the same value it loaded a moment earlier there is not much it does which I would do differently by hand in assembly. In other words I don't usually bother to pass arguments on the stack in assembly. Introl C-11 puts all it can in registers then stacks the rest. Introl's startup code is quite reasonable. Any HC11 has a few housekeeping chores which must be done early such as position the I/O registers and set the stack pointer. If one preloads variables with data then these must be copied from ROM to RAM. Introl goes a bit farther and by default routes IRQ vectors thru a RAM vector table and provides a wrapper so that nonspecial subroutines may be called. A provided library function inserts your subroutine into the vector table and wraps it. If one reads the source code and understands it then there is no problem replacing the actual ROM vector table with addresses of one's actual routines. And no problem defining them with a special function type so that they behave during IRQ and properly RTI. Have recently been looking at avr-gcc in quite some detail. One fairly simple example found in the avr-libc documentation had very little code out of RESET before main() was called. One could do lots of real work in 1k of ROM with avr-gcc. But one probably couldn't get printf() to fit if one insists on writing C the Microsoft Way. I agree with all the bad things Mark says about C if one limits the discussion to C compilers I have seen for the 8051, PIC 16, and 68HC05 products. The Metrowerks HC908 C compiler appears to be acceptable. But recently made the selection of Atmel AVR and avr-gcc for future products. Only time will tell. -- David Kelly N4HHE, ======================================================================== Whom computers would destroy, they must first drive mad. |