Nearly 100 upvotes for a page that fails its stated goal and which spends 100's of lines to do something you could do with one system call (sys_write) and a string constant?
The stated goal is not the real point. The real point is to learn about how programs are executed on real systems. Unfortunately, the second half which would (hopefully) have completed the example does not exist.
What you linked to is great, but it uses a different approach to explain the subject. That approach presents the correct thing to do, and explains some of it. The benefit of this approach is that it's short and sweet, but the downside is it's easy to miss subtle points. For example, what you linked to never explains why you have to call sys_exit. Someone reading this would know that's the right thing to do, but they may never really understand why that's so.
An alternative approach - which the posted article does - is to try the obvious but wrong thing, then explain why it fails. Fix that problem, and try the next obvious but wrong thing and keep iterating. The problem with this approach it can be a long process, particularly if you just want to know how to do something and are less interested in the why. But the benefit is that by seeing how things fail, and then seeing the fix for them, the reader can gain a deeper understanding of what's going on.
In general terms, one is more of a reference, and the other is more of a lesson. I like the try, fail, fix iteration for explaining things. I've used it many times when teaching. I find that it matches well with what we would actually do on our own, and for that reason, tends to stick with people better than simply saying "this is how to do it."
I'd be more inclined to sympathize if it had actually worked. As it stands it is a perfect example of how little knowledge of what goes on under the hood is present with the current generation of programmers. That's sad, because even if you never use that knowledge in your 'day job' I think that such knowledge does make you a better programmer.
If you write a blog post about something like this at least finish the damn thing rather than to leave a bunch of obviously wrong snippets laying around to confuse whoever lands on that page.
There are plenty of good pages on introductory assembler on the web, this isn't one of those and I'm really surprised to see it this high on the homepage. Maybe it shows how much the HN crowd would like to get a little bit of insight of what actually powers their computers, the error is mine in assuming that such knowledge would be commonplace here.
I upvoted it because if the reader reads through it, they will leave with more understanding of the system stack than they started with. As someone who has been deeply involved with teaching a systems class, that's near-and-dear to my heart. I think it succeeds in that goal. I'm far less concerned that it doesn't actually emit "hello, world".
That it fails at being an introduction to assembly is, I think, missing the point. It doesn't try to be. It's just trying to demystify some of the system stack.
As for HN itself, I've known for a while now that there's a pretty wide range of people here. While I think the percentage of people will almost no systems experience is more than it was a few years ago, the number wasn't zero a few years ago, either.
You're right about the current generation of programmers, but there might be more to it than "kids are lazy these days". Those programmers don't know much about system programming and assembly but they know about Java/C#, Python/Ruby/Perl/PHP, JavaScript, CSS, Unix command line tools, Windows, maybe a GUI toolkit or two, etc. The software world has been building layers of abstractions over the years to accelerate development of richer applications and it's just natural that we find more people working at higher level of abstractions today than before.
The xorl is one byte smaller, and can be faster. On modern CPUs it's more about the compactness of code than speed, but on some embedded CPUs you can save a cycle or two this way.
Both will work. The xor version is an old trick that many years ago was faster to execute. I do not think that is still the case, but there is still the difference that the XOR opcode is only one byte and the mov version is multiple, so it saves a few bytes in the executable.
It is not 100% a "smaller is better" choice. You also will want to check whether an instruction depends on an earlier one (for example, the XOR technically needs to read the register; if the CPU does not know that that is not actually the case, a self-XOR may introduce pipeline bubbles), what instruction unit (if any) it uses, and whether you want to preserve flags.
The xorl instruction uses fewer bytes than the mov. (The movl instruction encoding has the bytes needed for a 32 bit constant, while the xorl instruction encoding would not)
I think in this case it's a case of not being able to easily determine if "mov ebx, 0" is copying a value into a subregister, making the result dependent on previous operations, or if it's clearing a register. With xor (and sub too, I believe) the processor assumes that no such dependencies exist and can execute the instruction in parallel with others.
The second thought was, what the heck are people being taught in school these days? Can you get a CS degree these days without writing a compiler? Seriously?
As a tutorial on a blog about Arduino's or some other processor family, great stuff. As a blog entry from a company like Oracle, not so much.
And as others pointed out, had the person approached it from first principles they would have arrived at the equivalent of 'puts()' a lot sooner.
The link for Part 2 seems to have been removed from the site, someone linked Part 2 on G+[0] on Lamernews, where I originally found this part 1 as well.
gcc -m32 -static -nostdlib -x c - <<< 'int main(void) { int s = 12; char *m = "hello, world"; int n = 1, d = s - 8; asm("int $0x80"); d = (n = 0) + 1; asm("int $0x80"); }' && ./a.out # Hello from a libc-free world on Darwin 11.2.0, GCC 4.2.1, x86
It's not even that much harder to actually print something without libc; just include your own stub for write(2).