Slashdot Mirror


Why Learning Assembly Language Is Still Good

nickirelan writes "Why Learning Assembly Language Is Still a Good Idea by Randall Hyde -- Randall Hyde makes his case for why learning assembly language is still relevant today. The key, says Randall, is to learn how to efficiently implement an application, and the best implementations are written by those who've mastered assembly language. Randall is the author of Write Great Code (from No Starch Press)."

28 of 667 comments (clear)

  1. Debugging by Ann+Elk · · Score: 5, Insightful

    Another reason: Sooner or later, you'll need to debug something without a source-level debugger. Knowing how to debug raw assembly language has saved my ass many times.

    1. Re:Debugging by Tony-A · · Score: 5, Interesting

      Absolutely.

      Disclaimer: I learned to debug before I learned to code.
      With extremely few exceptions, machine code performs exactly as advertised. When things are not exactly as they should be, it helps to be able to see exactly what is going on.

      Performance is much more a matter of structure (exponential complexity) than language (poor linear complexity). As to level, "high level" languages limit you to their implementation of a few concepts. Depending on where the heavy lifting is, Perl could easily outperform optimized C.

    2. Re:Debugging by Percy_Blakeney · · Score: 5, Insightful
      Depending on where the heavy lifting is, Perl could easily outperform optimized C.

      But if Perl is written in C, wouldn't that mean that Perl can never be "faster" than C?

      To put it more concretely, couldn't I just write a program in C that does EXACTLY what the Perl program does, down to the last data structure? And if I did, wouldn't that mean that Perl can't ever (theoretically) be faster than C?

      You could even take it a step further. You could write an exact duplicate of the Perl program, leave out the parts of the Perl interpreter that you don't use, and you probably would end up with an overall faster program. Thus, in most cases, C could trump Perl.

  2. Why it's still good... by WilliamsDA · · Score: 5, Interesting

    Also, don't forget, a good deal of programming is still done in assembly. Both in a job I've had coding stuff and in my current research (crypto), I did/do a lot of assembly programming. Yes, learning assembly will make a better programmer out of those who never will code assembly again, but for some people, assembly is a valuable and often-used skill

  3. Schools not teaching assembly anymore by csimpkins · · Score: 5, Interesting

    It's a shame that schools are phasing assembly classes out of their computer science curriculums. If anything, it makes for a great foundation on which to learn more modern languages while teaching students things about computers that they probably wouldn't take the time to learn otherwise.

    1. Re:Schools not teaching assembly anymore by thegrassyknowl · · Score: 5, Insightful

      I was fortunate enough to learn assembly on a few architectures. Admittedly all of them are microcontrollers (PIC, AVR, HC11), but it really does force you to understand how the machine is working.

      Some of the more serious asselbly languages still scare the hell out of me though; have you ever looked at the assembly for the TI C6x DSPs? It took me quite a while to come to terms with something simple, and the C compiler can better use the 8 parallel execution units better than I can...

      --
      I drink to make other people interesting!
    2. Re:Schools not teaching assembly anymore by dsheeks · · Score: 5, Interesting

      Knowing something about the low level hardware / machine instructions and what compilers do to translate high level languages definitely helps programmers make better programming decisions.

      Given the rise of byte code environments like Java and .NET and the sophisticated tools available for working with them, I would think schools would do well to teach a class programming at that level. While obviously not a true assembly language, something like Java byte code is a lower level look at how programs really work, and since Java is highly portable you wouldn't have to worry about what hardware the students used like you would with an actual assembly language course. I still think doing some work with assembly and getting some exposure to hardware architectures is best, but this might be a reasonable alternative.

  4. don't bother........ by Anonymous Coward · · Score: 5, Insightful

    Hate to say, but the kind of optimization you learn about by knowing assembly language is just not necessary for most programmers these days.

    I learned programming in the 80's, and I did learn assembly language, starting with 6502 assembly. I would subconciously code my C so that it would produce faster code. Every block of code I wrote would be optimized as much as practical. My code was fast and confusing.

    When coding Perl or Java I would keep in mind the details of the underlying virtual machine so I could avoid wasteful string concatenation or whatever. I cache things whenever possible, use temp variables all the time, etc., etc.

    I've spent the last few years trying to UNLEARN this useless habit. There is just no need. And in highly dynamic languages like Ruby, it's pointless. You can't predict where the bottlenecks will show up.. almost every project I've worked on has either had no performance problems, or had a couple major performance problems that were solved by profiling and correcting a bad algorithm.

    Stuff like XP and agile development have it right: code as simply as possible, don't code for performance, then when you need performance you can drill down and figure out how to do it.

    To me a beautiful piece of code is one that is so simple it does exactly what it needs, and nothing more, and it reads like pseudo-code. Minimalism is the name of the game.

    So my advice is, don't learn assembly language. Learn Lisp or another abstract language. Think in terms of functions and algorithms, not registers and page faults. Learn to program minimally.

    On another note, the tab in my Konqueror for this article reads: "Slashdot | Why Learning Ass...". Heh. :-)

    1. Re:don't bother........ by MBCook · · Score: 5, Insightful
      I disagree.

      I have seen FAR FAR too many students in my various college programing classes who think nothing of calling functions with 15 parameters and copies of large datastructures (not references) and other such things. I really think that assembly should be one of the FIRST things taught to future programmers. So many people I've run up against don't have any idea how computers work. Sure things are "mentioned" in classes, but so much is lost on them. Somthing as simple as "passing 2 things is much MUCH faster/easier than passing 10" don't get taught.

      By passing 10 things, their job is easy. That's all they see. They don't know about registers (other than they exist and are sorta like variables on the CPU). So they don't know that to pass 10 things you might put some in registers but the rest will have to be passed in memory (which is slow) as opposed to puting everything in registers (if at all possible) which is faster (especially for simple functions).

      The only problem with assembly is the catch-22 mentioned in the article: you have to do all sorts of "magic" to print out to the screen or read from the keyboard, which can be confusing. And it takes a while to get them up to the point where they can start to understand that magic. My school teaches assembly (sorta) on little 68HC12 development boards that have built in callable routines that perform things equivelent to printf and such, so there is little voodoo involved which is nice.

      I'm not saying assembly is neccessary, but I DEFINATLY think it's important for programers to learn how things work under the compiler. I have seen FAR too many hideous bits of code that no one who understood the underpinnings of assembly would never dream of.

      --
      Comment forecast: Bits of genius surrounded by a sea of mediocrity.
    2. Re:don't bother........ by Smidge204 · · Score: 5, Insightful

      So basically you don't have time to do it right, but you might have time to do it twice?

      Learning assembly isn't all about optimization, either. Being familiar with how the machine works right down to the core will make you a better programmer, peroid. Personally speaking, it also helps develop that zen like ability to "think like the computer", and that helps you program not just more efficiently but more effectively since you can think things out better. You can't tell me you're not a better programmer for having been exposed to it... it simply changes the way you think about the machine.

      It can also be argued that "beautiful" code has no bearing on performance. It's also the kind of "Oh performance isn't an issue anymore" and "make te source code pretty" thinking that we now need gigahert+ machines with 128MB RAM just to write a goddamn letter... it's really quite sad that so many programmers just let their applications fill the hardware vacuum they think their users will have, or should have, just because they didn't take an extra day to think about what they're doing and write their code a little more efficiently.
      =Smidge=

    3. Re:don't bother........ by Elladan · · Score: 5, Insightful
      While the general idea you're expressing - that people should understand how computers work to program them - is a good one, I think you're missing the point to a large degree.

      The things that are most important in performance are, generally speaking, algorithms. It's important to understand things like:
      • Cache - the computer operates faster on small working sets.
      • Algorithm efficiency - O(nlogn) is better than O(n^2) for most problems.
      • Latency - network or disk round trips are bad.

      Etc. The sort of thing you're proposing, with stuff like function call arguments, loop conditionals, etc. are micro-optimizations, and are very seldom worthwhile for programmers. Micro-optimizations are almost always best left to the compiler writers, who can, in effect, program them once and let everyone reap the benefits.

      Consider your example in particular: A function with 2 arguments instead of 10 isn't really faster. First off, it's only slower on an x86 - many architectures have these things called registers, which you can use for things like function arguments. Second, those function arguments are spilled to the stack just before the function call jump. This means they're extremely hot in the D$, and will hardly even be any more expensive than a register to reload at all. Third, if you break the big function into a lot of little ones, you're incurring more call overhead and more pressure on the I$. Fourth, breaking the function up causes multiple copies of the function prologues and epilogues, which will easily overwhelm the register spilling cost. Etc. etc. etc.

      In other words, those 10 arguments are only microscopically slower, and may even be faster!

      In this case, the student should avoid writing a function with 10 arguments if it makes the code clearer. The value of this sort of incredibly trivial micro-optimization is fundamentally dwarfed by the value of readable code - if the student can read her code, that means she'll have fewer bugs and can spend more time optimizing it. And that's what'll really make the program faster.

      You should only consider worrying about optimizations at this level if you've already optimized your program at an algorithm level fully, have profiled it, and determined some particular pieces are extremely dense hot-spots that need to be improved by hand. But if you're doing that, you may want to consider recoding the hot-spots in assembly anyway.

      These days, these sorts of hot spots tend to be media codecs, and the way to speed those up is to use SIMD instructions - which can only be used properly from asm. So even before worrying about these sorts of extremely tight micro-optimizations, you'd want to recode in assembly just to use the special vector instructions! And in asm, readability is even harder to obtain, so you'll probably avoid a lot of the sort of micro-optimizations a crazy compiler will do just so you can make sure the code works right.
    4. Re:don't bother........ by DrSchlock · · Score: 5, Funny
      I have a favorite fortune on my system...

      The First Rule of Program Optimization:
      Don't do it.

      The Second Rule of Program Optimization (for experts only!):
      Don't do it yet.
  5. Yes and no... by Daniel_Staal · · Score: 5, Insightful

    While I learned assembly, and found it useful for learning to understand exactly how the machines think, I'm not sure I agree with his basic premise. Namely, that great code (code that is well designed for it's job, and easy to work with and under) is always the efficient code, in machine terms.

    The machine thinks one way. A human thinks in another. Code that is well designed for easy updating, and extending, is code that is easy for a human to understand. If that is not the most efficient way for the machine to do it, that may be the price for 'great' code in this project. (The ideal balance depends on the project, of course. A kernel should be machine-efficient, for example.)

    --
    'Sensible' is a curse word.
  6. I disagree by nacturation · · Score: 5, Insightful

    Efficiency in terms of coding is a wonderful art and I think it's still applicable today. Kernel-level routines, games, drivers, etc. all benefit from tight coding in assembly language.

    But let's be honest here. Computer Science 101: an efficient algorithm coded in an inefficient way will always beat out an inefficient algorithm coded by hand in 100% optimized assembly. I'll put my crudely coded Javascript quicksort algorithm against your finely honed 100% assembly bubblesort algorithm any day. Not only will my algorithm beat the pants off of your algorithm, but I'll also code it in far less time and with way fewer debugging sessions than you would. Also, the higher-level language you go, the better it is for security. How easy is it to introduce things like buffer overflows, array out of bounds, etc. errors in assembly? How easy is it to do that in Java, C#, etc.?

    So yes, writing in assembly language is still good and has its places. But let's keep it to those places, shall we?

    --
    Want to improve your Karma? Instead of "Post Anonymously", try the "Post Humously" option.
  7. Re:Smaller code? We can hope... by Jeffrey+Baker · · Score: 5, Funny

    Fuck, I'd settle for viruses smaller than 400K! Of all things, you'd expect a virus to be lean and mean, but I guess the latest crops were made with Visual Virus .NET or something to that effect.

  8. how many people actually program in assembly? by Doppler00 · · Score: 5, Interesting

    I've programmed a few embedded systems in assembly and it's not very fun at all.

    To make matters worse, each CPU has it's own instruction set, and special set of commands that you must learn before you can even sit down and start writing code.

    With C++ or at least a C compiler, you don't need to worry about so many implementation details. You should only resort to assembly if you absolutely, must have the performance required. Maybe the author of this article forgets how difficult it is to debug assembly code, or how difficult it is to implement abstract concepts such as OO at such a low level.

    I don't agree at all that writing "efficient code" necessarily creates better code. Writing "clearer" is better from a quality standard.

    We have compilers for a reason, to produce assembly code as efficiently as possible for a higher level language. Most 99% of the time, the compiler will optomize the code just as well, or better than you can.

    I would still recommend learning assembly language to C++ programmers simply so they understand how the computer is actually working. But to require anyone to program in assembly requires a great deal of justification.

  9. In what other languages by foidulus · · Score: 5, Funny

    can you get away with naming a source file org.asm?
    * rim shot
    I apologize.

  10. So What? by tomblackwell · · Score: 5, Insightful

    Wow. You can crash a machine with assembly language.

    That may seem impressive to you (especially if you're fourteen), but the fact is that exploits can be done in almost any language.

    In other news, this doesn't have a hell of a lot to do with the posted article, either.

  11. As somebody who has done DSP algorithms by earthforce_1 · · Score: 5, Informative

    Assembly language will always be needed to optimize certain types of algorithms, that don't translate efficiently into C. Try writing a FFT algorithm on C using a DSP, and compare it to what can be done in native assembly. The difference can be an order of magnitude or more. Some processors have special purpose modulo registers and addressing modes (such as bit reverse) that don't translate well into C, at least not without extending the language. Fixed point arithmatic operations are not supported in ANSI C either, but are a common feature on special purpose processors.

    For low power/embedded applications, efficiency makes sense as well. Every CPU cycle wasted chips away at battery power. A more efficient algorithm means a smaller ROM size, and the CPU can either be clocked slower (can use cheaper memory and/or CPU) or put into a halted state when it isn't needed. (longer battery life) Coding small ISRs in assembly makes sense as well, as C compilers often must make worst case assumptions about saving processor context.

    That being said, only a fool would try and re-write printf or cout in assembly, if they have a C/C++ compiler handy. Hand optimization is best used as a silver bullet, for the most computationally intensive or critical functions.

    --
    My rights don't need management.
  12. Try the games industry by Jack+Porter · · Score: 5, Interesting

    While the majority of the Unreal engine is C++, we often write assembly-code versions of critical functions for specific platforms. Of course this is done after the C++ versions are tried and tested, and the bottlenecks are idetified.

    To take full advantage of processor features like SSE or AltiVec you don't really have a choice.

    For example, UT2004 contains SSE and AltiVec assembly versions of some of the vector and matrix manipulation functions, some of the visibility culling code, etc. The amount of work Dan Vogel put into this kind of optimization is one of the reasons that UT2004 runs better than UT2003 on the same hardware.

    Learning assembly language is useful, as it's sometimes the right tool for the job.

  13. The problem with assembly... by jafo · · Score: 5, Insightful

    Quoting: "the best implementations are written by those who've mastered assembly language".

    I haven't read this book, but I'd hope that there would be some pretty good justification of the above statement. I suspect that it's not, though. First of all, who defines what the "best implementation" is?

    As Knuth says, the first rule of program optimization is: "Don't do it". Trying to optimize a program when you're writing it leads to all sorts of problems including difficult to maintain code, increated time and budget required for the project, and often it's not even a hot spot anyway.

    I used to be very concerned about using making my code fast, but have (over the decades) decided that making it obvious is much more important than speed, particularly in the initial implementation. Profiling allows you to concentrate on the 20% of the code that the program is actually spending 80% of it's time in, instead of guessing where the hot spots are going to be.

    I've found that another benefit of using simpler code is that I'm more likely to throw away whole sections of simpler code and try radically different algorithms or mechanisms. More complicated code I find I'll try to just tweek instead of dumping wholesale. Randically different approaches can lead to 10x speedups where tweeks of existing code may give you 2x speedups, if you're lucky.

    Don't get me wrong, I'm all for trying different approaches. I'm not sure I would have come to the same conclusion I have now if I hadn't spent quite a long time trying to write optimized code. It was a very different world back then, but I know I wasted a lot of time optimizing code that didn't at all need it. It was an experience though.

    Sean

  14. Re:Smaller code? We can hope... by Just+Some+Guy · · Score: 5, Insightful
    Misuse of high level languages such as visual basic, as well as off the shelf components for everything, has led to a level of code bloat in todays applications that is inexcusable.

    You, sir, are insane. Much of my job involves pushing around regular expressions and hash tables (aka associative arrays aka dictionaries). I know several flavors of assembler on distinct hardware platforms (x86, 68k, 6502, MIPS) so I say this out of experience rather than fear of the unknown: I'd rather swallow my own tongue than write anything non-trivial in a low-level language.

    Seriously, a lot of people who know what they're doing have provided a huge library of functionality for me to pick and choose from. If I need to write a GUI app, I'll do it in Python with GTK or QT bindings. I am competent to build it in assembler, but why? It wouldn't be portable, it'd shave a very small amount of size from the end product (most of the project's resources are likely to be spent in the GUI libraries and not the core of the program), and would take 20 times longer than necessary.

    There are a very few areas where low-level languages make sense. I haven't touched any of them in years.

    --
    Dewey, what part of this looks like authorities should be involved?
  15. Counterpoint by Temporal · · Score: 5, Insightful

    This guy says "Efficiency Is the Key". This guy is wrong.

    With the incredible power provided to us by modern CPU's, efficiency is just about completely irrelevant for 99% of non-game applications. Think... when was the last time you thought "This word processor just doesn't respond to my keypresses fast enough." or "AIM takes way too long to open a new IM window."? The reason why these programs aren't getting "faster" (as the article complains) is because there is no way to do so. They spend 99.9% of their time waiting for user input already.

    Optimizing code which doesn't need optimization is Bad with a capital 'B'. When optimizing code, there is almost always a tradeoff between efficiency and maintainability. Efficiency often requires cutting corners, killing opportunities for future expansion, or, at the very least, writing ugly code. When that added efficiency does not lead to any noticeable benefit to the user, why do it?

    Now, granted, you shouldn't use an O(n) algorithm when an O(lg n) one exists to solve the same problem. However, knowing the difference between O(n) and O(lg n) has nothing to do with knowing assembly. The only benefits you can get out of knowing assembly are constant-multiplier speed increases. And, frankly, shaving off 50% of 0.1% CPU time used is not going to help much.

    Really, the speed of modern CPU's is sickening. I can't count the number of times I've written a piece of code, thought "This is going to be so slow...", then watched it execute near instantaneously. Even when running programs in a prototype programming language I'm working on -- which currently runs about 40x slower than C, because it's a crappy prototype -- this happens to me regularly. The only time your code is going to be noticeably slow is if you are processing a very, very large data set or you are using slow algorithms. In the former case, sure, knowing assembly will help, but such cases are extremely rare in typical applications. In the latter case, find a better algorithm.

  16. Problems with article by Percy_Blakeney · · Score: 5, Insightful
    I agree with the underlying premise that more programmers should learn an assembly language and the intimate details of how a computer works. However, I disagree with several part of the article.

    - He faults inefficient coding for the failure of software speed to keep up with CPU speed (or at least, its a "large part".) This is much less true than he lets on; Amdahl's Law means that the CPU is less and less responsible for the speed of an application, while things such as disk seek/transfer times, memory access times, and network latency all play huge roles in the speed of your computer's software.

    - He seems to think that it's not terribly hard to become an "efficient" assembly language programmer. Bzzt, wrong! In the modern era of superscalar architectures, pipelining, processor specific instructions, branch delays, and memory heirarchies, it takes a hell of a lot of knowledge and experience to beat the performance of a good compiler.

    - He apparently hasn't tried any large assembly language porting efforts lately. I'd love to see the effort involved in porting a large x86 assembly language program to a MIPS architecture, all the while maintaining that coveted "ultra-efficiency". The reality is that a good compiler can be reasonably efficient at porting a program to a new architecture, while a programmer usually isn't.

    - He also apparently hasn't tried debugging a large chunk of assembly code lately. It is a fact of life that it is very difficult to debug assembly. By using a high-level language, you are increasing the readability of your software, which tends to decreases the number of bugs.

    I could go on, but needless to say, I'm not impressed with the numerous assumptions and generalizations about assembly that he makes. Learning assembly will make your high-level programming better, and limited use of it can be appropriate, but using it all over the place is a huge mistake.

  17. "Premature optimization is the root of all evil" by richieb · · Score: 5, Interesting
    To quote Donald Knuth.

    Having said that, knowing assembler is useful because it teaches you how the machine works.

    However, most modern compilers can generate code that is much faster than handwritten assembler - especially because they know how to take advantage of the specialized processor architectures (hyper-threading, pipeling etc).

    --
    ...richie - It is a good day to code.
  18. Because you can't always trust compilers by soullessbastard · · Score: 5, Insightful

    One thing that many programmers take for granted these days is that compilers produce correct code nearly all the time. They've gotten really good over the years and are really a testament to the quality of compiler engineers. Even so...

    I've been a programmer for over a decade and I've always found the worst problems to debug are when the problems aren't in your code but in the compiler. Compilers are programs too and have their own bugs. They aren't always 100% accurate at generating correct machine code for your source. And until the compiler gets fixed in the next patch or rev, you may be stuck with broken code unless you switch compilers.

    Sometimes disassembly of the problem code and inlining correct assembly can be the difference between shipping a product or missing a deadline because you've spent months sitting around for the next compiler version to fix your problem for you.

    ed

  19. Absolutely by KidSock · · Score: 5, Insightful

    I didn't start programming until I was in my mid 20s (degree in Chemistry). I liked fiddling with Java but always felt uncomfortable about what was going on underneath the hood. So I took a few classes. The first was Computer Systems Architecture. We wrote a game in x86 assembler. That class completely opened up my understanding how programs actually worked. To understand the stack, the state machine nature of things, and memory was an awakening experience.

    Now (~5yrs later) I'm a fully capable programmer and an even better designer. My preference is C, binary file formats, networking protocols, crafting elegant solutions for multiplexing IO. I'm lead on a project used in production by many companies large and small.

    I genuinely feel assembler is a vital part of the learning process for a programmer.

  20. More important to read than write by Diomidis+Spinellis · · Score: 5, Interesting
    It is vastly more important to be able to read assembly code than write it. In most cases this involves reading the code the compiler generates.

    An earlier poster mentioned how such a skill can help you find compiler bugs. This can be the case, but it is rare; I have located two such bugs in 20 years of programming. A more common use is to locate bugs in your code. When your brain refuses to see the missing braces around the wrongly indented code, or an spurious semicolon at the end of an if or while statement, reading the generated assembly code can save some extra hours of frustration. You will be able to see that the code the compiler generates differs from the code you think you wrote, and this will point you to the bug's location.

    As I argue in Code Reading, other cases where reading assembly code can be of use are:

    • to understand how an implementation-defined operation (e.g. a type cast) is actually performed,
    • to see how compiler optimizations affect the resulting code,
    • to verify that hardware-specific code written in C/C++ actually performs the operations you expect, and
    • to learn how a particular construct can be written in symbolic code.

    To read compiler-generated assembly code you need:

    • An understanding of the processor's architecture: registers, instruction format, addressing modes. See for example Intel's Pentium Architecture Manual.
    • A handbook of the processor's instruction set. Again, see for example Intel's Pentium Instruction Set Reference Manual A-M and Intel's Pentium Instruction Set Reference Manual N-Z.
    • An appreciation of how compilers generate code for modern structured languages. The key ideas here are the stack as a way to handle nested function and method calls, the frame pointer as a way to access function arguments and local variables, and the virtual function table often used for implementing dynamic dispatch in OO languages. The Red Dragon Book is the venerable classic here.
    • A way to obtain an assembly code listing of your high-level language code. The Unix compiler's -S switch, and the Java SDK "javap -c" command are two methods I often use. In gdb you can use the disassemble, nexti, and stepi commands to examine your program at the level of discrete processor instructions.

    Obligatory "hello, world" program written in i386 assembly:

    hello: .string "hello, world\n"
    .globl main
    main:
    pushl $13
    pushl $hello
    pushl $1
    call write
    addl $12, %esp
    xorl %eax, %eax
    ret

    Diomidis Spinellis - #include "/dev/tty"