January 2004 Archives

Fresse...

|

Wenn man keine Ahnung hat, einfach mal die Fresse halten - Dieter Nuhr.

If you don't have a clue, just shut up.

Das Wort zum Wochenende - Dem ist nichts hinzuzufügen.

The format of string resources

|

Nomad's land

|

Check out Nomad's land, a blog run by a professional photographer.

Robert Scoble on great uses of Avalon in Longhorn

|
In a response to Will Avalon be Ready?, Robert Scoble writes:
...That said, you will see some really great uses of Avalon in Longhorn. The clock that we shipped at the PDC is built in Avalon, for instance. There will be plenty of examples to prove to you that it's ready for serious app development.

Well, clock samples are no sign that Avalon is ready for serious app development. Neither are NotePad clones etc. Avalon will be ready for serious app development if a major app like Outlook can be written with out-of-the-box controls & widgets supplied by the UI infrastructure of Longhorn.

Out-of-the-box? Yes. Because, for the sake of consistency, lots third-party developers will try to mimic the UI of Microsoft apps. And it's neither in their nor in Microsofts best interest to re-invent the wheel.

.Net Overview

|

Official .NET overview.

Der aktuelle Soft-Drink Test

|

Fanta Berry Blue

Farbe: 10/10 Punkten. Ein grauenvolles, chemisch reines Blau.
Geschmack: 3/10 Punkten. Leichter Duft nach Hustensaft, dann der typische Beeren-Aromastoff, säuerlich prickelnder Abgang.

Fazit: Muß man nicht haben.

A simple proposal

|
A simple proposal by Alan Green (via Smalltalk with Rants):

Henceforth, any developer that uses the word "just" while describing or estimating the implementation of a new feature to a manager will be assigned the design, coding and testing tasks for that feature.

Uhm, oops. Gotta watch my language. Excellent post. Nice comments, there, too.

Generics in C#, Java, and C++

|

Anders Hejlsberg, the lead C# architect, talks with Bruce Eckel and Bill Venners about C# and Java generics, C++ templates, constraints, and the weak-strong typing dial. via [Artima.com Articles]

Folklore.org

|

Cite: Anecdotes about the development of Apple's original Macintosh computer, and the people who created it.

Apple exec: iTunes Europe launch runs into hurdles

|

Interesting article on Apple's problems launching its iTunes Music Store in Europe. [via MacCentral]

Smack the Penguin

|

Der Wahnsinn.

eXtreme ÖPNVing - Teil 3

|

Karlsruhe - Rheinzabern

Vom Büro aus mit der Linie 4 zum Hauptbahnhof. Fahrkarte kann man nicht mehr beim Fahrer kaufen, muttu Apparat in der Straßenbahn bedienen. Viele Leute. Man ist nicht alleine.

RegionalExpress nach Wörth - Abfahrt Gleis 101 - Bereits die Gleisnummer läßt ahnen, daß hier die Unterpriveligierten in die Pfalz fahren. Aber gut besucht der Zug. Neu. Würdig. Voll. Die Studentinnen neben mir referieren ohne Pause über Themen wie die WG, Papa's 60. Geburtstag und daß sie nicht wissen, was sie mit ihrem Medienpädagogik-Studium anfangen sollen.

Umsteigen in die Regionalbahn nach Rheinzabern. Nicht ganz so sozial. Graffiti. Schwamm drüber. Kein WiFi. Warum eigentlich nicht?

Nun vom Bahnhof quer durch den Ort laufen. Das tut Dir gut, mein Junge.

10 Things to Improve Writing

|

iTunes Music Store RSS Generator

|

Me no talk English good?

|

Got to apologize.

The person's name is Aaron Brethorst, of course.

Anyway, I was really excited about the phrase "Relative Levels of Suckage". No criticism whatsoever. Quite the contrary. Encouragement. Let's see more innovative uses of the English language.

Plus, gotta fix my Trackback. Looks like it's pointing to my password-protected site.

Relative Levels of Suckage

|

Bret once again demonstrates superior command of the English language: Relative Levels of Suckage.

Supercomputer Video

|

Video on Virginia Tech building a 10+ teraflops supercomputer from 1000+ Mac G5's in three weeks: http://www.apple.com/hardware/video/virginiatech/ via [MemoRanda]

Immutable Objects

|

Keith Ray on Immutable Objects.

Speeding C++ links

|

Beobachtung am Rande...

|

...und Bestätigung meiner Theorie.

Auf der Suche nach einer Toilette stolpere ich durch das spärlich besetzte Großraumabteil des IC und bemerke einen iBook. Der Besitzer trägt einen schwarzen Rollkragenpulli und eine perverse Brille.

Bahnhof Koblenz

|

Wird gerade umgebaut, Toiletten sind bereits ab 19:00 geschlossen. Nieselregen. Es ist kalt und zieht wie Hechtsuppe.

The Simplest Thing That Could Possibly Work

|

Ward Cunningham talks with Bill Venners about complexity that empowers versus complexity that creates difficulty, simplicity as the shortest path to a solution, and coding the simplest thing when you're stuck. [Artima.com Articles]

Writing style and blogging

|

Joi Ito on Writing Style....

Poor writing style, like bad manners, makes someone appear less intelligent than they are. Writing style, like manners, can be learned in many ways. Reading and writing a lot is the first step. Having people critique your writing is probably the next best thing. There are many basic writing mistakes that people make, which can easily be avoided by being aware of them.

I have never been a great writer and I am self-concious about my writing style. If you are serious about your blogging, I think that time spent polishing your writing style is well worth the investment.

My favorite reference is the Chicago Manual of Style.

Some web pages:

Special thanks to my editors on #joiito.

[Joi Ito's Web]

Interesting Website on Test-Driven-Development

|

Weather : "Highs around 9."...

|

Wetterbericht per RSS auch für Deutschland bis auf Stadtebene [Scripting News]

Laws of Explanation

|

Tim Bray: When you’re explaining something to somebody and they don’t get it, that’s not their problem, it’s your problem; When someone’s explaining something to you and you’re not getting it, it’s not your problem, it’s their problem [ via Sam Ruby]

Hmm. I disagree:

When you’re explaining something to somebody and they don’t get it, that’s not their problem, it’s your problem; When someone’s explaining something to you and you’re not getting it, that's not their problem, it's your problem. You're not asking the right questions.

The history of calling conventions, part 5: amd64

|

The last architecture I'm going to cover in this series is the AMD64 architecture (also known as x86-64).

The AMD64 takes the traditional x86 and expands the registers to 64 bits, naming them rax, rbx, etc. It also adds eight more general purpose registers, named simply R8 through R15.

  • The first four parameters to a function are passed in rcx, edx, r8 and r9. Any further parameters are pushed on the stack. Furthermore, space for the register parameters is reserved on the stack, in case the called function wants to spill them; this is important if the function is variadic.

  • Parameters that are smaller than 64 bits are not zero-extended; the upper bits are garbage, so remember to zero them explicitly if you need to. Parameters that are larger than 64 bits are passed by address.

  • The return value is placed in rax. If the return value is larger than 64 bits, then a secret first parameter is passed which contains the address where the return value should be stored.

  • All registers must be preserved across the call, except for rax, ecx, edx, r8, r9, r10, and r11, which are scratch.

  • The callee does not clean the stack. It is the caller's job to clean the stack.

  • The stack must be kept 16-byte aligned. Since the "call" instruction pushes an 8-byte return address, this means that every non-leaf function is going to adjust the stack by a value of the form 16n+8 in order to restore 16-byte alignment.

Here's a sample:

void SomeFunction(int a, int b, int c, int d, int e);
void CallThatFunction()
{
    SomeFunction(1, 2, 3, 4, 5);
    SomeFunction(6, 7, 8, 9, 10);
}

On entry to CallThatFunction, the stack looks like this:

xxxxxxx0.. rest of stack ..
xxxxxxx8return address<- RSP

Due to the presence of the return address, the stack is misaligned. CallThatFunction sets up its stack frame, which might go like this:

    sub    rsp, 0x28

Notice that the local stack frame size is 16n+8, so that the result is a realigned stack.

xxxxxxx0.. rest of stack ..
xxxxxxx8return address
xxxxxxx0 (arg5)
xxxxxxx8 (arg4 spill)
xxxxxxx0 (arg3 spill)
xxxxxxx8 (arg2 spill)
xxxxxxx0 (arg1 spill) <- RSP

Now we can set up for the first call:

        mov     dword ptr [rsp+0x20], 5     ; output parameter 5
        mov     r9d, 4                      ; output parameter 4
        mov     r8d, 3                      ; output parameter 3
        mov     edx, 2                      ; output parameter 2
        mov     ecx, 1                      ; output parameter 1
        call    SomeFunction                ; Go Speed Racer!

When SomeFunction returns, the stack is not cleaned, so it still looks like it did above. To issue the second call, then, we just shove the new values into the space we already reserved:

        mov     dword ptr [rsp+0x20], 10    ; output parameter 5
        mov     r9d, 9                      ; output parameter 4
        mov     r8d, 8                      ; output parameter 3
        mov     edx, 7                      ; output parameter 2
        mov     ecx, 6                      ; output parameter 1
        call    SomeFunction                ; Go Speed Racer!

CallThatFunction is now finished and can clean its stack and return.
        add     rsp, 0x28
        ret

Notice that you see very few "push" instructions in amd64 code, since the paradigm is for the caller to reserve parameter space and keep re-using it. [The Old New Thing]

Shooting yourself in the foot..

|

Not new, but always a good read. I like the updates on languages like PHP and Forth :-)

Shooting Yourself in the Foot, in 100 different [computer] languages [via Critical Section]

I haven't seen any substantial advances in Longhorn making the computer easier to use for the average user. Just keep in mind that 90% of the users out there aren't able to tell Windows XP from MacOS X. They aren't able to carry out simple tasks like copying a document. The concept of the Explorer or folders & documents escapes them. They aren't able to process all the information presented by today's UIs.

Show me fundamental advances in human-computer interaction for the average user.

Death of the Application

|

Joe Hewitt would like to see the death of the application in Longhorn.

We have been involved with the OpenDoc effort back in the mid-1990s. Moving to a component-oriented architecture is an incredibly complex problem to tackle. Both from a technical (plumbing, component-interaction, UI) and business (support, business-model) perspective. It would require fundamental changes in the way platform vendors and application developers do business.

While I agree with Joe that this would be a bold move on behalf of Microsoft, but I don't think they would be able to pull it off. Robert Scoble's approach seems more pragmatic: Making applications work together seamlessly. And it's a tiny (but important) step towards a more component-oriented architecture.

The history of calling conventions, part 4: ia64

|

The ia-64 architecture (Itanium) and the AMD64 architecture (AMD64) are comparatively new, so it is unlikely that many of you have had to deal with their calling conventions, but I include them in this series because, who knows, you may end up buying one someday.

Intel provides the Intel® Itanium® Architecture Software Developer's Manual which you can read to get extraordinarily detailed information on the instruction set and processor architecture. I'm going to describe just enough to explain the calling convention.

The Itanium has 128 integer registers, 32 of which (r0 through r31) are global and do not participate in function calls. The function declares to the processor how many registers of the remaining 96 it wants to use for purely local use ("local region"), the first few of which are used for parameter passing, and how many are used to pass parameters to other functions ("output registers").

For example, suppose a function takes two parameters, requires four registers for local variables, and calls a function that takes three parameters. (If it calls more than one function, take the maximum number of parameters used by any called function.) It would then declare at function entry that it wants six registers in its local region (numbered r32 through r37) and three output registers (numbered r38, r39 and r40). Registers r41 through r127 are off-limits.

Note to pedants: This isn't actually how it works, I know. But it's much easier to explain this way.

When the function wants to call that child function, it puts the first parameter in r38, the second in r39, the third in r40, then calls the function. The processor shifts the caller's output registers so they can act as the input registers for the called function. In this case r38 moves to r32, r39 moves to r33 and r40 moves to r34. The old registers r32 through r38 are saved in a separated register stack, different from the "stack" pointed to by the sp register. (In reality, of course, these "spills" are deferred, in the same way that SPARC register windows don't spill until needed. Actually, you can look at the whole ia64 parameter passing convention as the same as SPARC register windows, just with variable-sized windows!)

When the called function returns, the register then move back to their previous position and the original values of r32 through r38 are restored from the register stack.

This creates some surprising answers to the traditional questions about calling conventions.

What registers are preserved across calls? Everything in your local region (since it is automatically pushed and popped by the processor).

What registers contain parameters? Well, they go into the output registers of the caller, which vary depending on how many registers the caller needs in its local region, but the callee always sees them as r32, r33, etc.

Who cleans the parameters from the stack? Nobody. The parameters aren't on the stack to begin with.

What register contains the return value? Well that's kind of tricky. Since the caller's registers aren't accessible from the called function, you'd think that it would be impossible to pass a value back! That's where the 32 global registers come in. One of the global registers (r8, as I recall) is nominated as the "return value register". Since global registers don't participate in the register window magic, a value stored there stays there across the function call transition and the function return transition.

The return address is typically stored in one of the registers in the local region. This has the neat side-effect that a buffer overflow of a stack variable cannot overwrite a return address since the return address isn't kept on the stack in the first place. It's kept in the local region, which gets spilled onto the register stack, a chunk of memory separate from the stack.

A function is free to subtract from the sp register to create temporary stack space (for string buffers, for example), which it of course must clean up before returning.

One curious detail of the stack convention is that the first 16 bytes on the stack (the first two quadwords) are always scratch. (Peter Lund calls it a "red zone".) So if you need some memory for a short time, you can just use the memory at the top of the stack without asking for permission. But remember that if you call out to another function, then that memory becomes scratch for the function you called! So if you need the value of this "free scratchpad" preserved across a call, you need to subtract from sp to reserve it officially.

One more curious detail about the ia64: A function pointer on the ia64 does not point to the first byte of code. Intsead, it points to a structure that describes the function. The first quadword in the structure is the address of the first byte of code, and the second quadword contains the value of the so-called "gp" register. We'll learn more about the gp register in a later blog entry.

(This "function pointer actually points to a structure" trick is not new to the ia64. It's common on RISC machines. I believe the PPC used it, too.)

Okay, this was a really boring entry, I admit. But believe it or not, I'm going to come back to a few points in this entry, so it won't have been for naught. [The Old New Thing]

P900

|

The P900 is the successor to SonyEricsson's P800?:

http://www.mobile-review.com/review/image/sonyeric/p900/pic1.jpg

Reviews:

Articles:

[The Tao of Mac]

Hrgmpf. Drool.

NewsGator and posting to Radio UserLand

|

Smart Engine

|

An out-of-the-blue comment by Don Park:

Being highly intelligent just means there is a powerful engine under the hood. What one does with the car is an entirely different matter. And, of course, you need gas to power it. What powers your engine?

(new yorker, 1/12/04)

|

To Plan or Not to Plan

|

Ward Cunningham talks with Bill Venners about using the programming language, rather than the whiteboard, to design and communicate ideas. [Artima.com Articles]

Of course, a must-read.

Software Testing 6: Good Tests for Bad Parameters

|

Framework: NFVersionChecker 2.0

|

A free Cocoa class that lets developers set up version checking with zero effort. It notifies users of the developers program when a new version is available and has a direct download button. (that can point to VersionTracker!) [Studio Log]

Is there something equivalent for Carbon && MFC out there?

The history of calling conventions, part 3

|

Okay, here we go: The 32-bit x86 calling conventions.

(By the way, in case people didn't get it: I'm only talking in the context of calling conventions you're likely to encounter when doing Windows programming or which are used by Microsoft compilers. I do not intend to cover calling conventions for other operating systems or that are specific to a particular language or compiler vendor.)

Remember: If a calling convention is used for a C++ member function, then there is a hidden "this" parameter that is the implicit first parameter to the function.

All

The 32-bit x86 calling conventions all preserve the EDI, ESI, EBP, and EBX registers, using the EDX:EAX pair for return values.

C (__cdecl)

The same constraints apply to the 32-bit world as in the 16-bit world. The parameters are pushed from right to left (so that the first parameter is nearest to top-of-stack), and the caller cleans the parameters. Function names are decorated by a leading underscore.

__stdcall

This is the calling convention used for Win32, with exceptions for variadic functions (which necessarily use __cdecl) and a very few functions that use __fastcall. Parameters are pushed from left to right and the callee cleans the stack. Function names are decorated by a leading underscore and a trailing @-sign followed by the number of bytes of parameters taken by the function.

__fastcall

The first two parameters are passed in ECX and EDX, with the remainder passed on the stack as in __stdcall. Again, the callee cleans the stack. Function names are decorated by a leading @-sign and a trailing @-sign followed by the number of bytes of parameters taken by the function (including the register parameters).

thiscall

The first parameter (which is the "this" parameter) is passed in ECX, with the remainder passed on the stack as in __stdcall. Once again, the callee cleans the stack. Function names are decorated by the C++ compiler in an extraordinarily complicated mechanism that encodes the types of each of the parameters, among other things. This is necessary because C++ permits function overloading, so a complex decoration scheme must be used so that the various overloads have different decorated names.

There are some nice diagrams on MSDN illustrating some of these calling conventions.

Remember that a calling convention is a contract between the caller and the callee. For those of you crazy enough to write in assembly language, this means that your callback functions need to preserve the registers mandated by the calling convention because the caller (the operating system) is relying on it. If you corrupt, say, the EBX register across a call, don't be surprised when things fall apart on you. More on this in a future entry. [The Old New Thing]

Comments an Arnie's accent

|

Ausschussverwertung

|

Lange darüber nachdenken, ob es statt Thai-Tütensuppe nicht vielmehr Tüten-Thaisuppe heißen müsste, diesen Gedanken dann ergebnislos abbrechen und hier zweitverwerten... [frapp.antville.org]

Mal ein ganz anderer Blog. Und jetzt ist die Mittagspause rum.

The "Stupid factor" - There are two of us now...

|

Neal Starkman (quoted from an article wondering about Bush's popularity): Some people -- sometimes through no fault of their own -- are just not very bright.

Good to see that someone else is also coming to this conclusion. Although Neal isn't 100% there yet. Let's face it: Most people -- sometimes through no fault of their own -- are just not very bright.

Unfortunately, this isn't funny at all. Read Neal's article.

MIT OpenCourseWare

|

Für diejenigen Auszubildenden, die mal reinschnuppern möchten was so im Informatik-Studium am MIT gemacht wird.

MacOS X overview

|

Excellent discussion of MacOS X, it's technology and history.

Didn't knew that Open Firmware is based on Forth. Ahh, those fond memories from the early 80s.

The history of calling conventions, part 2

|

Foreshadowing: This information will actually be useful in a future discussion. Well, not the fine details, but you may notice something that explains... um... it's hard to describe. Just wait for it.

Curiously, it is only the 8086 and x86 platforms that have multiple calling conventions. All the others have only one!

Now we're going deep into trivia that absolutely nobody remembers or even cares about: The 32-bit calling conventions you don't see any more.

All

All of the processors listed here are RISC-style, which means there are lots of registers, none of which have any particular meaning. Well, aside from the zero register which is hard-wired to zero. (It turns out zero is a very handy number to have readily available.) Any meanings attached to the registers are those imposed by the calling convention.

As a throwback to the processors of old, the "call" instruction stores the return address in a register instead of being pushed onto the stack. A good thing, too, since the processor doesn't officially know about a "stack", it being a construction of the calling convention.

As always, registers or stack space used to pass parameters may be used as scratch by the called function, as can the return value register.

You may notice that all of the RISC calling conventions are basically the same. Once again, evidence that the 8086/x86 is the weirdo. A wildly popular weirdo, mind you.

The Alpha AXP

The Alpha AXP ("AXP" being yet another of those faux-acronyms that officially doesn't stand for anything) has 32 integer registers, one of which is hard-wired to zero. By convention, one of the registers is the "stack pointer", one is the "return address" register; and two others have special meanings unrelated to parameter passing.

The first six parameters are passed in registers, with the remaining parameters on the stack. If the function is variadic, the parameters can be spilled onto the stack so they can be accessed as an array.

Seven other registers are preserved across calls, one is the return value, and the remaining thirteen are scratch. 1 zero register + 1 stack pointer + 1 return address + 2 special + 6 parameters + 7 preserved + 1 return value + 13 scratch = 32 total integer registers.

Function names on the Alpha AXP are completely undecorated.

The MIPS R4000

The first four parameters are passed in a0, a1, a2 and a3; the remainder are spilled onto the stack. What's more, there are four "dead spaces" on the stack where the four register parameters "would have been" if they had been passed on the stack. These are for use by the callee to spill the register parameters back onto the stack if desired. (Particularly handy for variadic functions.)

Function names on the MIPS are completely undecorated.

The PowerPC

The first eight parameters are passed in registers (r3 through r10), and the return address is managed manually.

I forget what happens to parameters nine and up...

Function names on the PowerPC are decorated by prepending two periods.

Postclaimer: I haven't had personal experience with the MIPS or PPC processors, so my discussion of those processors may be a tad off, but the basic idea I think is sound. [The Old New Thing]

Great paper on the benefits of pair-programming.

Free Smalltalk Books

|

Stéphane Ducasse has an online collection of free Smalltalk books and articles. Very nice. Includes the missing chapters from the famous Smalltalk Blue Book which is, sadly, out-of-print. (Via LtU) via [Bob Congdon]

MacWorld Expo Keynote News

|
  • Xserve mit G5
  • Xserve RAID
  • iTunes
    • 30 Million iTunes served
    • 50K AudioBooks
    • 100K Gift Certificates
    • New Feature: Billboard 100 Charts from 1964 up to today
    • New Feature: 12K Tracks Classical Music
  • iLife '04
    • iPhoto 4 - Up to 25.000 Photos with blazing performance, time-based organizations, rule-based albums, photo ratings, rendezvous photo sharing
    • GarageBand - Music Application (Recording etc. for the rest of us)
  • iPod mini

Working the Program

|

Ward Cunningham talks with Bill Venners about the flattening of the cost of change curve, the problem with predicting the future, and the program as clay in the artist's hand. [Artima.com Articles]

Working the Program

|

Ward Cunningham talks with Bill Venners about the flattening of the cost of change curve, the problem with predicting the future, and the program as clay in the artist's hand. [Artima.com Articles]

Piracy

|

Nick Bradbury on software piracy.

Kata Twenty One: Simple Lists

|

Lists are one of the first data structures we learn as programmers. But familiarity doesn’t mean that we can’t learn a little from them.
Nice kata by Dave Thomas of Pragmatic Programmer fame. Pretty useful, especially for beginners. Of course, his kata's tend to be pretty academic (and my profound aversion for academic exercises is well-known), but let's ignore this aspect for a second ;-)

Kata Twenty One: Simple Lists

|

Lists are one of the first data structures we learn as programmers. But familiarity doesn’t mean that we can’t learn a little from them.
Nice kata by Dave Thomas of Pragmatic Programmer fame. Pretty useful, especially for beginners. Of course, his kata's tend to be pretty academic (and my profound aversion for academic exercises is well-known), but let's ignore this aspect for a second ;-)

Uncle Bob rambles...

|

...about much over-hyped concept of Web-Services.

Folgende Dinge bisher rausbekommen:

  • Beliebiges Symbol innerhalb eines SDK-basierten PIOs instantiieren (nicht ganz so einfach wie es sich anhört aber nach einem Nachmittag wildem Suchen im SDK dann doch hinbekommen)
  • Doppelklicken auf ein PIO kann ich nun abfangen und dann z.B. einen beliebigen Dialog aufreißen
  • Es besteht auch die Möglichkeit den "Edit Group" Event abzufangen, aber das macht wahrscheinlich weniger Sinn im Kontext eines KMs?

Nächste Tasks:

  • Sauberes CodeWarrior-Projekt (ich würge grade noch im Sample-Code rum) aufsetzen
  • Den Code zum Generieren eines KMs einbauen
  • Code zum Generieren eines KM im Kontext eines PIO zum Laufen bringen
  • Das innerhalb des PIOs erzeugte Korpusmöbel korrekt plazieren
  • Diese (hoffentlich orthogonalen :-) Änderungen am KM auch in die aktuelle Version im CVS einfließen lassen

A'll keep you posted on my progress...

Four Strategies for Iteration

|

RefactoringMalapropism

|

Posting to a blog from RSSBandit & FeedDemon...

|

You can post to your blog from RSS Bandit using the w.bloggar plugin developed by Luke Hutteman.
via [Dare Obasanjo aka Carnage4Life]

Update: Looks like the plugin works well with FeedDemon, too. (via [Ted Leung]). Haven't checked if w.bloggar works with Radio, though.

New Year's Regressions

|

The history of calling conventions, part 1

|

The great thing about calling conventions on the x86 platform is that there are so many to choose from!

In the 16-bit world, part of the calling convention was fixed by the instruction set: The BP register defaults to the SS selector, whereas the other registers default to the DS selector. So the BP register was necessarily the register used for accessing stack-based parameters.

The registers for return values were also chosen automatically by the instruction set. The AX register acted as the accumulator and therefore was the obvious choice for passing the return value. The 8086 instruction set also has special instructions which treat the DX:AX pair as a single 32-bit value, so that was the obvious choice to be the register pair used to return 32-bit values.

That left SI, DI, BX and CX.

(Terminology note: Registers that do not need to be preserved across a function call are often called "scratch".)

When deciding which registers should be preserved by a calling convention, you need to balance the needs of the caller against the needs of the callee. The caller would prefer that all registers be preserved, since that removes the need for the caller to worry about saving/restoring the value across a call. The callee would prefer that no registers be preserved, since that removes the need to save the value on entry and restore it on exit.

If you require too few registers to be preserved, then callers become filled with register save/restore code. But if you require too many registers to be preserved, then callees become obligated to save and restore registers that the caller might not have really cared about. This is particularly important for leaf functions (functions that do not call any other functions).

The non-uniformity of the x86 instruction set was also a contributing factor. The CX register could not be used to access memory, so you wanted to have some register other than CX be scratch, so that a leaf function can at least access memory without having to preserve any registers. So BX was chosen to be scratch, leaving SI and DI as preserved.

So here's the rundown of 16-bit calling conventions:

All
All calling conventions in the 16-bit world preserve registers BP, SI, DI (others scratch) and put the return value in DX:AX or AX, as appropriate for size.

C (__cdecl)
Functions with a variable number of parameters constrain the C calling convention considerably. It pretty much requires that the stack be caller-cleaned and that the parameters be pushed right to left, so that the first parameter is at a fixed position relative to the top of the stack. The classic (pre-prototype) C language allowed you to call functions without telling the compiler what parameters the function requested, and it was common practice to pass the wrong number of parameters to a function if you "knew" that the called function wouldn't mind. (See "open" for a classic example of this. The third parameter is optional if the second parameter does not specify that a file should be created.)

In summary: Caller cleans the stack, parameters pushed right to left.

Function name decoration consists of a leading underscore. My guess is that the leading underscore prevented a function name from accidentally colliding with an assembler reserved word. (Imagine, for example, if you had a function called "call".)

Pascal (__pascal)
Pascal does not support functions with a variable number of parameters, so it can use the callee-clean convention. Parameters are pushed from left to right, because, well, it seemed the natural thing to do. Function name decoration consists of conversion to uppercase. This is necessary because Pascal is not a case-sensitive language.

Nearly all Win16 functions are exported as Pascal calling convention. The callee-clean convention saves three bytes at each call point, with a fixed overhead of two bytes per function. So if a function is called ten times, you save 3*10 = 30 bytes for the call points, and pay 2 bytes in the function itself, for a net savings of 28 bytes. It was also fractionally faster. On Win16, saving a few hundred bytes and a few cycles was a big deal.

Fortran (__fortran)
The Fortran calling convention is the same as the Pascal calling convention. It got a separate name probably because Fortran has strange pass-by-reference behavior.

Fastcall (__fastcall)
The Fastcall calling convention passes the first parameter in the DX register and the second in the CX register (I think). Whether this was actually faster depended on your call usage. It was generally faster since parameters passed in registers do not need to be spilled to the stack, then reloaded by the callee. On the other hand, if significant computation occurs between the computation of the first and second parameters, the caller has to spill it anyway. To add insult to injury, the called function often spilled the register into memory because it needed to spare the register for something else, which in the "significant computation between the first two parameters" case means that you get a double-spill. Ouch!

Consequently, __fastcall was typically faster only for short leaf functions, and even then it might not be.

Okay, those are the 16-bit calling conventions I remember. Part 2 will discuss 32-bit calling conventions, if I ever get around to writing it. [The Old New Thing]

eXtreme ÖPNVing - Teil II

|

Rheinzabern - Karlsruhe

RB 38919 Rheinzabern/Wörth - Fahrkarte für EUR 2.90. Die Regionalbahn ist gut geheizt, ausreichend Platz - Ein offizielles Lob der deutsche DB. Kaffee wird nicht serviert. Der Fahrkartenentwertungsautomat ist natürlich kaputt, dafür entwertet ein von meinen Steuergeldern subventionierter Schaffner persönlich meine Karte.

Nächste Haltestelle Wörth.

RE 3815 Wörth/Karlsruhe - Eng, aber pünktlich. Kein WiFi. Ein ICE überholt rechts.

Karlsruhe HBF/Europaplatz.

S4 - Total überfüllt.

40 Minuten insgesamt.

About this Archive

This page is an archive of entries from January 2004 listed from newest to oldest.

December 2003 is the previous archive.

February 2004 is the next archive.

Find recent content on the main index or look in the archives to find all content.