Monthly Archives: March 2011

I never really learned to use NASM to its full potential, and now – in SOEN228, Concordia’s System Hardware class which I’m currently tutoring – I’m supposed to be teaching students how to use it.

To that end, I’ve written up a little refresher for me to consult.

Please note that – in order to discourage plagiarizers – all quotation marks – both "double quotes" and ‘single quotes’ – in this article (and all pages on my web site) are not normal quotation marks. If you are copy-pasting code it won’t compile or run properly.

The Plan: A "Hello World!" written in the NASM Assembly Language

What I’m going to do is to write a Hello World program, one step at a time… very slowly. Changes will be made one at a time, resulting in several iterations of the Hello World program. Some of them will run and compile without problem; some of them will fail miserably. Eventually, it will evolve to prompt the user for input ("What is your name?") so as to output personalized Hello messages such as "Hello Richard".

Before I get into it, if you are a student of SOEN228, you will also want to read the tutorials I wrote on ViM and SSH for SOEN229 – both tools you will need to understand before moving on to the next semester of the Software Engineering program, and you should be using them during these SOEN228 labs. Once you’re familiar with ViM and SSH, connect to one of Concordia’s public access servers and create a HelloWorld.asm file like so: (note that the [prompt] > is the prompt; don’t type that part out)

[prompt] > vim HelloWorld.asm

The Program – Iteration 1

Before I write the program, I need to reflect on what that program is doing. If I were programming at a higher level of abstraction (such as in Java or in C) I could probably summarize the program as simply "outputting the String ‘Hello World!’" but – when writing in Assembly language – this is an oversimplification which won’t work. That description of the Hello World program neglects that the String "Hello World!" (really not a string but simply information) must be declared and stored somewhere in memory.

So, again, in summary the program must at least do the following: (this list will grow)

Declare/store the information "Hello World!" (data)

Output that information "Hello World!" (behavior)

Declare/store the information "Hello World!" (data)

In NASM Assembly language, a Data Segment is used to declare data like this. Use db (which stands for "declare byte"; ignore the "byte" part and just think about the word "declare" for now…)

segment .data
helloMsg db 'Hello World!'
; more to come…

Output that information "Hello World!" (behavior)

The behavior of my program consists of instructions and I’m going to put code executing instructions in the Text Segment of my program.

Text Segment

The Text Segment must include a label_start – think of it as the NASM equivalent of main(…) in Java. That label (_start) must be declared as global… just because.

Executing Instructions

I’m now ready to actually do something with my program. What I need to do is output the information at helloMsg… but how do I do that?

Sadly, there is no instruction for output in NASM assembly language programming; I’m going to have to use a System Call. Invoking a system call is done by invoking an interrupt with the int instruction:

If you’re a SOEN228 student, take note that whenever you invoke a system call you will use int 0 × 80; within the scope of this course, all interrupts will always be code >int 0 × 80 interrupts – you don't need to think about the other interrupts in SOEN228.

But there are a lot of different system calls; exit, read and write are all system calls… and many more. How does the system know whether my program is trying to invoke read or write, or even exit?

Each system call is (arbitrarily) numbered, and when the int 0 × 80 interrupt is invoked (interrupting the execution of the program and transferring control to the operating system kernel so as to execute the system call) the operating system looks at the value in the eax register to identify which system call should be executed. The System Call Table I linked to above lists the numeric value for each system call in a column labeled "%eax".

It's important to note that helloMsg is not the string 'Hello World!' but rather the string's address in memory.

To emphasize this, consider the size of the ecx register versus the size of 'Hello World!'. 'Hello World!' is 12 characters long; each character in ASCII is 1 byte. Therefore 'Hello World!' would be 12 bytes long, while ecx is only 4 bytes long. As such, the information 'Hello World!' can't be moved into ecx; it's just not possible.

Which brings me to the last piece of missing information before I invoke the system call with the interrupt 0 × 80: ecx holds the address of the beginning of the information, but since helloMsg is simply an address it has no implicit length. This isn't Java; 'Hello World!' isn't a String object with a handy-dandy length property. Since helloMsg is merely an address, I need to specify how many bytes I'm writing to screen, using edx:

For reference purposes, nasm is an assembler and ld is a linker – but that information is technically out of scope for SOEN228.

Now, to run my program I type the following on the command line:

[prompt] > ./HelloWorld

... and I get the following output:

HelloWorld!Segmentation fault

My First Segmentation Fault

A Segmentation Fault is a memory access violation… but it doesn't look like there should be a segmentation fault in my program – it's a simple Hello World, isn't it?

Well, I forgot something very important. In order to understand this, I have to think about some computer architecture for a moment: specifically, I'm thinking about the Program Counter, the MAR and the MDR – some major players in the Instruction Cycle.

Simply put, to execute each instruction the value in the Program Counter register is moved to the MAR, then the information (in memory) at that address is read into the MDR, and that information is executed as an instruction. Meanwhile, the Program Counter increments by one so as to point to the next instruction.

So consider what happens when the program execution reaches that last line (int 0 × 80): the value in the Program Counter is moved into the MAR and the data at that address is memory is read into memory so it can be executed as an instruction… but there is no next instruction. Therefore the next position in memory isn't the next instruction but some memory which doesn't belong to my program; hence, a segmentation fault.

This brings me to Important NASM Lesson #1.

Important Lesson #1: Always Make A System Call to sys_exit

A NASM program needs to explicitly exit; I can't just let execution end like I would in higher abstraction languages. So really, what I need the program to do (continuation of the list from above) is:

Declare/store the information "Hello World!" (data)

Output that information "Hello World!" (behavior)

Exit

At the end of a NASM program I will always have to make a system call to sys_exit, which is system call 1. So I need to add an interrupt invoking system call 1 to the end of my text segment:

Compiling and Running the Program

But there's something that bothers me: the next prompt is on the same line as my output:

[prompt] > ./HelloWorld
Hello World![prompt] >

...which is ugly. So, my next iteration of the Hello World program will be just like this one, but will include that new line between the end of the output and the next prompt.

The Program – Iteration 2

How can I add a new line to the end of my output? I'm going to consider some (wrong) choices:

Can I Just Put a New Line in my Data Segment?

What if I change my data segment – adding a new line in the "Hello World!" data, so it spans two lines?

helloMsg db 'Hello World!
' ; this won't work!

This won't work, and why seems kind of apparent to me when I consider the difference between semi-colons in other languages and in NASM. In NASM semicolons are used to create line comments, but in other languages it is used as a statement terminator. In NASM, instead, the new line character is used as a statement terminator.

As such if I use the above code and try to assemble with nasm on the command line, I get an error:

Can I Use an Escape Character like \n?

In Java, a higher-abstraction language than NASM, I could use an esacpe character\n to include a new line in a string, but this is not the case in NASM:

helloMsg db "Hello World!\n" ; this won't work!

This is not right. To my knowledge, there are no such escape characters in NASM. Using the above I could end up with an application which outputs the following:

[prompt] > ./HelloWorld
Hello World!\n[prompt] >

No improvement.

Can I Use an ASCII code?

Using an escape character was in the right ballpark, but the correct solution is to use an ASCII code. I can't put the ASCII code in quotes though. Instead I have to list it as a hex-encoded byte (character) after I declare my helloMsg:

helloMsg db "Hello World!", 0xA ; 0xA is the ASCII code for new-line

Now that I've added the ASCII-code for a new line charcater to my helloMsg, what will happen if I compile and run again? My program still doesn't work!

I'm also going to declare data in my Data Segment for the user's name. This is 100% wrong and I'll get to that soon, but for now I'm experimenting with the Data Segment for the sake of demonstration. It is of utmost importance that the name is placed between helloMsg and endOfLine.

Since the user's name has no value to begin with (one could call it uninitialized) I'm initializing it with a value of 8 spaces:

segment .data
; Declare/store the information "Hello World!"
prompt db 'What is your name? '
; do not change the order of the following three lines!
helloMsg db 'Hello '
name db ' ' ; 8 space characters
endOfLine db '!',0xA
; do not change the order of the previous three lines!
segment .text
; omitted…

Prompt the user for their name (behavior)

Since I'm into the behavior of my program, I'm no longer working in segment .data but rather in segment .text.

When you boil down to it, prompting is really just output – so that means a system call to sys_write. Where there's a system call, there's an interrupt:

The eax register is used to distinguish between output and input system calls. I have to set its value (using a mov instruction) to the numerical value arbitrarily assigned to the sys_read (input) system call. Checking a Linux System Call Table I can see that the numeric value expected in eax for sys_read is 3.

Display Hello {name}! (behavior)

I need to change my output from before (previously "Hello World!",0xA) to now output "Hello" then name then "!",0xA, but I'm going to use a little trick to do it: instead of having 3 different outputs (an system calls) I'm going to have one:

Observations About Iteration 3

There are some ideas and points which stand out about Iteration 3 for me.

Important Lesson #2: The Data Segment Is Continuous

The important lesson I've picked up from Iteration 3 is that the data segment is continuous; since I declared helloMsg, name and endOfLine one after another, they are adjacent to each other in memory, which allows me to output them all with a single sys_write which outputs 16 bytes beginning at the address helloMsg:

; Output that information "Hello…"
; since the data segment is continuous
; and helloMsg, name and endOfLine are one after another
; I can just output all 16 bytes with one sys_write
mov eax, 4 ; write…
mov ebx, 1 ; to the standard output (screen/console)…
mov ecx, helloMsg ; the information at helloMsg…
mov edx, 16 ; 16 bytes (characters) of that information…
; (but isn't helloMsg only 6 bytes?)
int 0 × 80

This is just further evidence that the values declared in the data segment using db are not really variables nor objects nor Strings: they are simply positions in a segment of memory which have been given names. There is no concrete distinction between the 3 strings of information declared in the data segment of my program.

Calculating the length of information using equ and $

Since the data segment is continuous, I should be able to automatically determine the length of the information I output. For example, consider prompt:

Since helloMsg is the memory address at the end of the information 'What is your name? ' I should be able to calculate the length of 'What is your name? ' automatically by subtracting prompt from helloMsg. (end – beginning = length)

This can be done with equ and the $ token. In the data segment equ can be used to give a symbol a constant value, instead of making it an address, while the $ token is treated as assembly position of the current line.

So in the above code I can replace the hardcoded value 19 with a new symbol in my data segment, promptLength:

Now, if I have to change the prompt from 'What is your name? ' to 'Please input your full name? ' I don't have to worry about updating (or forgetting to update) the length of the output for the sys_write – the assembler will re-calulate the value of promptLength for me.

Important Lesson #3: Using the BSS section

Earler I said that I was putting name in the data segment and this was wrong; this is because name is uninitialized data, and only initialized data goes in the data segment. Uninitialized data belongs in the BSS segment.

Edit: Why does the uninitialized data go in .bss? It is to optimize the size of the final executable. Imagine if, instead of being 8 characters long, the name was 8 megabytes long instead. Now those 8 megabytes of empty spaces in the .data segment have to be compiled and stored in the executable file, making the executable file 8 megabytes larger than it has to be. The .bss section lets me simply declare "my program needs 8 megabytes of memory" without actually increasing the size of my executable file by 8 megabytes.

So I need to make some changes to my program so as to respect that rule: I need to remove name from segment .data, and while I'm at it I might as well make use of the above trick to calculate the length of information in memory:

I also need to add a segment .bss. In segment .bss – since unintialized data goes here – I'm not declaring information (like I was in segment .data) but rather just reserving memory. Hence, in segment .bss I won't be using db but rather resb – which stands for "reserve byte":

segment .bss
name: resb 8

And lastly, I have to change the call to sys_write which outputs helloMsg. (since the name is no longer in the data segment the information is no longer continuous in memory)

Important Lesson #4: That New Line Character…

The last important thing I'm going to take away from Iteration 3 is that there is a new line character in the output, between my name and the exclamation point '!' – which shouldn't be there:

What is your name? Richard
Hello Richard
!

In order to understand where this new line is coming from, I have to think really hard about what the user types in when prompted, because while my name is 7 characters long, the input the user provides is not. I have to remember that to input my name, the user has to type in 'R'-'i'-'c'-'h'-'a'-'r'-'d'-ENTER. That enter is a new line character, and it is included with the input provided by the user. For my Hello World program to work properly, I have to remove the new line character, and everything after it; this will be Iteration 4.

The Program – Iteration 4

In this final iteration I am going to write some code which will remove the new line character from the user input. In order to do this I need to:

Declare/store the information "What is your name? " (data)

Declare/store the information "Hello " (data)

Declare/store the information "!",0xA (data)

Prompt the user for their name (behavior)

Accept input and store the user's name (behavior? data?)

Display Hello {name}!, or: (more specifically)

Display "Hello " (behavior)

Loop over the the user's name outputting every character until a new line (behavior)

Display "!",0xA (behavior)

Exit (behavior)

It should be noted that while my program will loop logically, I will not be using the LOOP keyword.

I've dramatically oversimplified looping over the characters in the user's name though. As en example, if I think about a for loop in a higher-abstraction language like Java, I realize that a for loop is actually composed of several smaller instructions:

for(int i=n; i<n+8; i++)

I have the initializer, the loop-test (condition) and the counting expression. Also, I have a variable i which is being initialized, compared against the conditional and changed with each loop. I am going to call this value the "index".

So really, a loop can be no less complex than:

Initialize the index

(Do something in the loop)

Change the value of the index

Perform the loop test; if a success, loop again

So my program now has to:

Declare/store the information "What is your name? " (data)

Declare/store the information "Hello " (data)

Declare/store the information "!",0xA (data)

Prompt the user for their name (behavior)

Accept input and store the user's name (behavior? data?)

Display Hello {name}!, or: (more specifically)

Display "Hello " (behavior)

Loop over the the user's name outputting every character until a new line, or: (behavior)

Initialize an index

Check if the current character is a new line

If it is, exit the loop

If it is not, output the character

Change the value of the index

Perform the loop test; if a success, loop again.

Display "!",0xA (behavior)

Exit (behavior)

Up until the loop, my program's behavior is unaffected, so I am going to skip over everything before it.

Initialize an index

There are special registers which are conventionally used as indexes. They are called index registers and the ones available for me to use when I'm writing an assembly language program are esi – the source index registry – and edi – the destination index registry. The source index registry (esi) is conventionally used when reading from memory, and since I'm reading from memory and writing to the standard output this is the index I will use as my index. (realistically I could use any registry I want, but this is the conventional one to use)

I have to initialize it to the starting position, which is at name:

mov esi, name ; initialize the source index

Check if the current character is a new line

In order to check if the current character is a new line, I need to perform a comparison using cmp. I'm trying to compare the character which is in-memory at the address currently stored in register esi. Therefore, I'm going to be using Register Indirect Addressing.

At this point, I'm tempted to try this:

cmp [esi], 0xA ; this won't work

... but this won't work. There's nothing to indicate the size of the information being compared. Should 1 byte of memory be compared to 0xA? 2 bytes? 3 bytes?

In order to specify the size of the comparison, I have to include a register as one of the operands in my cmp instruction:

My comparison should have a consequence, however; if the comparison finds that the two values are equal, my program should exit the loop. I can accomplish this by means of a "jump if equal" instruction – je:

Here I'm comparing esi to name+8 to see if esi is pointing past the last byte reserved for name. I jump if esi is less than name+8 (using jl – 'jump less than') to a labal loopAgain… except there is no such label. I have to add it after I initialized esi:

In 1974, Lewis Thomas wrote an essay titled "The Technology of Medicine".

The entire essay is extremely interesting, and – while I know little of the technology of medicine nor of its delivery and advancement – it has fascinating parallels with web technologies. These parallels are present as early as the second paragraph:

Somehow medicine, for the $80-odd billion that it is said to cost the nation, has not yet come in for much of this analytical treatment [i.e. technology assessment]. It seems taken for granted that the technology of medicine simply exists, take it or leave it, and the only major technologic problem which policy-makers are interested in is how to deliver today’s kind of health care, with equity, to all the people.

With providers competing to connect more and more – from residents to offices to cafés, with civvies making a ruckus over net neutrality and with Canada’s Radio-television and Telecommunications Commission pushing usage-based billing, it really does seem to me like the only major technologic problem which policy-makers are interested in is how to deliver today’s Web. The focus seems – quite literally – on matters of quantity and not really of quality.

The Technology of Medicine

Thomas wrote his essay in anticipation of analysts and policy makers making decisions about budgets and funding for medicine, to distinguish between 3 levels of technology:

nontechnology

halfway technology

genuinely decisive technology

… each level technology was built upon a deeper understanding of biology than the one before it. As a result, each level is both more effective than the one before it and less expensive – significantly less expensive.

As an example, Thomas considers the treatment of Typhoid Fever. A thousand years ago, it would have been treated with non-technologies; a healer would attend to the patient – who would be isolated and bed-ridden or "hospitalized" in some way – and minimize their discomfort in the hopes that they would recover. A century ago, advances in technology would allow a physician to treat a patient who would be hospitalized for 50 days, in need of demanding nurse care, (a nontechnology) laboratory monitoring (a halfway technology) and occasional surgery (also a halfway technology) – at the very least. Today, however, biological science has advanced to the point where a $5 vaccination can combat the disease (a genuinely decisive technology) and no health professionals need tend to the patient as they simply take the day off work.

In the essay, Thomas goes to great lengths to emphasize the difference between halfway technology with genuine decisive technology; he expresses concern that policy makes would take genuinely decisive technology for granted…

The third type of technology [i.e. genuinely decisive technology] is the kind that is so effective that it seems to attract the least public notice; it has come to be taken for granted.

… while emphasizing the shortcomings of halfway technologies:

In fact, this level of technology [i.e. halfway technology] is, by its nature, at the same time highly sophisticated and profoundly primitive. It is the kind of thing that one must continue to do until there is a genuine understanding of the mechanisms involved in disease.

The Technology of the Web

I think web technologies can similarly be divided into these 3 levels, and the same predicament – of halfway technologies being glorified and genuinely decisive technology being taken for granted – exists. The inexpensive, long-standing technologies which have defined the web for decades and were created by people with a genuine understanding of the mechanisms involved in web development – technologies like HTTP, HTML, CSS – are all too often taken for granted in favor of less cost effective halfway technologies like Applets, Silverlight, ActiveX or sometimes Flash.

It’s important to note, though, that the great success stories of the web are often very observably genuinely decisive technologies:

Google was built upon a fundamental understanding of the nature of hypertext and its importance to the Web. While it wasn’t cheap to build Google, compared to Yahoo! Directory – which paid a team of editors who were sifting through search results (an expensive nontechnology) – and AltaVista – which simply searched and indexed the content of web pages without considering their place in the web (a costly but in the end ineffective halfway technology) – I think Google can be thought of as the less expensive technology.

jQuery was created with an understanding of the value and power of both CSS and JavaScript; its original developers leveraged CSS selectors while ackowledging that JavaScript code is important and ubiquitous enough to merit the same kind of professionalism server-side code gets. jQuery is of course free and easy to use, reducing development time and thus development costs.

I always like to talk about how Facebook overtook MySpace because it understood how the Web is an information medium and not a visual one; it didn’t allow users to change the layout of their profile pages.

Disabled Technology

Altogether, what got me thinking about these parallels between Thomas’ article and Web technologies was a quote from Dr. Hugh Herr:

There are no disabled people in the world, only disabled technology [because of] poor design.

Currently there’s a big ruckus in Canada about making federal web sites accessible – in particular to the blind. I believe this is a struggle between people who take genuinely decisive technology for granted (who focus on how highly sophisticated halfway technologies are) and those who have a genuine understanding of the mechanisms involved in the Web. Any genuinely decisive web technology will inevitably be accessible, and the reality is that the costs of genuinely decisive technology is always lower. Among other things, they usually don’t result in the kind of 5 year legal battle the current halfway technologies are resulting in.