Hacker News new | ask | show | jobs
Learning C and ASM, what's the way to go?
15 points by hilarious 6081 days ago
I'd like to learn C and ASM (on x86-64) The documentation I have varies between old books from the 70's, and tutorials from websites with the grammar of 16 year olds, from miserable sites. I'm not sure how best to attack this problem. I'd like to learn how to program in C and in ASM, I've read basic things, and understand their usefulness, but I don't know what to read! I have a number of people tell me that they've read near to nothing, but I don't think I have this sort of mindset.

Kind elders of Y, give me guidance.

Thanks

15 comments

I'd like to second the K&R book.

In addition, I've found if you're taking an engineering approach, "Applications Programming in ANSI C" by Johnsonbaugh & Kalin was to me a very valuable learning tool.

Do not go without the "C: A Reference Manual" by Harbison & Steele, which to me has been the most valuable reference book to have on my person if I couldn't get or chose not to fancy a good Internet reference.

For Assembly, my coverage has been limited to MIPS, which was in comparison to Intel's version, a lot easier to understand and thus learn from. Check out "Computer Architecture and Design" by Patterson & Hennesy. While of course mostly a book on architecture, it's rooted in learning MIPS to understand architecture and comes with the SPIM simulator software(which I assume could be had online). I also own the book by Bryant & O'Hallaron, "Computer Systems: A Programmer's Perspective" and personally I found that learning MIPS first brought home Intel's ASM a little softer.

Lovely note, a question, however -- I er, got "C: A Reference Manual" for my birthday, (which got me into this whole business), but it looks very advanced, shall I read it as my first book anyway? and ask questions where I falter? Or, should I go for something more basic?

Thanks again!

My advice is absolutely not. References are just that - to be looked up for something you've lost or just don't have the capacity for in your own memory; they're not made to be read back to back, or at least I could not do that. Question to ask might be, would you read the English dictionary back to back? Kudos to those that can or would. :)

You talked about learning C and ASM, and K&R and the other books (excluding C:ARM and CS:APP) are fine learning tools. So to answer your question, do not read it first, but have it by your side when something isn't clear... think of it like a dictionary to look up functions that were not well addressed (or even talked about at all) in the learning books.

Oh, okay -- Well, I'll make sure I have it handy :)
If you want to learn x86-64 assembly language, I recommend a historical approach: Start by learning 8086 assembly language, then learn 80386 (i.e., 32-bit x86) assembly language, then learn MMX/SSE assembly language; and only once you've mastered all of those, start on x86-64.

The x86 instruction set is kludges built upon kludges, and you're never going to understand it fully if you try to jump in at the end without seeing how it developed.

I learned asm starting with MIPS and then had the luxury of working at a place that was designing MIPS hardware. It was nice to be able to get into the assembler when some kernel modification wasn't working very well.

I have only good things to say about MIPS as a great place to learn ASM. The thing is, the better you understand how processors and pipelines work, the better you'll understand why instruction sets are the way they are.

If you want to learn a very bad assembler (for programmers) but one that's very to understand (for microcontroller designers), there's always 68HC11. How do two 8-bit registers and two 16-bit registers make you feel? (Probably like going to/from memory quite a bit :)

Agreed, the biggest switch is probably from 286 to 386.

486 and Pentium didn't really do much instruction set wise (sure there were changes), then the next big change is the 64 bit systems.

edit: What do you mean kludges ? It's the most orthogonal instruction set known to man!

Forget everything about the code, data, and stack segments.
The confusion and the reason you got modded down is that people don't understand that the segmentation is still present in the CPU, but that common practice now is to overlay all segments as a single 4GB space.

In other words, if you really really insisted you could mess around with giving the segment registers different base values and / or lengths but you'd probably end up regretting it.

What do you mean?
He means that you don't need those anymore.

You used to need them (badly), especially on the smaller CPUs because otherwise you were severely limited in memory.

Check out the 'mixed models' that were pretty common usage in the 80's.

There were lots of them:

  code          data            model name
  under 64KB	under 64KB	Small (-ms) or Tiny (-mt)  
  over 64KB	under 64KB	Medium (-mm) 
  under 64KB	over 64KB	Compact (-mc) 
  over 64KB	over 64KB	Large (-ml) 
I was so happy when I finally got out of 'model hell' and could use 'flat' mode using DJGPP. Finally C programming without the headaches.

http://en.wikipedia.org/wiki/DJGPP

You're going to see a lot of references to segment selectors, and apart from the fact that FS may refer to thread information, you're never going to have to remember what any of it means. You can safely consider segmentation to be detritus.
Specialized segment prefixes mean jacksquat in an execution model with no specialized segments.
Do you have any documentation you'd recommend for this, I'm not sure what to read/study.

Thanks for your help cperciva.

For C, absolutely K&R.

For Asm, I concur with cperciva that the best way to go is to start at 8086 and work your way towards more modern assembly.

For 8086 I highly recommend "The 80x86 IBM PC and Compatible Computers (Volumes I & II): Assembly Language, Design, and Interfacing". I learned from this book and thought it was very helpful.

For more modern stuff I really enjoyed "Computer Systems: A Programmer's Perspective". It will be most beneficial after reading through K&R and being familiar with ASM. It focuses a lot on programming techniques, tips, and tricks so that compiled C/C++ code is turned into efficient assembly.

Finally, if you'd like to build a whole system end to end, the Motorola 68HC11 microcontroller is a fun little piece of hardware to play around with. "MC68HC11: An Introduction to Software and Hardware Interfacing" is a good book for this purpose.

Best wishes on your journey into the low-level programming world!

PS. I'm biased. I have read and own all of the above mentioned books. Thanks for getting me to brush off the dust again ;)

The best way to learn assembly is to do it on a risc chip, then work up to a CISC chip.

So pic, mips, etc first, then X86

It might help to take a step back and ask why first. Are you working on a project that requires both?

If you just want mercenary ability with C and ASM, you'll have no problem finding the resources - just a matter of finding the best book. I'm sure you'll get plenty of recommendations here.

It sounds you want to enrich your general programming knowledge though. In that case I'd recommend learning computer architecture concepts - once you have that down, learning C and ASM will be a pretty transparent process. In fact, I'd recommend it even if you just need it to hack on something specific. I took an architecture course at uni that used this book, and it was pretty decent: http://www.amazon.com/Computer-Organization-Design-Fourth-Ar...

I'll take a look at that, thankyou :)
My favorite C book is "C Interfaces and Implementations" (CII) by Hanson. It's an excellent bridge from Perl/Python to C; in particular, it gives you resizeable arrays and hash tables, which are the two things you will miss most from high level languages. My advice is, learn to code C for a couple months using CII, then tackle assembly. When you see how C programs are decomposed into functions, and how arguments are passed to functions, you'll understand much more about how assembly should work as well.

I've taught a couple people basic x86 assembly using a programmable assembler we wrote in Ruby. A really great place to start with assembly is to be able to define a array of instructions and be able to "jump in" to them and see what they do.

CII looks like it'll be an amazing book! Shame it's not available online, I wish it were, I wouldn't sleep tonight!

I'll probably make a purchase when I get my paycheck though, thanks!

OK. Depending on your programming background you're facing a steep learning curve. That's why I recommend a bottom up approach for you.

First read "Code" by Charles Petzold. This book will get you "in the mood" and in the right frame of mind: http://www.amazon.com/Code-Language-Computer-Hardware-Softwa...

Then I suggest you pick up a good book on Assembler. This might be a good choice: http://www.amazon.com/Professional-Assembly-Language-Program...

Start writing some drivers for Linux. Like a memdrive or something. Do it all in Assembler! Oh, you need to read other books on how to do this...

Then pick up the K&R book on C. Now write your memdrive driver in C.

That should get you started. I think it will take you at least up to two years before you're passed the learning curve and to be comfortable with this level of programming.

Oh, you need to be willing to do it for the love of it because it's highly unlikely that you will make a living using these sort of technologies (nowadays).

Good luck!

PS: I miss the old days...

I wouldn't start off by writing a driver in assembler, probably better to write it in C first, then use the -S flag to get the intermediate and study that until you drop.
I can assure you that if you want to learn C AND Assembler and you start with C, you will never ever get to the Assembler bit. A memdrive isn't that difficult and if you never solve a 'real' problem, you never learn anything because you don't have to push yourself. Just my 2 cents...
It really is your two cents, what goes for you does not go for everybody else.

Some people will learn just for the fun of learning.

You are obviously missing my point. But that's alright...
Writing device drivers in C, and then using the -S flag ... have you seen the output gcc -S on Linux (Ubuntu) returns for a trivial hello world program? ;)
Sure. And for non-trivial programs as well.

Low level assembly is what you want, that presumably includes interfacing with you favorite C code.

Calling conventions, stack frames and so on.

Besides, the boilerplate runtime stuff has nothing to do with writing kernel code, so a 'trivial hello world' program will have a lot of cruft added to it:

        .file   "hello.c"
        .section        .rodata
  .LC0:
        .string "helo, world!"
        .text
  .globl main
        .type   main, @function 
  main:
        leal    4(%esp), %ecx
        andl    $-16, %esp

        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx

        subl    $20, %esp
        movl    $.LC0, (%esp)
        call    puts
        addl    $20, %esp

        popl    %ecx
        popl    %ebp

        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
        .section        .note.GNU-stack,"",@progbits
that's not that bad.

Note the stack frame alignment trick, the fact that 'printf' was specified in the source but puts is being called!

The -S flag was invaluable for me when I was moving from C to assembly. Then again, I used it in an iterative fashion, do something simple -S, do the same thing -S -O1, -S -O2, -S O3, and then a spattering of the different optimization techniques to see how it converted the C to assembly. I miss those days (did I just admit to being old?).
Well I'll admit it right along with you, I miss those days too.

I think I must have coded myself to the moon and back by now if you'd print it all out on fanfold paper (in C, mostly), but the joy of getting a little OS to boot up from nothing is never going to pale in comparison to installing framework X and building some web-app. No matter how successful.

Web-apps make substantially more $ though...

Sounds good, thanks bro, interesting approach ;D
The K&R book is the classic C reference. I'd also recommend the K.N. King book ... C programming: a modern approach.
I recently decided I wanted to learn assembly language. So far I haven't started but I spent an hour or two perusing books on assembly language on Amazon, reading product descriptions and users' reviews, and I decided to start from this one: http://www.amazon.com/Professional-Assembly-Language-Program...

The reasons I chose it are

(1) It's introductory, i.e., a good first book for a complete noob. (2) It's very Linux-centric. Most good books on assembly language assume you use Windows or even DOS it seems. (3) One of the reviews says, "you will get a good workout using the gdb debugger." Sounds like fun.

I highly, highly recommend the book "Programming from the Ground Up". It is freely available, and full of small asm sample programs to try out yourself.

Here's a link:

http://savannah.nongnu.org/projects/pgubook/

Oh, I've been missing out, haven't seen this one, thanks!
highly, highly recommand +1, I'm reading it, it's better than any other program books I've ever read. It tells you what, how, why, and it tells in an interesting way.
The classic C book is The C Programming Language by Kernighan and Ritchie (http://www.amazon.com/Programming-Language-2nd-Brian-Kernigh...).
I worked through Assembly Language for the PC(http://www.amazon.com/Assembly-Language-Brady-programming-li...) in highschool. You start with the basics and at then end you have a working hex editor, for DOS anyway. In terms of programming knowledge gained it was more than any college class I took, heck more than most college semesters.
I second the choice of K&R for learning C -- where better to learn C than from the authors themselves.

For assembly I've had a good experience with K. Irvine's Assembly Language for Intel-Based Computers, available on Amazon here:

http://www.amazon.com/gp/product/0132304686?ie=UTF8&tag=...

Do all the projects in K&R, then buy a pic board and pic compiler and get on it.
For assembly I can recommend Lance Leventhals books.

80386 Programming Guide

And the intel reference manuals.

When I was 18 and decided to first try programming, I picked assembly to start with since I had read somewhere that all other languages could themselves be written in terms of assembly. The book I learned assembly from was Randy Hyde's online version of his textbook Art of Assembly. I used the DOS version, because I didn't know what Unix even was at that time; but here's the newest Linux version: http://homepage.mac.com/randyhyde/webster.cs.ucr.edu/www.art...

Like other commentors, K&R would be my best recommendation for the second book. You might as well start off on the right path towards enlightenment.

Not trying to rub you the wrong way but I'm not interested in learning HLA, which is what AoA covers, purely LLA.

Thanks!

You are exactly right even though Randy won't like you (or me) saying that.