I've gone back and forth on the ASM issue myself several times over the years.

I've programmed in (and enjoyed) C, C++, Pascal, Prolog, LISP, Visual Basic, Forth, and several ASMs. Many people will say that the sensible thing to do is to stick with C or maybe C++, code mostly in that, and leave ASM for the little speed-ups you need here and there. Yet there's something about ASM that keeps drawing me in!

I remember reading an article back around 1990 about assembly, and it mentioned a DOS program (maybe it was a linker) that was written in 100% assembly. It consistently beat the pants off of all its competitors, not because of any specific tweaks, but because the whole thing was written in ASM. The point the article made (and I've seen it reiterated a few times in other articles) was that using assembly to tweak the 2% of the slowest C code is all fine and well, but the real advantage of ASM programming comes in using it to write the whole thing. Thinking in assembler!

I'm not sure how much that applies today because compilers are truly pretty decent on the whole. Still, it reminds me of owning and riding a motorcycle. It's more dangerous than a car, and it's not as practical as a car... if it's raining, you'll get wet... if it's hot, you'll be hot... if it's cold, you'll be freezing... BUT! -- it's a hundred times more fun!!!!!

As I get older, the things I enjoy doing mean more to me than things I get done. I don't know if that makes much sense, but another way of putting it is: life's a journey, not a destination... enjoy the journey. Program in ASM and be proud! :alright:
Posted on 2003-03-13 17:55:32 by MANT
Alrighty then, time to debunk a few myths:

1. Java is slow.

Once upon a time, that was true. Sun's original Java environment was purely interpreted and had an inefficient garbage collector (memory manager). However, I recently wrote a computational program in both C and Java 1.4. The Java program was only 5% slower, and was much simpler to customize and expand. Current Java implementations are on-demand compiled instead of interpreted (called Just-In-Time compiling usually) and have very efficient memory managers.

When you see a slow Java program, usually what is dragging it down is the graphical user interface (AWT and Swing) which, as even the most fanatical Java zealot will tell you, sux rox. But command-line and server-style (client is elsewhere) Java programs perform very well.

2. Servers are all about performance.

Wrong.

The main two requirements of servers are stability and correctness. I can build a home PC that will knock your socks off, but I would never use that PC in a production environment because it would not be stable enough. For a server, I want error-correcting memory, redundant hard drives, processors that have had all of their "errata" fixed... This extends to software. It is far easier to prove that a program written in a high-level language is correct than it is to prove that the same program written in assembly language is correct. Even if I could take the assembly route for a mission-critical business application, I wouldn't because it would be far too expensive (time-wise) to write it, test it, and maintain it.

3. HLL's are hard.

That would sort of defeat their purpose. Donkey, forget about those wonderful languages you looked at. Try Pascal. It's simple and readable. In fact, it was designed as a way to learn programming languages. Once you wrap your head around Pascal, other languages become a whole lot easier. Plus, most tutorials suck.

4. MS Office XP is such a sluggish bunch of pig programs.

Actually, that's true.

5. I don't like ASM.

Which you might think after I just finished championing high-level languages. Quite the opposite. I truly love assembler. This is as close to the metal as you can get without taking off your pants and sitting on the motherboard. It is a true pleasure to craft a program from scratch, like making a model railroad from individual rails and ties (and itty bitty spikes) rather than from preformed sections of track. And there is nothing so fun as tripling or quadrupling the performance of an algorithm by translating it from a high-level language to optimized, clock-counted, parallelized, lovingly hand-crafted assembler.

-- Craig Putnam
Posted on 2003-03-27 19:48:23 by PopeInnocent

5. I don't like ASM.

Which you might think after I just finished championing high-level languages. Quite the opposite. I truly love assembler. This is as close to the metal as you can get without taking off your pants and sitting on the motherboard. It is a true pleasure to craft a program from scratch, like making a model railroad from individual rails and ties (and itty bitty spikes) rather than from preformed sections of track. And there is nothing so fun as tripling or quadrupling the performance of an algorithm by translating it from a high-level language to optimized, clock-counted, parallelized, lovingly hand-crafted assembler.


2nd me on that!
btw, one just gotta ove the phrase "This is as close to the metal as you can get without taking off your pants and sitting on the motherboard."
Posted on 2003-03-27 23:38:07 by scientica

4. MS Office XP is such a sluggish bunch of pig programs.

Actually, that's true.


The worse one is still Office 2000. ;-)
97 was a nice compromise : ~10 MB for Excel... more than 100 for 2000 and much slower. :(

But I'm going off-topic...
Posted on 2003-03-28 01:04:09 by JCP
I recently wrote a computational program in both C and Java 1.4. The Java program was only 5% slower
Man, there must be something very wrong in your C code or compiler then!
Posted on 2003-03-28 03:16:46 by Maverick

Man, there must be something very wrong in your C code or compiler then!

Nah, somebody just misstake the optimization switch for the extra-over-bloat switch. :) (<-- where did that smiley come from?)
Posted on 2003-03-28 08:15:04 by scientica

Originally posted by PopeInnocent
Alrighty then, time to debunk a few myths:

1. Java is slow.

Once upon a time, that was true


Its still true :grin: You can strap a jet engine to a Volkswagen, but no matter how fast it goes, its still not a sports car...


2. Servers are all about performance.

Wrong.

The main two requirements of servers are stability and correctness.


Yes... this is good...



It is far easier to prove that a program written in a high-level language is correct than it is to prove that the same program written in assembly language is correct.


No... this is bad (have you been reading "Security Focus" :tongue: ???). Lately i've seen even the simplest problems turned into the most convoluted nightmares by these "proveable" HLLS. It's in who wrote the code/who is looking at the code... that is all.

-----
Domain
Posted on 2003-03-28 19:45:48 by Domain
I guess it has some to do with the task at hand but it will also have a lot to do with how familiar you are with the language. If you have some crappy thing to throw together to just get the job done, its hard to justify doing it all the hard way when you can spit it together in an easy HLL in minutes.

Its when you start doing more complex things or time critical things that you start looking hard at how to make it work better and its here where you have the wider range of options in assembler.
I routinely write using a PowerBASIC compiler as I actually enjoy bashing code together fast and tradditional basic has a nice feel about it if you have used it for a long time but when I need to do something that is outside the range of the basic language, it ends up being done in assembler as I think in it reasonably well.

PowerBASIC is a nice toy for this cross language programming but when I need to do stuff that is specific to an assembler, MASM is the right tool as an assembler can routinely do things that are outside the design range of most compilers.

It really has to do with how much code you already have written, if you have been at it for years, you usually have a mountain of code to play with that has been bashed to death many times and is very reliable. In this situation, you can construct a program in far less time than doing it cold turkey without the background to do it in the first palce.

A lot or programming today uses the idea of "engines" to do the grunt work, databases, image work, VB style runtime DLLs etc .... so this area is not very fruitful in terms of coding originality but then, you would not waste you time here as there is nothing to gain.

One of the comments in the thead interests me in that the idea of provable code and reliability in terms of server applications. This is one that does not immediately make sense to me why a HLL should be any better than an assembler if the code is written properly.

I well understand that assembler is usually seen as harder to write for people who don't have a background there but that could be said about normal C as well so I don't get the grasp of that one. The shift here is that compiler design is more reliable than hand written code which I doubt is true.

Certainly compiler code is easier and often faster to write but it does not have the flexibility or maintainance caacity that assembler code has. It is common to find you don't have the right tool to do the job in a HLL where in an assembler, you just write it if you need to, the difference is that you can in assembler where often a compiler gives you a finite capacity and no room to do something different.

Regards,

hutch@movsd.com
Posted on 2003-03-30 07:46:30 by hutch--
Another couple of things strike me as to why I like assembler programming. In many cases, it's cleaner. In C and C++ you can get into a lot of type casting, bending this way and that to make things fit. In assembler the code is often much easier. For instance, a simple example of setting the icon for a window. In C:



mb.lpszIcon = MAKEINTRESOURCE(1007);


In MASM:



mov mb.lpszIcon, 1007


Okay, that was simple. But C/C++ is full of this kind of stuff. Of course, a C/C++ person would say that assembler is full of noise like having to move something to EAX before using it, or using a M2M macro to move memory to memory.

Here's another one. I wanted to set the GWL_USERDATA dword in a window as soon as it's created, which requires trapping the WM_NCCREATE message. Here's the C++ code:



if(message == WM_NCCREATE)
{
wnd = reinterpret_cast<Window *>((LPCREATESTRUCT)lparam)->lpCreateParams;
::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<long>(wnd));
}


And here's the MASM code:



.if msg == WM_NCCREATE
mov eax, lParam
mov eax, (CREATESTRUCT PTR [eax]).lpCreateParams
invoke SetWindowLong, hWnd, GWL_USERDATA, eax
.endif


Maybe it's just me, but I can understand what the MASM code is doing right away. The C++ syntax seems terribly overburdened. I've found that the more I use assembler, the less daunting the Win32 API (or any API for that matter) becomes, because I can reduce the complexities to loading a register, then manipulating that somehow. When you break things down like that (which assembler forces you to do), they can suddenly become crystal clear.

And I agree with Hutch completely about having a library of code already written. It makes writing new programs much easier. I have enough assembly code now, and a good enough core library, that a few weeks ago I was able to whip up a fully-functional dialog-based Windows app in MASM in under an hour. Not just a "hello world", but something that takes four input fields, and then generates an HTML file from it, and calls up the default web browser to view the HTML file. I've done programs like that in the same amount of time in VB and C. Once you get to a certain point in experience in assembler, you can program in it just about as fast as in most HLLs. Plus, IMHO, it's more fun, and you get a deeper understanding of what's going on in general.

On another topic, the issue of provability is a tough one, no matter what the language. I would say though that unless you're using a compiler like Ada, which is certified through a rigorous process, provability is probably easier with assembler, since the hardware instructions are well known and well documented. With a language like C, C++, C#, Pascal, VB, Java, etc., you may have bugs in the compiler/interpreter itself. Plus, we come back to the idea of basic operations in assembler. There are only so many. With a compiler, you can generate all sorts of convoluted expressions, which are often difficult to prove correct. Assembler forces you to break them down into simpler components.

The best way to certify a program module is probably to step through it using a debugger like OllyDbg or SoftICE. Programming in assembler, your code is already very close to what you'll see in the disassembly, and therefore will be (a) easier to understand and step through, (b) easier to fix, and (c) easier to certify, especially since you're more likely to have kept your modules fairly small.
Posted on 2003-03-30 08:59:18 by MANT

Once you get to a certain point in experience in assembler, you can program in it just about as fast as in most HLLs. Plus, IMHO, it's more fun, and you get a deeper understanding of what's going on in general.


I totally agree with that :)
Posted on 2003-03-30 09:17:47 by bazik

Another couple of things strike me as to why I like assembler programming. In many cases, it's cleaner. In C and C++ you can get into a lot of type casting, bending this way and that to make things fit.

True, assembler is simple because its instructions are simple. But I'm sure I can read a binary tree search or quicksort implementation easier in C++ than in asm, especially when the asm is optimized (it should :)).

C++ is strongly typed, which is good IMHO. In asm, if you accidentaly reverse two totally different typed parameters when calling a function you won't notice it until it executes and probably crashes, because all parameters are just dwords. C++ will tell you at compile time.
It's even worse if your program contains such a bug but it doesn't crash, you'll probably have a hard time finding it.


In assembler the code is often much easier. For instance, a simple example of setting the icon for a window. In C:



mb.lpszIcon = MAKEINTRESOURCE(1007);


In MASM:



mov mb.lpszIcon, 1007


That's because the windows API is dirty :). Using a char pointer as an integer *is* dirty. Probably not in the eyes of assembly programmers but an integer and a char* are totally different things. A cleaner method would be providing two members, or an union, and a flag which tells what to use, although that would take more space and code..


Okay, that was simple. But C/C++ is full of this kind of stuff. Of course, a C/C++ person would say that assembler is full of noise like having to move something to EAX before using it, or using a M2M macro to move memory to memory.

Here's another one. I wanted to set the GWL_USERDATA dword in a window as soon as it's created, which requires trapping the WM_NCCREATE message. Here's the C++ code:



if(message == WM_NCCREATE)
{
wnd = reinterpret_cast<Window *>((LPCREATESTRUCT)lparam)->lpCreateParams;
::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<long>(wnd));
}


And here's the MASM code:



.if msg == WM_NCCREATE
mov eax, lParam
mov eax, (CREATESTRUCT PTR [eax]).lpCreateParams
invoke SetWindowLong, hWnd, GWL_USERDATA, eax
.endif


Maybe it's just me, but I can understand what the MASM code is doing right away. The C++ syntax seems terribly overburdened. I've found that the more I use assembler, the less daunting the Win32 API (or any API for that matter) becomes, because I can reduce the complexities to loading a register, then manipulating that somehow. When you break things down like that (which assembler forces you to do), they can suddenly become crystal clear.

C++ needs the types so you'll have to cast it. Again, passing a CREATESTRUCT pointer as a long (LPARAM) is dirty too, but necessary because of the way window procedures work. Don't blame C++ for how the windows API works. If you look at C++ without the windows API, you will nearly never see these reinterpret_casts. As long as everything is typed, code is clean and easy to follow. The windows API often lacks this typing. SetWindowLong for example, you can store anything in it, but you'll have to cast it to longs. That's where things get dirty.

Once you get to a certain point in experience in assembler, you can program in it just about as fast as in most HLLs.

Most API stuff, yes. Complex algorithms and optimized code, no. Especially if you want things to work as fast as possible, you might be optimizing a routine for an hour while the same thing could have been written in a HLL in 10 minutes. It's the price you pay for a fast routine.

Plus, IMHO, it's more fun, and you get a deeper understanding of what's going on in general.

True, its good to have an assembly background even when programming in a HLL.

Thomas
Posted on 2003-03-30 09:28:59 by Thomas

True, assembler is simple because its instructions are simple. But I'm sure I can read a binary tree search or quicksort implementation easier in C++ than in asm, especially when the asm is optimized (it should).

I agree. However I did read somewhere about C code written for optimization being very difficult to read too. As I recall it was something about the Berkeley strings library(?), that that code is brutal because it's optimized. So I guess if you compare non-optimized HLL tree code to non-optimized ASM tree code, I do think the HLL would still be easier to understand, but probably only slightly. I have an expandable array library that I rewrote from C to MASM, and I find the MASM version is just as easy to understand, looking at it several months after writing it.

C++ is strongly typed, which is good IMHO. In asm, if you accidentaly reverse two totally different typed parameters when calling a function you won't notice it until it executes and probably crashes, because all parameters are just dwords. C++ will tell you at compile time.

Those are easy to find and correct.

It's even worse if your program contains such a bug but it doesn't crash, you'll probably have a hard time finding it.

Agreed! It's harder than a crash, but nothing that's ever turned my hair gray! :grin:

Just as likely as swapping parameters is the possibility of sending a parameter that is simply logically wrong, in other words, you misunderstood the meaning of that parameter, or you're sending it in the wrong format -- and that can happen with ANY language. In assembler, however, you get used to dealing with crashes :) and you become much better at finding their sources. If you're making some Win32 API call from VB that crashes your app, and all you know is VB, good luck finding that bug!

Don't blame C++ for how the windows API works. If you look at C++ without the windows API, you will nearly never see these reinterpret_casts.

That may be, but we program in the Win32 API. You're right, in theory, I shouldn't blame C++, but I don't use it in the perfect context where C++ is pristine and beautiful (is it ever? really???). In the Win32 world, things get pretty ugly, and I'm just saying that I prefer ASM for that world.

To each their own though... these are just my personal opinions! :alright:
Posted on 2003-03-30 10:21:17 by MANT
Originally posted by MANT
I agree. However I did read somewhere about C code written for optimization being very difficult to read too. As I recall it was something about the Berkeley strings library(?), that that code is brutal because it's optimized.

Optimized code is always harder to read, but usually you just put them in a library when they're finished and use them without looking at it. If you write dirty code, it looks dirty. However C++ makes it easier to write clean code than asm. Also note that C++ and C use a totally different programming paradigm, many 'C++ programmers' think they are C++ programmers but are actually C coders using a C++ compiler.

So I guess if you compare non-optimized HLL tree code to non-optimized ASM tree code, I do think the HLL would still be easier to understand, but probably only slightly. I have an expandable array library that I rewrote from C to MASM, and I find the MASM version is just as easy to understand, looking at it several months after writing it.

Also for people that have never seen it before? Of course it also depends on your coding style and the quality of your comments, you can make asm easier to understand by formatting your code well (indenting, meaningful labels, good comments).
But in general, I think HLLs are much easier to read. For example, the code I posted in another thread this day, compare:


xor eax, eax
mov ecx, [esp+4]
cmp ecx, 1
je _ret
mov eax, 2
jb _ret
cmp ecx, 16
sbb eax, 0
_ret:
ret

with:


if (val==1)
return 0;
else if(val>1 && val<16)
return 1;
else
return 2;

Which one did you understand faster? I guess the second. This isn't completely fair, since the assembler version doesn't have comments, but the C version hasn't either and is still easy to follow. If you comment it a bit:
    xor     eax, eax

mov ecx, [esp+4]
cmp ecx, 1
je _ret ; ecx==1 -> return 0
mov eax, 2
jb _ret
cmp ecx, 16 ; ecx>1 && ecx<16 -> return 1
sbb eax, 0 ; else return 2
_ret:
ret

Now it's clear what the code does but it takes a lot more characters than in C.

Those are easy to find and correct.

Agreed! It's harder than a crash, but nothing that's ever turned my hair gray! :grin:

Just as likely as swapping parameters is the possibility of sending a parameter that is simply logically wrong, in other words, you misunderstood the meaning of that parameter, or you're sending it in the wrong format -- and that can happen with ANY language. In assembler, however, you get used to dealing with crashes :) and you become much better at finding their sources. If you're making some Win32 API call from VB that crashes your app, and all you know is VB, good luck finding that bug!

True, you'll have to learn by making mistakes :). Still, C++'s strong typing helps you find bugs in an early stage thus saving you the time of debugging.

That may be, but we program in the Win32 API. You're right, in theory, I shouldn't blame C++, but I don't use it in the perfect context where C++ is pristine and beautiful (is it ever? really???). In the Win32 world, things get pretty ugly, and I'm just saying that I prefer ASM for that world.

Lower languages are more flexible and powerful but that does mean you have to know what you're doing. In java, you get a 'nice' exception if you cast an object to a type it doesn't support. In C++, it does cast and likely ends up crashing. In asm, noone cares what you're doing :). This has its advantages and disadvantages. It allows you to optimize code but also to mess things up faster.

To each their own though... these are just my personal opinions! :alright:

Agreed :)
Posted on 2003-03-30 10:56:38 by Thomas
I really don't want to make this a flame session, because I agree with some of your points. However, you're stacking the deck a bit with your ASM vs C code comparison, and that's not entirely fair. When I was talking about how I personally program, I use MASM, and my version of that code would have been:



.if val == 1
return 0
.elseif val > 1 && val < 16
return 1
.else
return 2
.endif


Just as easy to understand and write as the C version. A few more characters, no big deal. I defined a "return" macro a hundred years ago so I could write more readable code.

Even if I didn't use MASM's structured programming goodies, there's no way I would have written the code your way, which, forgive me, seems deliberately hard to read. Here's how I might have written it:



cmp ecx, 1
je R0
jl R2

cmp ecx, 16
jl R1

R2: mov eax, 2
ret

R1: mov eax, 1
ret

R0: xor eax, eax
ret


If you even have a passing knowledge of assembler, I don't see that as being hard to understand at all. (In your C code, it's not clear whether you're dealing with signed or unsigned, so I assumed signed.)

I'm sure we can both find plenty of counterexamples to try and disprove the other's points, but that would really be missing my original point, which was that in dealing with the Win32 API, I find assember code "feels" cleaner to me, and I get a deeper understanding of what's going on.

And again, for me personally it's more fun! ;)
Posted on 2003-03-30 11:25:00 by MANT
MANT: NOFI, but if you write the code I posted like you did, there's no use in doing it in assembly. If you look at the other thread you can see that the C version will generate more efficient code than MASM's IF constructs. Why use assembler then?
This sounds a bit harsh but it's true. However many people have more reasons to program in assembly than just speed. Like you said, it's fun and I agree. I like hacking out a piece of code until it's fast as hell but I don't have the time to do this for complete programs.

The 'problem' with code that isn't speed critical is that it doesn't matter in which language you write it. You won't notice the difference anyway. So it won't matter either whether you use .IF/.ELSEIF or an optimized version like I showed you. You might as well program the thing in C and never notice any difference. But some things I believe are true:

- *well* written asm code is at least as good as what the compiler outputs
- 'normal' asm code (that is, not completely optimized, using IF constructs, WHILE loops, MASM's support for locals & parameters) is worse than the compiler's output
- well written asm takes a lot longer than writing in a HLL
- normal written asm might be coded in the same time as in a HLL (like you said)

For critical code this means: writing in assembly (highly optimizing) is best. compiler's are second best. writing non-optimal code in assembly for speed critical operations is stupid, you'd better use a compiler.

For non-cricitcal code this means: it doesn't matter. You won't notice the difference anyway. When counting every clock cycle, it's probably just like critical code: handwritten is best, then compilers then non-optimized assembly.
But: if it doesn't matter for non-critical code, you must have other reasons for your choice, such as:
- assembly is fun :)
- HLLs are easier and faster to program
- I hate HLLs (bad reason :) but true for some people)
- etc. etc.
You can probably think of a lot more reasons but the bottom line is that it doesn't matter what you code in for non-critical code (well if you end up with javascript you might notice a difference :grin:). I code most non-critical code in C++ because I can code much faster and cleaner in it. If you prefer asm for what reason, that's your choice. My program won't be noticibly faster than yours.

Only for speed critical code it matters, but then, you need to use any trick you've got to optimize the code to the fullest. That means no .IF constructs, your own stackframe, hard to read code etc. etc. Everything that makes it go faster (or smaller).

Thomas
Posted on 2003-03-30 12:09:11 by Thomas
Well, Thomas, I think the bottom line is, program in whatever you want. :tongue:

I have personally found a lot of use coding 100% assembler, and it goes far beyond what we've been talking about. You're right that the if/elseif/else test you illustrated is not critical code, and it doesn't matter whether you use assembler or not. But there are so many things you get out of doing your project in 100% assembler, that I can't even begin to describe how annoying it is to hear someone say "you might as well write that in C or Java". Although it's absolutely true, you end up missing a whole bunch of opportunities for letting assembler change the way you THINK about your coding.

And, upon thinking further about that code example, in C and any language I use, I tend to not use elseif's when there's a return before it. So I would really have written it like this...



if (x == 1)
return 0;
if (x < 1 && x > 16)
return 1;
return 2;


Coding something similar in MASM using .if/.endif would eliminate some of MASM's (and some C compilers') stupidity. If it's critical code, you're probably going to be optimizing it to the point of illegibility anyway, no matter what language you use. And in that case, I would say that if you did the rest of the app in assembler, you'll have an easier time optimizing, because that's what you're already thinking in. For instance, this comes to mind:



mov eax, 1 ; return 1 by default
cmp ecx, 0
cmove eax, value_2 ; 0 --> return 2
cmp ecx, 1
cmove eax, value_0 ; 1 --> return 0
cmp ecx, 16
cmovae eax, value_2 ; 16+ --> return 2
ret


No jumps at all. (I'm not sure it's totally correct, or even faster, but it's just an example.) I doubt a C compiler would do that, and this kind of thing is pretty natural to come up with when you're writing in assembler anyway. Further, the experimentation with different ways of doing it in assembler often gives you insights into changing the nature of the test or the module itself in such a way that you can get 2x or 10x the speed (or cut the size of the code). You would get a similar improvements in a HLL language too, but you only THOUGHT of it in the first place because you were programming in assembler, and dealing with the details.

I don't know if that illustrates my point very well, but it's those kind of "ah-ha!" moments I really value about ASM programming. I get them in HLL's too, but not nearly as often.

Anyway, I know I'm crazy to program in 100% assembler. I can't port my code, and most of the code I write using MASM's HLL constructs are slightly worse than what I'd get with C. But I know that I'm using them in non-critical areas, so it doesn't matter to me. What matters is the state of mind I enter when using assembler. YMMV! :grin:
Posted on 2003-03-30 12:46:08 by MANT
Originally posted by MANT
I have personally found a lot of use coding 100% assembler, and it goes far beyond what we've been talking about. You're right that the if/elseif/else test you illustrated is not critical code, and it doesn't matter whether you use assembler or not. But there are so many things you get out of doing your project in 100% assembler, that I can't even begin to describe how annoying it is to hear someone say "you might as well write that in C or Java". Although it's absolutely true, you end up missing a whole bunch of opportunities for letting assembler change the way you THINK about your coding.

Programming in assembly is a good learning experience, it can improve your optimizing and logic skills and gives you a new view on programming. I have written several programs in 100% assembly too, but after a while I shifted more to the HLL side. I still like to optimize code in assembly and often use it as parts of a program but I don't write big programs in assembly completely anymore.
While all this might be good for you, it isn't for the program itself. As long as you know this, its okay. But some so called assembly programmers think they are great but in reality write code that's worse than the worst compilers (that's not the case with you :)).

And, upon thinking further about that code example, in C and any language I use, I tend to not use elseif's when there's a return before it. So I would really have written it like this...



if (x == 1)
return 0;
if (x < 1 && x > 16)
return 1;
return 2;

It would have produced nearly the same code (just a swap of the conditions).

Coding something similar in MASM using .if/.endif would eliminate some of MASM's (and some C compilers') stupidity.

Well if you would translate it directly in MASM code it would still test x for 1 twice and add useless jumps to the next instruction that will never execute.

If it's critical code, you're probably going to be optimizing it to the point of illegibility anyway, no matter what language you use. And in that case, I would say that if you did the rest of the app in assembler, you'll have an easier time optimizing, because that's what you're already thinking in.

If I have a big program where 2% is speed critical I would write it in C++ and optimize the 2% in assembly rather than writing everything in assembly, taking twice as long and ending up with a program that's harder to read and maintain than the C++ version. But that's my choice..


For instance, this comes to mind:



mov eax, 1 ; return 1 by default
cmp ecx, 0
cmove eax, value_2 ; 0 --> return 2
cmp ecx, 1
cmove eax, value_0 ; 1 --> return 0
cmp ecx, 16
cmovae eax, value_2 ; 16+ --> return 2
ret

No jumps at all. (I'm not sure it's totally correct, or even faster, but it's just an example.) I doubt a C compiler would do that, and this kind of thing is pretty natural to come up with when you're writing in assembler anyway.

That would probably be faster, I assumed the cmov instruction was not allowed (VC6 doesn't use it). Some other compilers may use it (they easily can). But like I said, you can always write better code than a compiler but the question is is it worth it?

Further, the experimentation with different ways of doing it in assembler often gives you insights into changing the nature of the test or the module itself in such a way that you can get 2x or 10x the speed (or cut the size of the code). You would get a similar improvements in a HLL language too, but you only THOUGHT of it in the first place because you were programming in assembler, and dealing with the details.

True, when programming in assembly you're more alert for optimizations.

I don't know if that illustrates my point very well, but it's those kind of "ah-ha!" moments I really value about ASM programming. I get them in HLL's too, but not nearly as often.
Anyway, I know I'm crazy to program in 100% assembler. I can't port my code, and most of the code I write using MASM's HLL constructs are slightly worse than what I'd get with C. But I know that I'm using them in non-critical areas, so it doesn't matter to me. What matters is the state of mind I enter when using assembler. YMMV! :grin:

In any case, you will get great knowledge from programming assembly. I just think that after some years of asm programming you get a bit tired of doing everything in assembly even when you don't optimize it to the fullest while you know a compiler could do better. At a certain point you won't learn much more from the usual program stuff that mostly involves calling API functions. That's when the combination of a compiler for the main work and an assembler for the speed critical work becomes a good alternative. You have the benefit of compiler optimized code while still hand optimizing some routines and learning the neat tricks involved with that. That's my choice, it's a personal thing. Just use what you're confortable with :)
Posted on 2003-03-30 13:22:44 by Thomas
:tongue:
Posted on 2003-03-30 13:43:44 by f0dder
Hey Thomas, never mind all that, just tell me how you get your ASM code to format so beautifully on your web site?!?!? :grin:
Posted on 2003-03-30 13:48:47 by MANT

Hey Thomas, never mind all that, just tell me how you get your ASM code to format so beautifully on your web site?!?!? :grin:

:) I just wrote a simple highlighter for asm/C++ to html and a couple of batch files to generate php includes from the output.

Thomas
Posted on 2003-03-30 13:58:51 by Thomas