Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
NASM Tutorial (2018) (lmu.edu)
135 points by AlexeyBrin on March 1, 2019 | hide | past | favorite | 31 comments


Assembly is still quite useful in a number of circumstances. The compiler was generating terrible code for a ticket (spin) lock, and rewriting in assembly helped considerably [1].

Its also still the best way to get the most out of AVX and SSE. I find the register allocation to be extremely poor when using intrinsics.

1. https://github.com/JohnSully/KeyDB/blob/unstable/src/fastloc...


Quick question, I was skimming the code and came across this:

  xor eax, eax
  mov ax, 1
Was there a reason you didn't use the shorter

  xor eax, eax
  inc eax

?


I experimented with just mov eax, 1 and found it be slower - though I didn't try inc eax.

Using 16-bit registers is tricky because they leave the upper bits unchanged. Its easy to trigger a partial register hazard inadvertently.

p.s. the comments were nicely lined up in my editor, don't know what happened once it got to github.


> p.s. the comments were nicely lined up in my editor, don't know what happened once it got to github.

probably spaces-vs-tabs. GitHub has a different number of spaces-per-a-tab than your text editor. If one configures one's editor to expand tabs to spaces this won't happen.


> If one configures one's editor to expand tabs to spaces this won't happen.

…or you could use tabs for indentation, spaces for alignment, as they are intended to be used ;)


> …or you could use tabs for indentation, spaces for alignment, as they are intended to be used ;)

Yes. But, that is easier to stuff up. Getting rid of tabs completely, it disappoints some people who want to change the indentation amount to fit their personal preferences, but it reduces the likelihood of messes being made.


> it disappoints some people who want to change the indentation amount to fit their personal preferences

That's one issue I have with spaces, along with the fact that they are more annoying to delete. And I've seen people indent by 4n+1 spaces by accident at times (usually when there are no surrounding lines to provide context), so I wouldn't be so sure about it being the end-all, be-all for fixing indentation mistakes.


> along with the fact that they are more annoying to delete.

FWIW my editor (vscode) seems to be deleting 4 tabs at a time on when my caret is at the start of a code line.

(That said what I usually do is shift up or down to select some text on all lines I intend to move and then use tab or shift-tab to fix indetation.)


> deleting 4 tabs at a time

I assume you meant 4 spaces.


That is correct!


Or use tabs for indentation, spaces to separate words, and don't align.


That’s fine as well :) I guess you can call it a degenerate case of my more general guidelines. (FWIW, I don’t align usually; I just run a formatter over my code and make sure the indentation is right.)


Tabs are intended to be used for alignment. "Tab" is a clipping of "tabulator", as in "thing that tabulates" or "thing for tabulating", where "tabulate" means "to arrange in a tabular manner, to format as a table". But rather than risk etymological fallacy, I'll explain the history of the tab key to illuminate that it was certainly intended for alignment.

The tab key on typewriters caused the carriage to advance to the next tab stop. The tab stops were physical barriers that would stop the carriage from moving at a specific position. In many cases they were adjustable, but the specifics of how varied from model to model. Usually it would be pins, clips, sliders, vel sim. attached to a bar near the carriage. The tab key would raise the carriage and fling it across until it hit a tab stop and... stopped.

This mechanism can't have been invented terribly long after typewriters started to be sold commercially in 1868, because by 1900 Underwood was already advertising tabulating as "part of the machine, not an attachment"[1]. The Underwood No. 5 was immensely popular and became the template for what we think of today as a typewriter; earlier models were subject to much variation, and in many cases the typist couldn't even see what she was typing, because the typeheads would strike from behind the paper! Of course, nobody had to copy every feature of the Underwood machine, so the tabulator must've been somewhat popular. I imagine it was rather handy in businesses or any institution that kept typed records.

It's true that many cheaper machines only had support for a single tab stop, and that it was oftentimes used for paragraph indentation, but this is a limitation of low-cost machines rather than an intention, I think, and even a single tab stop can be used for tabulation—so long as you only need to make tables of two columns ;)

The tab's entry into computing is somewhat accidental, due to the usage of teletypewriters as terminals in the early years, and thus both the adoption of teleprinter codes such as ASCII for information encoding and the adaptation of the keyboards of such terminals for later HIDs. When the CRT terminal emulator ("glass TTY") was introduced, its tab stop functionality would often emulate that of a typewriter—in many cases even going as far as being adjustable (see e.g. [2]).

Despite the accident, there were some benefits to keeping tabs around, especially in the early days. Kernighan & Plaugher's «Software Tools in Pascal» presents them in §2.1 where it introduces a filter called "entab":

… you could convert your files to a standard representation, one that has no wasteful imbedded blank strings. As an added payoff, your files are smaller and they all look alike; that makes it easier to write programs that talk and work together.Another use for `entab` is to prepare output to be sent to a terminal. You might have a program that expects to drive a smart printer. You would like to speed up printing by tabbing whenever possible. Rather than rewrite a working program, you are better off with a separate program to filter the output before it is typed. Thus `entab`.

And although it's common these days for software to give tabs a simplistic treatment by always expanding them to a constant number of blanks, Kernighan & Plaugher's "detab" tool in §1.5 demonstrates that this is not how tabs are "supposed" to work: when you have a fixed-width typeface, are to be expanded to a variable number of blanks, depending on the distance between the current cursor column and the next tab stop. If tab stops are set to 8, then it's roughly equivalent to 8 blanks in the first column, but 7 blanks in the second column, 6 in the third, and so on, because the tab key isn't "supposed" to mean "k blanks", but rather "skip to column k". And that certainly sounds like alignment to me! (For the curious, I've translated K&P's `detab` tool to Lua (and made it a bit more flexible); you can find it at [3]).

Unfortunately, the utility of tabs for alignment is countered by their lack of portability. Since every terminal (and later every text editor/word processor) had its own notion of tab stops, and since they were often configurable (and therefore many users would change them to suit their own tastes), tabs couldn't really be relied upon for conveying pretty files. And as technology has advanced, their utility as an optimization or convenience has diminished significantly. So the only utility they're left with is as a configurable signal of indentation. For programmers especially, this is no small utility, perhaps, but it wasn't how they were intended to be used ;)

——

[1]: https://www.antiquetypewriters.com/typewriter/underwood-1-ty...

[2]: http://man.openbsd.org/POSIX-2013/tabs

[3]: http://ix.io/1Cnh.lua (whereto I hereby disclaim any warranty, and likewise disclaim all copyright—insofar as I believe it my right to do so, I make it communis juris, in solemn hope that if it be any use whatsoever that it be a benefit to all; and I am not proud, for yet this is but a humble offering, not likely to be of much use to any; but considering my own shortcomings, not least among them is a lack of foresight, so be it far from me to prophesy what benefit may come of the thoughts or actions of others who have been free to think and to act; and considering also that history has shown what great achievements whereof mankind is capable when each one is allowed to nourish and complement each other: I say let none languish in bondage, but grow to magnificence in freedom, for the good of each other and of our whole humanity; wherefore I would encourage others do likewise, even with so small a thing as this, however I do not demand it)


I wouldn't use tabs to align your comments; I use them exclusively for indentation and rely on spaces for alignment. This makes them work both with editors that do simplistic "replace tabs with spaces" and with editors that have tab stops.


i agree with this, but find the complexity of writing assembly with modern processors instruction sets requires quite specialized knowledge.


I had fun recently generating Intel assembly for mathematical expressions:

https://github.com/skx/math-compiler/

Mostly the project was to write something that compiled, from start to finish, but it was a nice refresher on assembly which I've otherwise not touched seriously for 20+ years.


It is, but someone needs to write compiler backends.


It is quite scary to think that less and less people know how to write good assembly. So in a few years (decades?) we will have to rely on backends, with almost no one knowing how they really work, or how to write another one.


Luckily it seems working on language design and compiler stuff is stuff is considered cool, almost as cool as game programming so I'm not too worried yet.


I am not so negative, thankfully any good CS degree has enough compiler design lectures and assignments.

And using sites like Godbolt is becoming trendy.


That's true, but not difficult as many people may think. In most cases you only need to remember most-used ~20 instructions and leave the remaining to reference. Sure it requires other domain knowledge, but it has almost nothing to do with asm itself.


Hello Nineties. Are you home? I miss you.

I don't believe I've really thought or heard of Nasm for the last two decades, but boy is it time for me to dig it out again and get assembling. For absolutely nothing but the sheer fun of it and for reconnecting with my hardware.

Thanks for posting.


Does anyone know the best way to run assembly code on Windows?

As usual, I seem to recall this is one of the many things that is easy in Linux and almost impossible on Windows.


Well, since we're talking about NASM, go to https://www.nasm.us/ and download the latest stable build for Windows.


Does that use MINGW though and require you to build all that junk on Windows?


nasm is a single .exe


There are a lot of assemblers, but I've used MASM. It ships with visual studio. I think you can find the actual binary by searching for ml.exe or ml64.exe. Then you just write some MASM code and assemble it. It's less well documented but entirely possible.


Thank you! I'll check!


It is quite easy, specially since home computer Assemblers were historically more powerful than UNIX ones, with very expressive macros.

Here is the relevant information for MASM.

https://docs.microsoft.com/en-us/cpp/assembler/masm/microsof...

And some game development references of yore

http://win32assembly.programminghorizon.com/tutorials.html


Wow, NASM is really a blast from the past for me. 80386 assembly was my second "language" that I learned, after various forms of BASIC (on TRS-80 and QuickBASIC). In the mid-90's I was a teenager, and would write most of my code in QuickBASIC, and make optimized code in NASM. QuickBASIC was a compiled BASIC, but still pretty slow on a 386, so about half of my code base ended up being assembly.

At one point, I made my own pseudo-language, which was actually just a few dozen commands that would be translated into NASM, to make programming in assembly much easier to deal with. I ran out of room on my 40mb hard drive, and also ran out of backup floppies that worked (I would 3x backup my important stuff, because the mid-90's was a terrible time for reliable magnetic media on a budget), so I would periodically delete source code that I had spent weeks programming. The interpreter was one of those casualties, which, thinking back, was a really dumb move (I was 15 or so, cut me some slack!), because I still kept a lot of programs that needed that interpreter to compile. I have those codebases to this day, and can run the executable on my retro DOS machines, view the code, but no compilation :-(

I can't remember what my old assembler was, but I do remember NASM was a dream compared to whatever other assembler I was running at the time. I'm happy to see that it is still kicking.

In case anyone is wondering why I would be running a 386 in the mid 90's with a 40mb hdd (and 1mb RAM!), it's just because my parents had the time had no money, and to them a computer was a computer - they couldn't see the advantage of 1mb vs 16mb of RAM, people in general were much less computer savvy. It wasn't until my 30's that my mother realized that my time programming computers as a teenager was actually something productive!


On my CS degree compiler assignment, I got to learn a neat trick from our teacher that I still use when advising someone trying to write a compiler.

Basically, our IL was just a bunch of NASM macros.

So yeah not good at all for doing register assignments or writing any kind of performant code, but it was a binary generated by our toolchain anyway, and it felt good.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: