Archive for August, 2008

How Well Can We Know What an Author Meant?

August 5, 2008

(Written April, 1993)

In interpreting a text, is there a limited range of valid “variant” readings, outside of which are only invalid “misreadings”? If so, how can a reader determine which meanings are allowable variants and which are impermissible misreadings?

The answer to that question hinges on the answer to some more general questions. Is a text’s meaning determined by its author? If so, how sure can a reader be of correctly determining what the author meant? Or is the meaning of a text determined only by the language used to construct it, the author being irrelevant?

The stakes are high for answering these questions. As M.H. Abrams writes, “without that confidence that we can use language to say what we mean and can interpret language so as to determine what was meant, there is no rationale for the dialogue in which we are now engaged” (p. 438).

Some theorists hold that readers can determine the meaning of a text without reference to the author of the text. I.A. Richards writes, “The meaning of a line of Shakespeare is, for linguistics, to be conceived… in terms of its relations to other utterances, actual or possible, in English…. an appeal to some hypothetical event in Shakespeare’s mind… is not… propitious procedure” (Sebok p. 245). According to Richards, a reader can determine the difference between an acceptable variant reading and a misreading-”which of the various meanings was present” (p. 247) in a text-by seeking “what most fully takes into account the situation the utterance is meeting and the integrity of the language” (p. 251). In other words, look at the extratextual context of the text as a whole and at the relationships between the individual words. What each word can mean is constrained by the other words and by what that word has meant in the past and in other texts. The relationships within the language and knowledge of the context of the writing are our only resource for interpretation since we can not know with certainty what was on the author’s mind.

While a procedure such as Richards advocates can narrow down the range of possible meanings of the text to some extent, is it sufficient to identify a misreading? Or are additional restrictions on meaning required? Can a text even be language-have meaning-apart from the intent of its author? Those who answer “yes” must believe “that marks and noises can be language ‘even though nobody ever meant anything’ by them” (p. 469), point out Steven Knapp and Walter Benn Michaels. That view must even allow the possibility of texts that have no author, but nevertheless have meaning. When the wind howling through a house sounds like the word “who,” is language (with meaning that can be interpreted by a listener) being produced?

Knapp and Michaels, as summarized by Richard Rorty, say otherwise. “Marks which are shaped like a sentence of English do not count as language unless the marks are backed up by an intention-unless they are inscribed by somebody who meant something by them” (p. 460). They propose as an illustration a hypothetical set of markings, produced by random wave motion, that happen to have the form of an English poem. There is no author, and thus no intent; is there still meaning, and is misreading possible?

Those who pursue meaning apart from intent end up in the camp with deconstructionists such as Jacques Derrida and Hillis Miller. Derrida begins with only the physical marks on the page-ignoring the author-and concludes by proposing (as described by Abrams) “that we deliver ourselves over to a free participation in the infinite free-play of signification opened out by the signs in a text” (p. 431). There is not just one meaning to each text; there are an infinite number. While others may agree with that statement, Derrida goes a step further by claiming that only the marks on the page constrain the meaning of the text. Not even the syntax of the sentences can narrow down the range of possible meanings for their constituent words.

So how should the reader choose among the infinite number of meanings? Richard Rorty suggests that interpreters “treat everything as a matter of a choice of context and nothing as a matter of intrinsic properties” (p. 461). If there is no intrinsic meaning to a text (given to it by its author), then “why not just put in a context, describe the advantages of having done so, and forget the question of whether one has got at either its ‘meaning’ or ‘the author’s intention’?” (p. 461) Rorty seems unconcerned about which particular meaning the reader arrives at, a curiously cavalier attitude to take toward textual interpretation. Can we do no better in choosing between the possible meanings allowed by Richards’ textual analysis?

Hillis Miller, a follower of Derrida, describes the implication of Derrida’s approach: in the absence of the author’s intention, it is impossible for the reader to choose between the meanings. They are all equally likely. M.H. Abrams writes of Miller’s view, “Any word within a given text… can thus be claimed to signify any and all of the diverse things it has signified in the varied forms that the signifier has assumed through its recorded history…. [It is] stripped of any norms for selecting some of these and rejecting others” (p. 433). He quotes Miller: “Any reading can be shown to be a misreading on evidence drawn from the text itself” (p. 433). Every reading is a misreading because every meaning is possible for every word and many of those meanings are incompatible with each other. 

But if every reading is a misreading, language loses its primary function-communication. It becomes a pointless, useless game in the reader’s mind. Miller, again quoted by Abrams, writes, “reading is never the objective identifying of a sense but the importation of meaning into a text which has no meaning “in itself'” (pp. 427-428). It is true that a text has no meaning “in itself,” in that the meaning is not physically present in the text. If it were, people would not be debating how to interpret texts, for the meaning of a text would be unambiguous. If, as Miller claims, the meaning is only created in the reader’s mind, discarding the possibility of discovering the author’s intent, the reader must allow all possible meanings. The result, as summarized by Abrams, is that “no text, in part or whole, can mean anything in particular, and that we can never say just what anyone means by anything he writes” (p. 434). 

This is a grim prospect for those who had hoped to communicate something through writing. Abrams writes in an opposing view: “Language, unlike the physical world, is a cultural institution that developed expressly in order to mean something and to convey what is meant to members of a community who have learned how to use and interpret language” (p. 432). Of Miller’s claims, he adds, “Such criticism has nothing whatever to do with our common experience of the uniqueness, the rich variety and the passionate human concerns in works of literature, philosophy, or criticism” (p. 435). In fact, as Abrams points out, Miller is not true to the consequences of his proposals when he writes, for in expressing his views, he appears to be assuming that he is clearly communicating a message that his audience will understand. Knapp and Michaels argue that regardless of the theories people may put forth, in practice they “all think language is intentional, and they all think their beliefs are true” (p. 472).

If some determination of the author’s intent is necessary for a text to have meaning and thus to communicate, how can a reader determine that intent? How accurately must he do so in order to avoid a misreading? How accurately is it possible to determine the intent? 

An author does have a definite meaning in mind when composing a text. Therefore, there is an objective reference for our interpretations. As Knapp and Michaels write, “A text means what its author intended it to mean whether or not other authors on other occasions use the same marks (or noises) to say the same thing” (p. 469). The problem for the reader is to determine, as closely as needed for the occasion, what the author’s intention is. To use an illustration from Knapp and Michaels, of two people yelling, “Fire!”, one might be commanding a firing squad and the other calling the fire department (p. 469). Another example is the use of irony. If one is to respond appropriately to a message, one must be able to know what the author of the message means.

Stanley Fish takes issue with claims that it is possible to know objectively what an author meant in a text. He rejects the notion of objective truth because “there are no unmediated facts nor any neutral perception” (p. 443). That is the case because everything we learn is filtered through our beliefs, which” are not what you think about but what you think with” (p. 443). Fish extends this probably uncontroversial claim into a claim that objective truth (about anything) does not exist, or does not exist for any practical purpose: “This does not mean that a notion like ‘truth’ ceases to be operative, only that it will always have reference to a moment in the history of inquiry rather than to some God or material objectivity or invariant calculus that underwrites all our inquiries” (p. 439). We must be content with whatever perception of truth our beliefs and surroundings allow us to have. In Fish’s view, a reader can not know what an author meant, only what the reader’s beliefs allow. All knowledge is performance; competence, as theorized by Noam Chomsky, does not exist. 

But Fish errs in making the knowledge of objective truth an all-or-nothing proposition. His purpose is to show that the creation of theories of competence, such as Chomsky has attempted for linguistics, is “impossible” because all knowledge is derived from context-our beliefs. A perfect understanding of a person’s competence at interpreting language or literature may well be impossible to arrive at. But can not one interpretation of a text be nearer to, or farther from, what the author meant than another? If we can not have a perfect and complete theory, can we learn nothing from an incomplete one that explains many empirical observations? 

Perfect and exhaustive understanding of the meaning intended by the author is not necessary. In practice, it appears that (in Abrams’ words) “competent readers” can understand “closely enough for the purpose at hand, what the author meant” (p. 426). There is some latitude in interpretation. While the author might have had additional shades of meaning in mind, knowing an approximation is good enough for most purposes. Most people would agree that this claim holds true for everyday conversation. Why not also for literary texts? 

Fish states that his opponents have “the hope that our claims to knowledge can be ‘justified on the basis of some objective method of assessing such claims’ [quoting Keith Lehrer] rather than on the basis of the individual beliefs that have been derived from the accidents of education and experience” (p. 439). Although we filter all of our knowledge through our education and experience, and thus our beliefs, it is possible for our beliefs to be proven wrong (inconsistent with observation) and to change. We learn how to interpret literature as part of a social process. As Abrams puts it, “By interaction with more competent users and by our own developing experience with language, we come to recognize and correct our mistakes in speaking or understanding” (p. 429). This view is similar to Richards’ textual and contextual analyses. Readers can correct misreadings by examining other texts and by interacting with other readers.

Not being the text’s author, we can never be completely sure what his objective intention is. But if we are to have true communication, and the marks that represent language are to signify anything definite, we must concern ourselves with determining it. As Knapp and Michaels write, “Controversy arises only when there is a disagreement about what some particular author meant on some particular occasion” (p. 467).

Although perfect communication is impossible, it is possible and necessary for a reader to come reasonably close to understanding what a text’s author meant. Without reference to the author’s intent, meaningful communication is impossible and we are forced into Derrida’s bleak and pointless void of indecision. Any reading that competent readers consider likely to be one intended by the text’s author is an acceptable variant. Any reading that they can not plausibly consider an intended meaning of the author must be a misreading.


Abrams, M.H. “The Deconstructive Angel” Critical Inquiry, Spring 1977, 425-438.
Fish, Stanley. “Consequences.” Critical Inquiry, March 1985,433-458. 
Hirsch, Jr., E.D. “Against Theory?” Critical Inquiry, June 1983,743-747. 
Knapp, Steven, and Walter Benn Michaels. “A Reply to Richard Rorty: What Is Pragmatism?” Critical Inquiry, March 1985,467-473. 
Rorty, Richard. “Philosophy without Principles.” Critical Inquiry, March 1985, 459-465.
Thomas A. Sebok, ed. Style in Language. Cambridge: M.I.T. Press, 1960. 


The 8086 and 68000 Compared

August 5, 2008

(Written in 1987)

I. Introduction

Among the high-end microprocessors currently available, two of the most widely used are the Intel 8088 and the Motorola MC68000 (usually abbreviated to just 68000).  Both are members of small families of microprocessors.  The 8088 family includes the 8086 and the more powerful 80286 and 80386; it can trace its lineage through the earlier 8080 and 8008 all the way back to the first microprocessor, the 4004. Since the 8088 is identical to the 8086 in most respects, and since the 8086 is considered to be the “parent” of the 8088 chip’s microprocessor family, I will refer to the 8086 in this paper; however, everything said about it also applies to the more widely-used 8088. The 68000 family contains, besides the 68000 itself, the 68008, the 68010, the 68012, and the 68020.  These processors generally have additional registers and operation codes beyond what the 68000 has; however, I will not be dealing with them.

The rivalry between the 8088-based IBM PC family and the 68000-based Apple Macintosh series sets one wondering how the microprocessors they use perform.  I will be examining these two microprocessors from a programmer’s point of view; the only references to hardware characteristics will be those that are important to most assembly-language programmers using the chips.

II. User Registers

The registers that are available to the assembly-language programmer are where some of the most obvious major differences between the 8086 and the 68000 can be found.  The 8086 contains 14 16-bit registers, four of which can also be used as two eight-bit registers.  All of the 8086’s registers are used for specific functions, although several can be used for general storage as well.

The four “general purpose” registers in the 8086 are called AX, BX, CX, and DX to indicate their “eXtended” (16-bit) length; their two halves can also be referenced as eight-bit registers called AH and AL, BH and BL, CH and CL, and DH and DL, for the High and Low halves of the 16-bit value. The AX register is the primary accumulator; many instructions, such as MOV and AND, have special short forms which specifically deal with the AX register (or the AL register, for eight-bit operations). The BX, CX, and DX registers can also be used as eight- or 16-bit accumulators, but they have unique functions to which they are dedicated in some situations: BX is used as a base pointer in certain addressing modes, CX is used as a loop counter, and DX is used to hold I/O port addresses.

Besides the four “general purpose” registers, the 8086 has four 16-bit index registers, called SP (the stack pointer), BP (the base pointer, used similarly to BX in some addressing modes), SI (source index for string operations), and DI (destination index for string operations). It also has a 16-bit PC register (the program counter) and four 16-bit “segment” registers, called CS (code segment), DS (data segment), SS (stack segment), and ES (extra segment). I will deal more fully with the segment registers in the Addressing Modes section of the paper. Finally, the 8086 has a 16-bit Status register, also called the Flags register or the Program Status Word (PSW).  This register contains nine one-bit flags which keep track of the results of arithmetic operations and certain operating modes; some of the flags will be discussed in detail later on.

The 68000 contains 18 32-bit registers and one 16-bit register, giving it considerably more internal storage space than the 8086.  In addition, the 68000 registers come much closer to being “general purpose” than do those of the 8086.  The 68000 has eight 32-bit “data” registers, named D0 through D7. They can be used to hold 32-, 16-, or 8-bit values, depending on the instructions used to manipulate them. The 16- and 8-bit instructions affect only the appropriate number of lower order bits in the registers.  The data registers can all be used for all arithmetic operations, and most other operations as well. 

The 68000 also has seven 32-bit general-purpose “address” registers, named A0 through A6. These registers can also be used for 16-, but not 8-bit operations. They can be used in some arithmetic operations, but they are usually used to hold the addresses of operands which will be manipulated.

The 68000 also has a 32-bit program counter (PC) and two 32-bit stack pointers, called USP (user stack pointer) or A7, used in “user mode,” and SSP (system stack pointer) or A7′, used in “supervisor mode” (see the Other Differences section below for a more complete description of the 68000’s operation modes). However, the USP register can be copied to or from any of the address registers during supervisor mode by using the MOVE instruction.  Finally, the 68000 has a 16-bit SR (Status Register) register, of which the lower eight bits are available in user mode and are called the CCR (Condition Code Register). The CCR essentially holds the results of arithmetic calculations, as with the 8086 Flags register; the rest of the 68000 SR holds other operation mode flags.

In summary, while some of the registers in these two processors share similar functions, e.g. the stack pointers, program counters, and status registers, their “general purpose” registers differ greatly. The 68000 has more of them (15 vs. six, including SI and DI), and they can hold larger values and be used for a greater variety of purposes than those on the 8086.

III. Addressing Modes

The 8086 and the 68000 also differ in how they find the operands for their machine language opcodes, although their addressing modes look less similar at first glance than they actually are.  The 8086, as mentioned before, has a 16-bit program counter and four 16-bit “segment registers.” Depending on the operation being performed, the value of one of the segment registers, shifted left by four bits (in effect multiplying it by 16), is added to an “effective address,” calculated in one of the ways described below, resulting in a 20-bit absolute address.  This means that the 8086 can directly address one megabyte of memory. For fetching instructions, the Code Segment register is used; for stack operations, the Stack Segment register; for certain string operations, the Extra segment register; and for most other operations, the Data Segment register.  The Data Segment default can be overridden to use another segment register in most cases.

The 8086 can access its operands in one of twelve general ways, called addressing modes. They are:

Immediate Mode:
1. Operand is in opcode
Direct Mode:
2. Operand is in register specified in opcode
3. Address of operand is in DS+16 bit signed displacement following opcode
Direct, Indexed Mode:
4. Address of operand is in DS+DI or SI+8 or 16 bit signed displacement
Implied Mode:
5. Address of operand is in DS+DI or SI
Base-Relative, Direct Mode:
6. Address of operand is in DS+BX
7. Address of operand is in DS+BX+8 or 16 bit signed displacement
Base-Relative, Direct, Indexed Mode:
8. Address of operand is in DS+BX+DI or SI+8 or 16 bit signed displacement
Base-Relative, Implied Mode:
9. Address of operand is in DS+BX+DI or SI
Base-Relative, Direct Stack Mode:
10. Address of operand is in SS+BP+8 or 16 bit signed displacement
Base-Relative, Direct, Indexed, Stack Mode:
11. Address of operand is in SS+BP+DI or SI+8 or 16 bit signed displacement
Base-Relative, Implied Stack Mode:
12. Address of operand is in SS+BP+DI or SI 

Note that there are actually more than twelve combinations of registers used for addressing, because of the many places where either DI or SI can be used.  However, the above are the twelve patterns that the 8086 uses to compute effective addresses.  Note the dedicated use of specific registers for each addressing mode.

The 68000, in contrast, has no need for the segment registers because of its 32-bit program counter. In fact, the program counter actually allows larger addresses than the chip’s hardware can address: the 68000’s address bus has only 24 bits.  Still, that is enough to handle 16 megabytes, compared with the 8086’s one megabyte address space.  In addition, the specialized register uses of the 8086 are largely missing in the 68000; the main distinction is between the seven address registers and the eight data registers.  Any data register can be used for any purpose that any other data register can; likewise for the address registers.

Here are the available addressing modes in the 68000:

Immediate Mode:
1. Operand is in opcode
Direct Mode:
2. Operand is in register specified in opcode
Absolute Mode:
3. Address of operand is in opcode
Address Register Indirect Mode:
4. Address of operand is in An (n=0-6)
5. Address of operand is in An; predecrement An (n=0-6)
6. Address of operand is in An; postincrement An (n=0-6)
Address Register Indirect Mode/Program Counter Indirect Mode:
7. Address of operand is in An or PC+16 bit signed displacement (n=0-6)
8. Address of operand is in An or PC+Xm+16 or 32 bit signed displacement (n=0-6; Xm=A0-A6 or D0-D7)

Again, there are actually many more combinations of registers than there are access patterns, i.e. addressing modes.  The 68000’s addressing modes tend to each use fewer registers than the 8086’s do; however, most of that difference is due to the 8086’s use of segment registers.  Once they are taken into account, the addressing modes of the two processors are remarkably similar; the largest difference between them is that the 68000 modes can be used with many more registers than can the 8086 modes.  Aside from that, the 8086 lacks predecrement and postincrement modes, a minor omission.

IV. Instruction Sets

Many of the differences between the instruction sets of the 8086 and the 68000 have already been dealt with in the section on User Registers and the section on Addressing Modes.  Differences in those areas lead directly to readily evident differences in the instruction sets, for example the sizes of the values saved on the stack by the CALL/JSR instructions. Below I will discuss notable differences not covered earlier. 

The standard assembler mnemonics for the 8086 and the 68000 differ considerably.  Although both use capital letters, the 8086 uses the order “destination, source” in its operand field while the 68000 uses the reverse.  Also, instructions which perform essentially the same function are given different names by the two assemblers. For example, the 8086 CALL (subroutine) performs analogously to the 68000 JSR (Jump to SubRoutine), and the 8086 SBB (SuBtract with Borrow) performs the same function as the 68000 SUBX (SUBtract with eXtend).  Other mnemonics have smaller differences, for example: MOV on the 8086 is MOVE on the 68000 (and as noted above, the order of operands is reversed).

“String operations” means the instructions used to implement operations on consecutive memory elements, usually with some kind of automation or semi-automation. The 8086 has special instructions included for just this purpose. They automatically perform an operation (moving or comparing data), then increment or decrement (depending on the state of the Direction flag in the Flags register) index registers (SI and/or DI) to point to the next element. If they are preceded by the REP instruction, they also decrement and test a counter (CX); if it is not zero, they keep looping. Perhaps the weakest aspect of these instructions, called MOVS, LODS, STOS, SCAS and CMPS, is that they inflexibly use specific registers for each aspect of their operation. Otherwise, they are faster and shorter than the corresponding normal loops would be.

The 68000 does not have dedicated string operation instructions. Instead, it has the predecrement and postincrement addressing modes, mentioned earlier, which can be used with any of the address registers.  These are used with the standard conditional branch instructions.  Thus although the 68000 is more flexible in its implementation of string functions, it cannot have loops which are as tight as those the 8086 can.

Stack operations are an area where the 68000 is clearly more versatile than the 8086.  The 8086 uses PUSH and POP instructions which can only move 16-bit values onto or off of the system stack. To implement more than one stack, the programmer would need to use MOV along with DEC (DECrement value) and INC (INCrement value) on the register or memory location chosen as the second stack’s pointer. The 68000, by contrast, handles stack operations by using the predecrement (for push) and postincrement (for pop) addressing modes on anyone of the address registers, including A7, the USP register. The 68000 can therefore not only move 16-bit values onto or off of the stack, but it can perform other operations such as AND and CLR on stack values, and the MOVEM (MOVE Multiple registers) instruction can be used to good advantage to quickly push or pop many registers at once to or from the stack. The 68000 can also do 32- and 8-bit stack operations.  However, register A7 won’t accept 8-bit operations, to guarantee that words it contains will start on even addresses (see the section on Other Differences below). The 68000 also has two instructions, LINK and UNLK, which allocate and deallocate, respectively, a stack frame for temporary storage.  The 8086 has a form of the RET instruction which adds a given value to the stack pointer before pulling the address off of the stack, but it is most useful for cleaning up at the end of subroutines which are passed values on the stack.

In the area of integer arithmetic, the 8086 is slightly more versatile than the 68000. It can add and subtract 8 or 16 bit values, with or without adding in the carry; it can multiply two 8-bit or two 16-bit values, signed or unsigned; and it can divide 16 by 8 bit or 32 by 16 bit values, signed or unsigned. The 68000 can add and subtract 32 bit values in addition to the operations that the 8086 can do, but it can’t do the 8*8 bit multiplication or the 16/8 bit division that the 8086 can. Of course, those operations are easy to do with the multiplication and division instructions that it does have, simply by clearing the upper parts of the affected registers beforehand. 

Besides the regular binary arithmetic operations, the 8086 has instructions to adjust the result so that it can do arithmetic on BCD and ASCII values, as well. The 68000 has special instructions for doing BCD arithmetic, but it has nothing equivalent to the 8086’s ASCII adjustment instructions.

Although the interrupt handling facilities of the 8086 and the 68000 differ considerably, if we limit ourselves to looking at the software interrupt instructions we find that they are very similar. The 8086 INT instruction causes a jump to any of 224 addresses in low memory; there are actually 256 available, but 32 of them are reserved for other purposes.  INTO uses one of those reserved addresses to cause an interrupt if the overflow flag in the Flags register is set. Both INT and INTO push the Flags, CS and PC registers onto the stack before jumping. The IRET instruction returns from an interrupt, restoring the values of Flags, CS and PC from the stack.

The 68000 has similar instructions with different names: TRAP causes a jump to any of 192 addresses in low memory (the other 64 are reserved) and TRAPV causes an interrupt if the overflow flag is set, both of them saving the values of PC and SR on the stack. RETE is the 68000 equivalent of IRET. Note that although the 68000 has 8 priority levels for interrupts, compared to the 8086’s one level, software interrupts on the 68000 always operate at the same priority, so software interrupts are really no different from those on the 8086 in that respect.  There is one small difference, however: interrupts on the 68000 cause the processor to enter supervisor mode, which the 8086 does not have.

In looking over the instruction sets of the 8086 and the 68000, I found a few other oddities I would like to discuss. The first instructions in the alphabetical lists for both processors made me wonder if someone was playing a joke on me: AAA and ABCD on the 8086 and 68000, respectively. The abbreviations stand for Adjust result of ASCII Addition and Add Binary Coded Decimal, but they sure look to me like they were contrived to be cute.  That’s okay. It’s fun to see something like that sneak into general production.

The 8086’s assorted odd instructions include LAHF and SAHF, which load and save the lower byte of the Flags register into the AH register. That seems rather specialized to me. There is also JCXZ, which Jumps if the CX register is Zero. It is the only instruction in the set which tests a full register instead of just a bit or two, and it reinforces the specialized use of CX as a counter.  Last, there is the XLAT instruction, which moves the value pointed to by AL + BX into AL.  It is intended for use in table lookups, but it seems very limited and specialized to me: there is no choice as to which registers may be used.  However, in that respect, it is consistent with what seems to be the general register use philosophy of the 8086. 

The 68000 also contains some unusual instructions. In addition to the standard bit test instruction, BTST, it has BCHG, BCLR, and BSET, which combine two operations: they test a bit and then complement, clear, or set it respectively. It also has instructions for dealing with variable-length bit fields, with the mind-numbing mnemonics BFEXTU (Bit Field EXTract Unsigned), BFFFO (Bit Field Find First One), BFINS (Bit Field INSert), BFSET (Bit Field SET), and BFTST (Bit Field TeST). I never thought I’d see three F’s in a row in an assembly language instruction!

Another 68000 instruction which combines two operations is CAS2, which Compares And Swaps two values. It is specifically useful in a multiprocessor environment, where if the operation was done in several steps another processor could grab control of the bus in the middle of the process and corrupt the operation. CHK is an unusual instruction which checks if the value in a data register is between 0 and a given boundary.  Unlike most comparison instructions, if the value is outside of those limits, it causes an interrupt (a trap) rather than setting a flag. Finally, there is RTR, which pulls not only the PC but also the CCR from the stack. It is like RTE, which can only be used in privileged mode, except that it does not restore the high byte of the SR.

Overall, in the majority of areas the 68000 has a more powerful and flexible instruction set than the 8086. That difference is due largely to its having more and larger registers and allowing more versatility in their use.

V. Other Differences

There are a few other differences which will be important to most assembly language programmers on these machines but which do not fit into any of the above categories.  For example, the 8086 allows words (16-bits) to start at any address, while the 68000 requires that words and long words (32-bits) start at even addresses.  Also, the two processors use opposite orders of storage for multibyte numbers: the 8086 stores the lowest valued byte first, the 68000 the highest. And lastly, the 8086, like most microprocessors, has only one operating mode. The 68000, designed more with multi-user environments in mind, has two operating modes: user mode, which is the normal one, and supervisor mode, which is able to use certain privileged instructions affecting the Status Register and I/O devices, like RTE and RESET.  As mentioned above, interrupts cause the 68000 to enter supervisor mode. Having two different modes is useful in preventing ordinary users from changing data belonging to the system or to other users, or even crashing the system.

VI. Conclusion

Both the 8086 and the 68000, and their related families of microprocessors, contain a powerful assortment of registers, addressing modes, and instructions.  Both are able to perform high-precision arithmetic, allow large address spaces, and can access their operands in many different ways.  The 68000, however, has more and larger registers, and allows much greater versatility in their use. In addition, it has a privileged operating mode, which the 8086 lacks, to protect the system from disaster in complex operating environments. From the programmer’s point of view, then, the 68000 seems to be a more desirable chip to use than the 8086.


All technical data on the 8086 is from:

Rector, Russell, and Alexy, George. The 8086 Book. Berkeley, California: Osborne/McGraw-Hill, 1980.

All technical data on the 68000 is from:

Leventhal, Lance A.; Hawkins, Doug; Kane, Gerry; and Cramer, William D. 68000 Assembly Language Programming, Second Edition. Berkeley, California: Osborne/McGraw-Hill, 1986.

Introduction To Kerberos

August 5, 2008

(Written in June, 2000)

What Is Kerberos?

This is an introduction to the concepts and conventions used in Kerberos. It is intended to give system administrators and software developers an overview of how Kerberos works. It does not contain step by step, detailed instructions on setting up or using Kerberos.

For more information on Kerberos, see its home page at
and Microsoft’s Windows 2000 Kerberos page at

Kerberos is a software package providing authentication between clients (typically run interactively by people) and servers (such as a telnet or POP mail daemon). It consists of several C libraries, several standard client and server programs, a database, and some configuration files. Programs that are not part of the Kerberos software distribution can be Kerberos-enabled by adding calls to the Kerberos libraries.

Kerberos was developed at MIT as part of Project Athena. It is named after the three-headed dog who guarded the entrance to Hades in Greek mythology (called Cerberus by the Romans). The C API is called the General Security Service (GSSAPI). The current version of Kerberos is v5, though v4 is still in widespread use. v5 and v4 are not directly compatible, but v5 has a v4 compatibility mode. This document discusses only v5, as v4 is being phased out.

What techniques does it use?

Kerberos uses private keys (a.k.a. secret keys) to provide authentication. This is unlike SSH, which uses public-private key pairs. In Kerberos, each client has its own private key (your password) and each server also has its own private key (which is stored in a file called a keytab on that server host). Automated clients (such as cron jobs) also have private keys stored in keytabs. Kerberos private keys are never sent over the network in cleartext (that’s what keeps them private). Kerberos does not depend on IP addresses or DNS names for providing authentication, so if they are spoofed, connections will not succeed.

Kerberos divides the world into administrative realms, with names based on hosts’ DNS domain names but in all capital letters. In each realm is a physically secure host with a database containing the private keys of all clients and servers in that realm. That way, each organization can control its own private keys. The host with this database is a trusted third party. It is running a Kerberos server, and is called the Key Distribution Center, or KDC. The KDC database can be replicated onto other hosts for redundancy. (Kerberos calls this propagation.) The host with the master copy is called the primary KDC, and the hosts with the copies are called secondary KDCs.

A client might actually have several private keys, for authenticating to different services. For example, a person might have one private key for logging in as themself, and another private key for logging in as the superuser (root). To figure out which of a client’s private keys to use when authenticating to a server, each private key is labeled with an principal name, which is their user name with an optional instance name. The default instance for a user is empty and is used for logging in, and the principal name looks like “username@REALMNAME” (similar to an email address). The other principal names look like “username/instancename@REALMNAME”, for example, “djm/root@VA.PUBNIX.COM”. (Although any number of instance names separated by slashes can be used, in practice only one level of instance names is ever used.) The “@REALMNAME” is optional, and defaults to the realm of the local host.

Servers’ private keys are also labeled by principal names, with the same format except the user name is replaced by the service name. They look like “servicename/hostname@REALMNAME”, for example, “imap/”. For logins, the service name is “host”.

You can see from the previous example that each Kerberos realm can authenticate for servers in multiple DNS domains. But each DNS domain can be served by only one Kerberos realm. However, clients can authenticate to servers in any realm in which they have principals.

Each request for authentication to the Kerberos server sends the client a sesssion key, which the client caches in a credentials cache file locally. The session keys are used to encrypt connections to servers instead of using the client’s private keys. Session keys are valid only for a few hours, to prevent replay attacks.

The authenticated information for a connection between a particular client and server is called a ticket. A client’s tickets are stored in the credentials cache along with the session key. The first ticket which is issued to a client, and can be decrypted using that client’s private key, is called a ticket-granting ticket, or TGT. It is used for authenticating all services, instead of using the client’s private key, to avoid having to type your password every time you check your email or login to another host.

After an authenticated connection to a server is established, whatever protocol that server uses can either pass information in cleartext, or encrypt it in the session key, as desired. For example, Kerberos “rcp” copies files in cleartext unless the “-x” option is given.

How Is It Configured?

Every host using Kerberos needs a copy of the master configuration file, called “krb5.conf” on Unix, and usually located in /etc or /etc/krb5. The main functions of this file are to specify the KDC(s) for each realm, which DNS domains each realm services, and some optional parameters. There is no distributed lookup service (analogous to DNS) for Kerberos realms. You need to create or copy a krb5.conf that contains information about the realms that you want to access servers in.

In addition, the KDC has a “kdc.conf” giving some parameters and file locations, and ACL files for Kerberos administration and database replication.

On Unix, entries in “/etc/inetd.conf” for the standard versions of servers such as “telnetd” and “rshd” are replaced with entries for the Kerberos versions.

Semi-standard locations for the Kerberos programs and libraries on Unix are /usr/krb5 or /usr/local/krb5.

How Is It Administrated?

Kerberos administration consists mostly of creating principals for new clients and servers, deleting principals for retired clients and servers, creating keytabs for servers and automated clients, and changing passwords.

After the initial setup, most Kerberos administration is done with the “kadmin” program, which uses a separate protocol to connect to a Kerberos administration server on the primary KDC for a realm. Administrative connections can not be made to the secondary KDCs. kadmin uses an “admin” instance to authenticate Kerberos system administrators. There is another version of it called “kadmin.local” that runs only on the primary KDC and does not require a password.

Any client can change their own Kerberos passwords using the “kpasswd” program. Note that the kpasswd protocol changed between Kerberos v5 release 1.0 and release 1.1.

How Does It Authenticate?

As mentioned above, Kerberos uses a trusted third party model. Authentication is initiated by a client, which contacts the KDC to get a TGT, which it decrypts using its own private key. The client then uses the TGT to get a ticket for a particular server from the KDC, and then connects to that server. This process is illustrated in the accompanying diagram (click to enlarge).

Kerberos authentication

More concretely, a user runs “kinit”, which prompts for a password, to get a TGT. Alternately, some login programs and graphical telnet clients get a TGT with the password provided, as does the Kerberos “su” program, “ksu”. kinit can get a private key from a keytab instead of prompting for a password, for use with automated clients.

You can list your current credentials (tickets and session keys) using “klist” and remove them (when you log out) using “kdestroy”.

For remote logins, there is an optional file similar to the non-Kerberos “.rhosts” file, called “.k5login”, which a user can create in their home directory. This file lists principals who are allowed to login
as that user from other hosts using Kerberos, or “ksu” to that user on that host.