It seems to be a mainstream opinion that assembly programming takes longer and is more difficult to program in than a higher level language such as C. Therefore it seems to be recommend or assumed that it is better to write in a higher level language for these reasons and for the reason of better portability.

Recently I've been writing in x86 assembly and it has dawned on me that perhaps these reasons are not really true, except perhaps portability. Perhaps it is more of a matter of familiarity and knowing how to write assembly well. I also noticed that programming in assembly is quite different than programming in an HLL. Perhaps a good and experienced assembly programmer could write programs just as easily and as quickly as an experienced C programmer writing in C.

Perhaps it is because assembly programming is quite different than HLLs, and so requires different thinking, methods and ways, which makes it seem very awkward to program in for the unfamiliar, and so gives it its bad name for writing programs in.

If portability isn't an issue, then really, what would C have over a good assembler such as NASM?

Edit: Just to point out. When you are writing in assembly, you don't have to write just in instruction codes. You can use macros and procedures and your own conventions to make various abstractions to make programs more modular, more maintainable and easier to read. This is where being familiar with how to write good assembly comes in.

+73  A: 

ASM has poor legibility and isn't really maintainable compared to higher-level languages.

Also, there are many fewer ASM developers than for other more popular languages, such as C.

Furthermore, if you use a higher-level language and new ASM instructions become available (SSE for example), you just need to update your compiler and your old code can easily make use of the new instructions.

What if the next CPU has twice as many registers?

The converse of this question would be: What functionality do compilers provide?

I doubt you can/want to/should optimize your ASM better than gcc -O3 can.

Ben S
+1: "I doubt you can/want to/should optimize your ASM better than gcc -O3 can."
Bruno Reis
gcc is not that great at optimization, far better than the average human, but there are many places where the optimizers fail to do a good job. Agree with you though otherwise.
+1 for the second reason
George Edison
@dwelch It is in very rare instances that gcc (or many other compilers) fail to properly optimize compiled C. In those instances, however, you can always write a limited number of procedures in ASM and link just those methods in during build.
@Ben S: I initially edited in "many" rather than "much" because "much" is used for singular objects only. Since the object of "much" is plural (developers), "many" is the correct option. But I won't edit your answer again if "much" is what you want.
Billy ONeal
It is not rare I see it every program compiled. that doesnt mean it should be fixed in every program. I agree you need a really good reason and if so then call a tuned routine. If you dont live in an corner case world like the one I work in I would say you should probably never touch or tune the compilers output other than using compiler switches. There are far better compilers than gcc where I would lean even more to agreeing with you completely.
There are many cases where a compiler cannot optimize well, but quite often a developer that is aware of limitations of the optimizer can optimize his C code without resorting to assembly.
FWIW in my day job I compile our product with gcc -g -O0, because being able to attach gdb to it on a live system and not go mad due to variables optimized out of existence, is worth a hell of a lot more to the company than it would be to leave another 4 billion CPU cycles idle every day (out of a total of 3 trillion). Crunching integers just isn't the bottleneck very often.
Bernd Jendrissek
+23  A: 

I love programming in assembly language, but it takes more code to do the same thing as in a high-level languge, and there is a direct correlation between lines of code and bugs. (This was explained decades ago in The Mythical Man-Month.)

It's possible to think of C as 'high level assembly', but get a few steps above that and you're in a different world. In C# you don't think twice about writing this:

foreach (string s in listOfStrings) { /* do stuff */ }

This would be dozens, maybe hundreds of lines of code in assembly, each programmer implementing it would take a different approach, and the next person coming along would have to figure it out. So if you believe (as many do) that programs are written primarily for other people to read, assembly is less readable than the typical HLL.

Edit: I accumulated a personal library of code used for common tasks, and macros for implementing C-like control structures. But I hit the wall in the 90s, when GUIs became the norm. Too much time was being spent on things that were routine.

The last task I had where ASM was essential was a few years ago, writing code to combat malware. No user interface, so it was all the fun parts without the bloat.

Are you sure about that? I seem recall reading in Code Complete that this was not the case...
I'm sure there's a point where the 'fewer lines' advantage is beaten by the 'premature optimization' disadvantage. But I haven't looked at Code Complete in ages...
A bit ironic to use "premature optimization" as an argument *for* assembly... (I probably misinterpret you though. I still think it's funny.)
Bernd Jendrissek
+6  A: 

Well I have been writing a lot of assembly "in the old days", and I can assure you that I am much more productive when I write programs in a high level language.

Maurice Perry
"Assembly is Latin".
Adriano Varoli Piazza
@Adriano: except there are many, many different dialects and no two of them look alike.
Joachim Sauer
Sure, but I meant that learning to program in any of them gives you an insight on the architecture of a machine that helps you at higher levels. Unless you deal with paged memory, in that case you end up scarred. Like reading Carmen 16 from Catullus.
Adriano Varoli Piazza
@Adriano "Assembly is Latin", No asm is caveman grunts. One grunt for rock 2grunts for deer, 3grunts for fire - good for simple stuff but hard to run an empire on.
Martin Beckett
@Martin: Have you ever tried to do complex arithmetics with Roman numerals?
Adriano Varoli Piazza
+2  A: 

I'm sure there are many reasons, but two quick reasons I can think of are

  1. Assembly code is definitely harder to read (I'm positive its more time-consuming to write as well)
  2. When you have a huge team of developers working on a product, it is helpful to have your code divided into logical blocks and protected by interfaces.
Note that you can separate assembly into logical blocks, too.
Paul Williams
+4  A: 

Assembly is not portable between different microprocessors.

That's not exactly true with modern processors and assembler programs, you can target different processors just as you can in C. Sure you won't be able to use the full set of instructions in this case, but then neither do you if you write it in C. Portability isn't the primary concern.
Maybe you mean *architecture*.
Ben S
@Blindy - You can target different processors within the x86 family but there is definitely no commonality in assembly instructions between an x86 variant and an ARM processor or a Z80 or an 8051.
True, but then you can't program a z80 in c either. I think we're all talking about normal x86/x64 processors here.
@Ben S - Thank you for your suggestion. Perhaps architecture would have been a better choice of words.
@Blindy: I did have a C compiler once for a CP/M computer with a Z80. This was pre-standard, and I don't remember what would have had to be changed to conform to C90, and I don't know how difficult that would have been.
David Thornley
@Blindy, see sdcc the open source "Small Devices C Compiler" which does target the Zilog Z80 and other small micros.
All the world is not an x86. Nothing about "different microprocessors" suggests that they all execute the same instruction set.
Bernd Jendrissek
+36  A: 

I've written shedloads of assembler for the 6502, Z80, 6809 and 8086 chips. I stopped doing so as soon as C compilers became available for the platforms I was addressing, and immediately became at least 10x more productive. Most good programmers use the tools they use for rational reasons.

+6  A: 

If an average production program has say 100k lines of code, and each line is about 8-12 assembler instructions, that would be 1 million of assembler instructions.

Even if you could write all this by hand at a decent speed (remember, its 8 times more code that you have to write), what happens if you want to change some of the functionality? Understanding something you wrote a few weeks ago out of those 1 million instructions is a nightmare! There's no modules, no classes, no object-oriented design, no frameworks, no nothing. And the amount of similar looking code you have to write for even the simplest things is daunting at best.

Besides, you can't optimize your code nearly as well as a high level language. Where C for example performs an insane number of optimizations because you describe your intent, not only your code, in assembler you only write code, the assembler can't really perform any note-worthy optimizations on your code. What you write is what you get, and trust me, you can't reliably optimize 1 million instructions that you patch and patch as you write it.

+5  A: 

The same reason we don't go to the bathroom outside anymore, or why we don't speak Latin or Aramaic.

Technology comes along and makes things easier and more accessible.

EDIT - to cease offending people, I've removed certain words.

Jack Marchetti
You are still offending Luddites with the word `Technology`

Is this a serious question ...?


Q. Why don't airlines use biplanes as passenger aircraft more often?

Q. Why are antiseptics used instead of voodoo or magic?

Q. Why don't more people use mainframes as desktop pcs?

Is this a serious answer ...?
Michael Myers
Yes. It is a serious question.
It is a serious question.
+4  A: 

A reasonable level of assembler competence is a useful skill, especially if you work at any sort of system level or embedded programming, not so much because you have to write that much assembler, but because sometimes it's important to understand what the box is really doing. If you don't have a low-level understanding of assembler concepts and issues, this can be very difficult.

However, as for actually writing much code in assembler, there are several reasons it's not much done.

  • There's simply no (almost) need. Except for something like the very early system initialization and perhaps a few assembler fragments hidden in C functions or macros, all very low-level code that might once have been written in assembler can be written in C or C++ with no difficulty.

  • Code in higher-level languages (even C and C++) condenses functionality into far fewer lines, and there is considerable research showing that the number of bugs correlates with the number of lines of source code. Ie, the same problem, solved in assembler and C, will have more bugs in assembler simply because its longer. The same argument motivates the move to higher level languages such as Perl, Python, etc.

  • Writing in assembler, you have to deal with every single aspect of the problem, from detailed memory layout, instruction selection, algorithm choices, stack management, etc. Higher level languages take all this away from you, which is why are so much denser in terms of LOC.

Essentially, all of the above are related to the level of abstraction available to you in assembler versus C or some other language. Assembler forces you to make all of your own abstractions, and to maintain them through your own self-discipline, where any mid-level language like C, and especially higher level languages, provide you with abstractions out of the box, as well as the ability to create new ones relatively easily.

Dale Hagglund
+7  A: 

In addition to other people's answers of readability, maintainability, shorter code and therefore fewer bugs, and being much easier, I'll add an additional reason:

program speed.

Yes, in assembly you can hand tune your code to make use of every last cycle and make it as fast as is physically possible. However who has the time? If you write a not-completely-stupid C program, the compiler will do a really good job of optimizing for you. Probably making at least 95% of the optimizations you'd do by hand, without you having to worry about keeping track of any of it. There's definitely a 90/10 kind of rule here, where that last 5% of optimizations will end up taking up 95% of your time. So why bother?

Brian Postow
+1. Writing assembler code and writing *fast* assembler code are two different things. If you use a good compiler, you get the fast assembler code for free.
you get fast assembler code for free only if you know how to use the compiler, most do not use optimization, most people compile with debug options and as a result end up with poorly done slow assembler.yes over 99% of the time you shouldnt touch it, just touch the compilers knobs and not tweak the output directly.
if you care about the optimizations, then you should be doing that from the compiler... IF you don't care about optimizations, but you're still using assembly, then you're just being silly.
Brian Postow
@dwelch: I guess there might be some script-kiddies who don't bother to find out how they're tools are used. But I doubt people like them would ever be able to write fast assembler code.
+2  A: 

One of the early discoveries (you'll find it in Brooks' Mythical Man-Month, which is from experience in the 1960s) was that people were more or less as productive in one language as another, in debugged lines of code per day. This obviously isn't universally true, and can breaks when pushed too far, but it was generally true of the high-level languages of Brooks' time.

Therefore, the fastest way to get productivity would be to use languages where one individual line of code did more, and indeed this works, at least for languages of complexity like FORTRAN and COBOL, or to give a more modern example C.

David Thornley

Because it's always that way: time pass and good things pass away too :(

But when you write asm code it's totally different feeling than when you code high-level langs, though you know it's much less productive. It's like you're a painter: you are free to draw anything you like the way you like with absolutely no restrictions(well, only by CPU features)... That is why I love it. It's a pity this language goes away. But while somebody still remembers it and codes it, it will never die!

True. On the other hand, there is the humiliation you experience when the cashier and the supermarket refuses to cash your check, disdainfully saying, "Oh, you program in a LOW-LEVEL language."
+2  A: 

Portability is always an issue -- if not now, at least eventually. The programming industry spends billions every year to port old software which, at the time it was written, had "obviously" no portability issue whatsoever.

Thomas Pornin
"It won't have to port to another architecture" sounds a whole lot to my ears like "It won't need more than two digits for the year."
David Thornley
Or we can't use C# because Windows might not be around next year?
Martin Beckett
E.g. Apple's MacIntosh computers which have been based upon Motorola MC68000 series processors, PowerPC (IBM et all), and now Intel's x86 (IA-32(e)) processors. So yeah, portability is an issue for any system used long enough, and any programmer who hasn't been bitten by their code lasting longer than expected isn't experienced yet.
@Martin: Twenty years from now, there will be a lot of C# programs people want to run, and so there will be a way to compile and run C# programs. There's nothing inherently fixed about C#, although in twenty years I'd be surprised if it was still as popular as it is now. However, in twenty years our CPUs will be significantly different. An assembler program written in 1990 may well run nowadays, but it sure won't be optimal, and will run slower than compiled C.
David Thornley
That's what I meant - I have a lot more porting issues because a high-level framework changed from 6months ago than I do because the instructions in an x86 changed - especially since hand coded asm tends to stick to the simplest methods.
Martin Beckett
Even if M$ disappears, C# is mostly an open standard is it not, or am I thinking of something else?


A company hires a developer to help turn code into $$$. The faster that useful code can be produced, the faster the company can turn that code into $$$.

Higher level languages are generally better at churning out larger volumes of useful code. This is not to say that assembly does not have its place, for there are times and places where nothing else will do.

+1  A: 

I'm learning assembly in comp org right now, and while it is interesting, it is also very inefficient to write in. You have to keep alot more details in your head to get things working, and its also slower to write the same things. For example, a simple 6 line for loop in C++ can equal 18 lines or more of assembly.

Personally, its alot of fun learning how things work down at the hardware level, and it gives me greater appreciation for how computing works.

+3  A: 

When you are writing in assembly, you don't have to write just in instruction codes. You can use macros and procedures and your own conventions to make various abstractions to make programs more modular, more maintainable and easier to read.

So what you're basically saying is, that with skilled use of a sophisticated assembler, you can make your ASM code closer and closer to C (or anyway another low-ish-level language of your own invention), until eventually you are just as productive as a C programmer.

Does that answer your question? ;-)

I don't say this idly: I have programmed using exactly such an assembler and system. Even better, the assembler could target a virtual processor, and a separate translator compiled the output of the assembler for a target platform. Much as happens with LLVM's IF, but in its early forms pre-dating it by about 10 years. So there was portability, plus the ability to write routines for a specific target asssembler where required for efficiency.

Writing using that assembler was about as productive as C, and with by comparison with GCC-3 (which was around by the time I was involved) the assembler/translator produced code that was roughly as fast and usually smaller. Size was really important, and the company had few programmers and was willing to teach new hires a new language before they could do anything useful. And we had the back-up that people who didn't know the assembler (e.g. customers) could write C and compile it for the same virtual processor, using the same calling convention and so on, so that it interfaced neatly. So it felt like a marginal win.

That was with multiple man-years of work in the bag developing the assembler technology, libraries, and so on. Admittedly much of which went into making it portable, if it had only ever been targeting one architecture then the all-singing all-dancing assembler would have been much easier.

In summary: you may not like C, but it doesn't mean that the effort of using C is greater than the effort of coming up with something better.

Steve Jessop

There was a vicious cycle as assembly became less commonplace: as higher level languages matured, assembly language instruction sets were built less for programmer convenience and more for the convenience of compilers.

So now, realistically, it may be very hard to make the right decisions on, say, which registers you should use or which instructions are slightly more efficient. Compilers can use heuristics to figure out which tradeoffs are likely to have the best payoff. We can probably think through smaller problems and find local optimizations that might beat our now pretty sophisticated compilers, but odds are that in the average case, a good compiler will do a better job on the first try than a good programmer probably will. Eventually, like John Henry, we might beat the machine, but we might seriously burn ourselves out getting there.

Our problems are also now quite different. In 1986 I was trying to figure out how to get a little more speed out of small programs that involved putting a few hundred pixels on the screen; I wanted the animation to be less jerky. A fair case for assembly language. Now I'm trying to figure out how to represent abstractions around contract language and servicer policy for mortgages, and I'd rather read something that looks close to the language that the business folks speak. Unlike LISP macros, Assembly macros don't enforce much in the way of rules, so even though you might be able to get something reasonably close to a DSL in a good assembler, it'll be prone to all sorts of quirks that won't cause me problems if I wrote the same code in Ruby, Boo, Lisp, C# or even F#.

If your problems are easy to express in efficient assembly language, though, more power to you.

+1  A: 

What C has over a good macro assembler is the language C. Type checking. Loop constructs. Automatic stack management. (Nearly) automatic variable management. Dynamic memory techniques in assembler are a massive pain in the butt. Doing a linked list properly is just down right scary compared to C or better yet list foo.insert(). And debugging - well, there's no contest on what is easier to debug. HLLs win hands down there.

I've coded nearly half my career in assembler which makes it very easy for me to think in assmebler. it helps me to see what the C compiler is doing which again helps me write code that the C compiler can efficiently handle. A well thought out routine written in C can be written to output exactly what you want in assembler with a little work - and it's portable! I've already had to rewrite a few older asm routines back to C for cross platform reasons and it's no fun.

No, I'll stick with C and deal with the occasional slight slowdown in performance against the productivity time I gain with HLL.

Michael Dorgan
+1  A: 

Ditto most of what others have said.

In the good old days before C was invented, when the only high level languages were things like COBOL and FORTRAN, there were lots of things that just weren't possible to do without resorting to assembler. It was the only way to get the full breadth of flexibility, to be able to access all the devices, etc. But then C was invented, and almost anything that was possible in assembly was possible in C. I have written very little assembly since then.

That said, I think it is a very useful exercise for new programmers to learn to write in assembler. Not because they would actually use it much, but because then you understand what is really happening inside the computer. I've seen lots of programming errors and inefficient code from programmers who clearly have no idea what's really happening with the bits and bytes and registers.

Yes, spot on. Fortran Disk and Tape I/O on IBM mainframes years ago was next to useless, so we wrote our own I/O routines in 370/Assembler and called them from the Fortan IV code.And writing assembly code made me really understand the underlying architecture. I haven't written any assembly code now for quite a few years and all the younger people I work with have never written any - but I wish they would, it is so educational.
Simon Knights
+1  A: 

I can only answer why I personally don't write programs in assembly more often, and the main reason is that it's more tedious to do. Also, I think that it is easier to get things subtly wrong without noticing immediately. E.g., you might change the way you use a register in one routine but forget to change this in one place. It'll assemble fine and you may not notice until much later.

That said, I do think there are still valid uses for assembly. For instance, I have a number of pretty optimised assembly routines for processing large amounts of data, using SIMD and following the paranoid "every bit is sacred"[quote V.Stob] approach. (But note that naive assembly implementations are often a lot worse than what a compiler would generate for you.)

+136  A: 

Hello I am a compiler.

I just scanned thousands lines of code while you were reading this sentence. I browsed through millions of possibilities of optimizing single line of yours using hundreds of different optimization techniques based on vast number of academical research that you would spend years getting at. I won't feel any embarassment not even a slight ick when I convert a three lines of loop code to a thousands of instructions just to make it faster. I have no shame to go great lengths of optimization, do the dirtiest tricks. And if you don't want me to, maybe for a day or two, I'll behave and do it the way you like. I can transform the methods I'm using whenever you want, without even changing any single line of your code. I can even show you how your code would look in assembly, on different processor architectures and different operating systems and in different assembly conventions if you'd like. Yes all in seconds. Because, you know, I can; and you know, you can't.

P.S. Oh by the way you weren't using half of the code you wrote, I made you a favor and threw them away.

If I could upvote you more then once, I would. This was way too funny.
Thanks klez, I enjoyed writing it too :)
Al brought to you By.... Droid. ;)
+1: That's quite a good piece of poetry!
Daniel Vassallo
I love you, mr. compiler. Now please stop caring so much about types.
Thank you compiler, but perhaps if you weren't commenting on StackOverflow, you could get me a drink and play some nice music while you're working?
Andrei Krotkov

The advantage of HLL's is even greater when you compare assembly to a higher level language than C, e.g. Java or Python or Ruby. For instance, these languages have garbage collection: no need to worry about when to free a chunk of memory, and no memory leaks or bugs due to freeing too early.


As others mentioned before, the reason for any tool to exist is how efficiently it can work. As HLLs can accomplish the same jobs as many lines of asm code I guess it's natural for assembly to be superseded by other languages. And for the close-to-hardware fiddling - there's inline assembly in C and other variants as per language. Dr. Paul Carter in says in the PC Assembly Language

"...a better understanding of how computers really work at a lower level than in programming languages like Pascal. By gaining a deeper understanding of how computers work, the reader can often be much more productive developing software in higher level languages such as C and C++. Learning to program in assembly language is an excellent way to achieve this goal."

We've got introduction to assembly in my college courses. It'll help to clear concepts. However I doubt any of us would write 90% of code in assembly. How relevant is in-depth assembly knowledge today?

+4  A: 

As a developer who spends most of his time in the embedded programming world, I would argue that assembly is far from a dead/obsolete language. There is a certain close-to-the-metal level of coding (for example, in drivers) that sometimes cannot be expressed as accurately or efficiently in a higher-level language. We write nearly all of our hardware interface routines in assembler.

That being said, this assembly code is wrapped such that it can be called from C code and is treated like a library. We don't write the entire program in assembly for many reasons. First and foremost is portability; our code base is used on several products that use different architectures and we want to maximize the amount of code that can be shared between them. Second is developer familiarity. Simply put, schools don't teach assembly like they used to, and our developers are far more productive in C than in assembly. Also, we have a wide variety of "extras" (things like libraries, debuggers, static analysis tools, etc) available for our C code that aren't available for assembly language code. Even if we wanted to write a pure-assembly program, we would not be able to because several critical hardware libraries are only available as C libs. In one sense, it's a chicken/egg problem. People are driven away from assembly because there aren't as many libraries and development/debug tools available for it, but the libs/tools don't exist because not enough people use assembly to warrant the effort creating them.

In the end, there is a time and a place for just about any language. People use what they are most familiar and productive with. There will probably always be a place in a programmer's repertoire for assembly, but most programmers will find that they can write code in a higher-level language that is almost as efficient in far less time.

+1  A: 

Flipping through these answers, I'd bet 9/10 of the responders have never worked with assembly.

This is an ages old question that comes up every so often and you get the same, mostly misinformed answers. If it weren't for portability, I'd still do everything in assembly myself. Even then, I code in C almost like I did in assembly.

+1  A: 

You people are crazypeople

I got marked down -4 for making this point more subtly :-(

C is a macro assembler! And it's the best one!

It can do nearly everything assembly can, it can be portable and in most of the rare cases where it can't do something you can still use embedded assembly code. This leaves only a small fraction of programs that you absolutely need to write in assembly and nothing but assembly.

And the higher level abstractions and the portability make it more worthwhile for most people to write system software in C. And although you might not need portability now if you invest a lot of time and money in writing some program you might not want to limit yourself in what you'll be able to use it for in the future.


I'd guess ASM on even x86(_64) makes sense in cases where you gain a lot by utilizing instructions that are difficult for a compiler to optimize for. x264 for example uses a lot of asm for its encoding, and the speed gains are huge.


Why? Simple.

Compare this :

        for (var i = 1; i <= 100; i++)
            if (i % 3 == 0)
            if (i % 5 == 0)
            if (i % 3 != 0 && i % 5 != 0)


.locals init (
    [0] int32 i)
L_0000: ldc.i4.1 
L_0001: stloc.0 
L_0002: br.s L_003b
L_0004: ldloc.0 
L_0005: ldc.i4.3 
L_0006: rem 
L_0007: brtrue.s L_0013
L_0009: ldstr "Fizz"
L_000e: call void [mscorlib]System.Console::Write(string)
L_0013: ldloc.0 
L_0014: ldc.i4.5 
L_0015: rem 
L_0016: brtrue.s L_0022
L_0018: ldstr "Buzz"
L_001d: call void [mscorlib]System.Console::Write(string)
L_0022: ldloc.0 
L_0023: ldc.i4.3 
L_0024: rem 
L_0025: brfalse.s L_0032
L_0027: ldloc.0 
L_0028: ldc.i4.5 
L_0029: rem 
L_002a: brfalse.s L_0032
L_002c: ldloc.0 
L_002d: call void [mscorlib]System.Console::Write(int32)
L_0032: call void [mscorlib]System.Console::WriteLine()
L_0037: ldloc.0 
L_0038: ldc.i4.1 
L_0039: add 
L_003a: stloc.0 
L_003b: ldloc.0 
L_003c: ldc.i4.s 100
L_003e: ble.s L_0004
L_0040: ret 

They're identical feature-wise. The second one isn't even assembler but .NET IL (Intermediary Language, similar to Java's bytecode). The second compilation transforms the IL into native code (i.e. almost assembler), making it even more cryptical.

Andrei Rinea