Sunday, July 9, 2017

Taxation Is Unnecessary

Although taxation is theft, do you wonder if it is still a necessary evil? If it is possible to fund something coercively, it is possible to fund it consensually. If we put our minds to it, we can come up with ways to work together consensually to accomplish great things. The following are possibilities, though not an exhaustive list. There may be even better ideas to be discovered.

Some voluntary ways to fund/produce something, in general

  • Voluntary donations/philanthropy/endowments/crowdfunding
  • Consensual fund raisers (e.g. a lottery)
  • Make it optional to participate in and pay for the service/program.
  • Income from savings (e.g. Edwards, "Financing Government Without Taxation")
  • Businesses in a free market provide the service
  • Non-profit organizations provide the service
  • Voluntary societies/co-ops get together to provide the service for one another

To take an example, a library could be funded by any one of the above. It could operate on subscription fees, or people opting in instead of a tax forced on everyone. Or if you want it to be 'free' to everyone, it could get its income from a philanthropic endowment, fund raisers or complementary goods sold in the library. Or it could be a community effort--a library society. In the latter case it could be a traditional library building, or new models could be invented, such as a book-sharing society organized as a distributed network of private collections. Or a network of the Little Free Library model. The possibilities are limited only by our ingenuity.

Similarly, apply the above general bullet points when thinking through all other services or programs. There has been much discussion on voluntary production of various specific services. Below is a (non-exhaustive) collection of resources exploring ideas and solutions that don't use taxation.

Sources discussing many services/programs

Welfare

Some possible ways to provide for those in need:

Some discussion of how people were cared for in the United States prior to Social Security.

Roads

Education

Fire Fighting

Utilities (electricity, communications, water, sewer)

Police

  • Bruce L. Benson, To Serve and Protect: Privatization and Community in Criminal Justice.
    See also an interview with the author.
  • Local Problems, Libertarian Solutions, "Crime".
  • Recoup from convicted criminals the cost of defense against crime.

Courts

Military defense

Monday, January 30, 2017

Taxation Is Theft FAQ

Taxation is theft. The basic argument is simple:

  1. Taking that which is another's without their consent is theft.
  2. Taxation is taking that which is another's without their consent.
  3. Therefore, taxation is theft.

The common objections are answered below. I plan to update and improve this FAQ as new objections and arguments arise.

But who will build the roads? or pay for police etc.? Wouldn't it be anarchy without taxation?

Doesn't "Taxation is theft," mean you are being selfish and a freeloader?

Isn't supporting basic governmental functions a shared responsibility that you owe?

You benefitted from the state, therefore don't you owe the state?

Don't you consent by using public infrastructure?

Don't people consent by remaining in the land? It's not force/immoral because you are free to leave.

Isn't taxation like rent? You either pay the rent or have to move.

Aren't you consenting by remaining a citizen (instead of renouncing citizenship)?

Don't people consent by choosing to engage in a taxed activity, like buying/selling?

Don't people consent by using state currency?

Doesn't a person consent by participating in society?

Doesn't a person consent via the social contract?

Don't people consent by voting?

Isn't taxation okay if the people voted to approve it?

Doesn't the state have the authority/jurisdiction to tax people regardless of their consent?

Isn't taxation like a private club, requiring dues in exchange for club benefits?

I consent to be taxed, so the state isn't stealing from me, so it's not the case that taxation is always theft.

Only illegal taking is theft, but taxation is legal.

But doesn't the state define property and what is whose?

Doesn't "taxation is theft" presume that all current property holdings are just?

But who will build the roads? or pay for police etc.? Wouldn't it be anarchy without taxation?

If no taxes meant no government it would not contradict taxation being theft. Both may be true without contradiction, and many people affirm both that taxation is theft and that it is a necessary evil. If both are true, then that would be a hard truth, but we'd have to face it head on, and not ignore the truth because it's hard.

Others disagree with the premise that no taxes means no government, and say that taxation is unnecessary. But whether taxation is necessary, and whether there can be such a thing as a necessary evil are questions different from whether taxation is theft.

Doesn't "Taxation is theft," mean you are being selfish and a freeloader?

Not at all. We, like most people, are glad to contribute to good causes and joint projects, and to pay for goods and services we use. It's just that we can't take what is someone else's to fund things we want and pretend that isn't theft. Do I have a moral responsibility to give charitably/liberally for the common good? Sure, but that doesn't give me a right to take from other people.

Voting for taxes because you are willing to pay it is selfish. You are always able to give as much as you want to the state regardless of the existence of a tax. Therefore, voting for a tax is only about taking from other people. It's voting for theft.

Isn't supporting basic governmental functions a shared responsibility that you owe?

If it were, then any person, group, or organization that wants to produce any of these functions, could start taking money from everyone to fund their own projects without it being theft. Any security company, school, energy company, civil engineering company, or insurance company would be able to take the money it wants from everyone else without it being theft, by claiming that the service they provide (e.g. security, education) is a "shared responsibility." Thus this objection would lead to a kind of anarchy of everyone plundering everyone.

You benefitted from the state, therefore don't you owe the state?

Unilaterally benefiting someone doesn't give you a license to take from them. And a forced exchange is a form of theft. Otherwise it would not be theft for any random jerk to force you into whatever exchange he wants.

Consider the case if anyone else besides the state were to do the same thing (e.g. if you personally unilaterally benefit someone, and then try to take what is theirs). It's recognized as theft if anyone else does the same thing.

Moreover, the state had to tax people in order to be able to fund the benefit in the first place. The production of the benefit was already paid for (via theft) by the taxpayers. For the state to then turn around and claim that the taxpayers owe the state for having provided them the benefit is rather perverse.

Don't you consent by using public infrastructure?

If the state is freely giving away use then this falls under the question You benefitted from the state, therefore don't you owe the state?. Or if fees are charged for usage--such as with water, electricity, garbage collection, toll roads--then this is still no justification for taxation, since users are already paying for the usage.

So the objection being raised here is the idea that the state, as the owner of the resource in question, requires that users pay taxes as payment--that usage is implied consent to the terms of use contract. Firstly, infrastructure is only a tiny fraction of taxes in modern, Western states, so this argument could justify only that tiny fraction. Secondly, this objection falls flat because it's not how taxes work; refraining from using state resources doesn't get you out of taxation. And thirdly, it begs the question because it presupposes that the state justly came to own the public resource in question but the state taxed to fund the construction of the resource in the first place. And in most cases the state is suppressing or banning competition.

Don't people consent by remaining in the land? It's not force/immoral because you are free to leave.

This objection begs the question because it presupposes that taxation is not theft. Because if taxation is theft, then there's no reason the victim should have to opt out or leave.

It would be a form of victim-blaming to to say the victim consented or deserved it for being in the neighborhood. So because this objection assumes that it is not victim-blaming, it assumes the very thing to be proved.

It's seen as obviously theft if anyone else were to do the same thing. Imagine if your neighbor starts stealing from you and his other neighbors, and claims it is okay because he'd stop taking your money if you move away. Your living in your house would not at all imply that you consent to his takings. You never consented to his unilateral impositions in the first place.

Isn't taxation like rent? You either pay the rent or have to move.

In the case of rental property, you have to move because it's someone else's property. This theory would work only if there were no property owners in the land except for the state. But throughout history there have been private landowners (except perhaps in communist countries). There is private property, and there is government property (e.g. government buildings or state parks). (Note however that the state generally obtained its property by theft, such as purchase with taxed money, eminent domain, or arbitrary claims to vast tracts of land.)

To get around this people come up with complex theories of different kinds of property ownership in which the state is the real owner and what we normally think of as ownership is only a conditional permission slip. This theory comes to us from feudalism--the idea of fiefdoms, where an overlord would grant some power (but not real ownership) over some land to a vassal in exchange for allegiance. It is a theory that reduces us all to vassals at best.

There is no reasonable historical argument that any actual existing state owns all the land. Certainly not in the case of rule by conquest or arbitrary claims over land. And in the case of governments purportedly formed by the people, people wanted government to protect them from things like theft, so it would be bizarre to suppose that in doing so they gave up their property. Every landowner would have had to consent to give up his property. And there's no evidence they did.

Aren't you consenting by remaining a citizen (instead of renouncing citizenship)?

Most people became citizens at birth, apart from consent. And non-citizens are forced to pay taxes too.

Don't people consent by choosing to engage in a taxed activity, like buying/selling?

A voluntary exchange involves two parties (buyer and seller). And those two did not consent to the third party's (the state's) unilateral demands. Indeed, consider what happens if the buyer and seller try making the exchange without consenting to pay the tax.

Don't people consent by using state currency?

People had and used money prior to the state making currency. And you can't get out of taxes by using other money (e.g. gold, bitcoin).

For example, if you were to receive your wages in the form of gold or bitcoin, in the U.S. that is counted as taxable income (at the "fair market value" of the gold or bitcoins). You would be forced to pay income tax in U.S. dollars (unless you can persuade the IRS to accept alternative payment). Not possessing any U.S. dollars is not accepted as an excuse for not paying income taxes. It would be up to you to figure out how to obtain the U.S. dollars demanded from you in tax. You would need to exchange your gold, bitcoin, or other assets for U.S. dollars. That exchange may incur additional taxes such as capital gains or sales taxes.

Doesn't a person consent by participating in society?

Society is not the state. Society includes any peaceful, voluntary human interactions including families, friends, division of labor, and buying and selling. Engaging in such interactions does not imply that any of the participants consents to you or anyone taking what is theirs. If it did then it would never be theft for any participant in society to take from another.

People engage in human interaction because it is mutually beneficial. People remain friends because they each value their society. People engage in voluntary division of labor because each party benefits. In trade, both parties become wealthier. It is already reciprocal, voluntary benefit, thus not a one-sided debt. Yes, people are better off by participating in society, but that doesn't mean we may steal from one another.

See also: You benefitted from the state, therefore don't you owe the state?

We also have society with citizens of other countries, in this ever-more-connected world, but you have not therefore have consented to pay the taxes of all the other countries. Nor do states claim to be able to tax the incomes of all people with whom its citizens have society.

Doesn't a person consent via the social contract?

This is circular reasoning because "social contract" is just another way of claiming the person consented. You would still need to explain exactly how the person consented.

Don't people consent by voting?

You still are forced to pay taxes even if you don't vote.

Also a person may vote against taxes or for the candidate most likely to support the least taxes. Neither of which would suggest any consent of taxation. At most the people who actively voted for the taxation could be said to have consented.

Neither does voting imply consent to the system of voting itself or its outcome, because a person can vote merely in self-defense against those who might vote for injustice, and because the outcome is imposed upon him regardless whether he votes.

Isn't taxation okay if the people voted to approve it?

Theft by majority vote is not any the less theft--just as murder by majority vote is still murder. There's nothing magical about a majority that makes it okay to do things that is immoral for anyone else to do. Majorities can't convert injustice into justice. It would be a form of might-makes-right to say that the group with the largest numbers may do what they will to smaller groups. And it is unreasonable to suppose that everyone consented to stake their rights to be won or lost by mere numbers.

Likewise it is not meaningful to suggest that anything goes because "we" are the state. A democratic state could vote to enslave a minority, and it wouldn't follow that it's okay because the enslaved were only doing it to themselves, because "we are the state".

When the older political philosophers (e.g. John Locke and the U.S. Founders) talked of consent of the governed, they meant it as a principle of limiting the state, not a principle that can create new power. The point was that the state has no legitimate powers but what the governed delegate to it, and nobody can delegate any powers but what he already possessed. Ordinary people may not steal from each other, and so they can't delegate any such right to the state.

Doesn't the state have the authority/jurisdiction to tax people regardless of their consent?

How did it get such authority? It is an organization of human beings created by human beings, none of whom have the right to steal. There is no way they could grant to themselves or their organization authority they don't have.

Isn't taxation like a private club, requiring dues in exchange for club benefits?

In the case of a private club, subscription to a magazine, phone service, apartment rental, or whatever, they can claim payment only if you consented to subscribe or become a member, and consented to the terms of the contract. Taxation is a unilateral imposition by the state, taking from people regardless of their consent.

I consent to be taxed, so the state isn't stealing from me, so it's not the case that taxation is always theft.

The issue is that not everyone consented, thus taxation always entails stealing from someone.

Only illegal taking is theft, but taxation is legal.

We aren't talking about theft as a merely legal concept, but in the sense of (in)justice. Any random unjust thing could be be made "legal" or "illegal" by any state. But justice is prior to man-made statutes, as seen in that we often judge statutes as just or unjust. If (in)justice were defined by the state, then nothing the state did could be said to be unjust, and we could eliminate injustice in the world by abolishing the state. But of course injustices like murder and theft are the reason people propose government in the first place. If we defined "murder" in terms of mere legality we could never say that Nazi Germany ever murdered anyone, or that Stalin murdered millions of his countrymen. And common dictionary definitions do often define theft as unjust or wrongful taking.

Sure, one can define a term however one wants, and "illegal taking" is another dictionary definition. Words can have multiple definitions, but to shift a term to a different definition in an argument is dishonest, and fails to respond to what we are talking about here.

But doesn't the state define property and what is whose?

Picture the first human to set foot on a particular area of land, and they decide to settle there on this unowned land, painstakingly clearing and cultivating a field to grow food, building a house, barn, etc. If someone else comes along later and seizes the house and buildings, driving out the builder, we can see the inherent parasitic nature of the act and identify it as theft. (And it is very different from the case of recipients of unilateral beneficence. This is unilateral taking.) We understand the injustice of it, and the concept of property, regardless of the existence of a state, or what laws a state has made. The reason people would propose government in the first place is to defend themselves against such violations--including to protect their property.

Furthermore a state with license to define and assign property as it wants would have absolute power. There would be no tyranny not permissible. It would be antithetical to the idea of a republican or liberal state.

Doesn't "taxation is theft" presume that all current property holdings are just?

No. Taxation would not be a just way to correct for unjust possession. Such a problem needs to be corrected through due process on an individual basis. In each particular case, the particular rightful owner of the particular property in question would need to be identified, with all the relevant evidence considered.

Sunday, September 4, 2016

The Physical Meaning of the Riemann Curvature Tensor

We saw before that the Riemann tensor is the degree to which second derivatives of a vector field fail to commute. We will now consider the physical implications of that. It has a few different meanings that are (not obviously) equivalent.

Parallel transport

To parallel transport a vector along a path means to carry the vector with you along the path without any change in the vector--that is, with the vector's (covariant) derivative along the path being zero.

It turns out that if you parallel transport a vector along a closed path back to where you started, then it will surprisingly end up different (rotated) from the vector you started with, if there is curvature in the region of the closed path. Likewise if you parallel transport a vector from one point to a second point, the result at the second point may vary with the choice of path. This is most easily seen if you imagine transporting a vector along the surface of the sphere of the earth, say from the equator straight north to the north pole vs first transporting it along the equator for some distance, and then straight north to the north pole.

The change \( \delta v^a \) in vector \( \vec{v} \) after parallel transporting it around a closed parallelogram going first along a small vector \( \vec{T} \), then a small vector \( \vec{S} \), and then completing the parallelogram, is given by the Riemann tensor: \[ \delta v^a = - v^b T^c S^d R^a{}_{b c d} \]

If the curvature is positive (see Gaussian curvature) like on a sphere, \( \vec{v} \) will rotate in the same direction as you go around the closed loop. Negative curvature will rotate \( \vec{v} \) in the opposite direction.

Geodesic deviation

The second meaning of the Riemann tensor is that it also describes geodesic deviation. A geodesic is a curve that is as straight as possible. E.g. a "great circle" on a sphere, or a straight line on a plane. In flat space, two initially parallel geodesics will remain a constant distance between them as they are extended. In curved space, the distance between will grow or shrink.

Given a geodesic with initial tangent \( \vec{V} \), and
given a second geodesic starting at a small displacement \( \vec{\xi} \) from the first and initial tangent being the result of \( \vec{V} \) parallel transported along \( \vec{\xi} \),
then as we extend the two geodesics forward, the first derivative of the displacement between them will be zero, because we chose them to be initially parallel. But the second derivative (acceleration) of the displacement is given by the Riemann tensor: \[ (\nabla v \nabla v\xi)^a = V^b V^c \xi^d R^a{}_{b c d} \]

(Note this happens to be the same as the change in \( \vec{V} \) when parallel transported around the parallelogram of \( \vec{V} \) and \( \vec{\xi} \).)
With positive curvature, the geodesics will converge. With negative curvature, the geodesics will diverge.

Sectional curvature

If \( \vec{V} \) and \( \vec{\xi} \) are orthogonal and unit length, then the above acceleration, dotted with \( \vec{\xi} \) is also negative of the value of the sectional curvature (Gaussian curvature) of the 2-surface made of geodesics through the initial point and tangent to \( \vec{V} \) and \( \vec{\xi} \). That is the flattest 2d surface containing the initial point and tangent to \( \vec{V} \) and \( \vec{\xi} \). Any orthonormal pair of vectors in that same plane will give the same value, because a 2d surface has only one scalar value of curvature at a point.

In addition to telling us how geodesics converge/diverge in this 2-surface, the Gaussian curvature can tell us other things like how much the circumference of a circle divided by its diameter will differ from \( \pi \). And how much its area will differ from \( \pi r^2 \). It will tell us how much the sum of the angles of a triangle formed by geodesics will differ from 180 degrees.

Inability to construct a Cartesian coordinate system.

The above meanings of the Riemann tensor are also equivalent to describing the impossibility of constructing a Cartesian coordinate system in the curved space.

  • In Cartesian coordinates we need the basis vectors to be the same everywhere (a basis vector forms a uniform vector field). But the fact that the second covariant derivatives do not commute implies that we cannot construct a vector field whose second derivatives all vanish.
  • The failure of a vector to parallel transport around a loop likewise means we cannot construct a uniform vector field for a basis vector. If you transport a basis vector one unit up the x axis and then up the y axis, you will not get the same result if you transport it to the same point by first going up thy y axis and then the x axis. There's no way to consistently define the basis vector at that point.
  • In Cartesian coordinates, we need to construct straight and parallel coordinate lines, but geodesic deviation means that initially parallel coordinate lines will inevitably converge or diverge.

We can construct a Cartesian coordinate system if and only if all the values of the Riemann tensor are zero at all points in space.

On the other hand, no matter how curved space is, we can always locally construct an approximately Cartesian coordinate system to first order, within a small enough region of space that appears locally flat. For example, a grid of city streets can approximate a Cartesian coordinate system to first order. But if you try to extend it further across the surface of the globe, you will run into problems. The Riemann tensor shows failure in the second derivatives. We can get the first derivatives to behave. E.g. we can make our coordinate lines initially parallel, with the first derivatave of their separation being zero. The amount of rotation of a parallel-transported vector varies linearly with the area of the closed path, thus it is a second-order property.

Monday, August 15, 2016

From Coordinate System to Curvature (Riemann Tensor in General Relativity)

Coordinate system

A set of coordinates specifies a point, so position can be thought of as a function of the coordinates. \[ \mathscr{P} = \mathscr{P}(x^1, x^2, x^3, \dotsc) \] At each point, a set of basis vectors \( \vec{e_i} \) can be defined. Each basis vector is obtained by differentiating position by one coordinate (i.e., holding all other coordinate values constant), which means it is a vector pointing along that coordinate line, where a coordinate line describes a path along which only that one coordinate varies. \[ \vec{e_i} = \frac{ \partial \mathscr{P} }{ \partial x^i } \] Any given vector \( \vec{A} \) can now be expressed as a linear combination of the basis vectors. \[ \vec{A} = A^i \vec{e_i} \] Where the \( A^i \) are the components of the vector in this basis. Here (and throughout) we are using the Einstein summation convention, \( A^i \vec{e_i} = \displaystyle\sum_{i=0}^{N} A^i \vec{e_i} \)

Partial derivative of a vector field:

A vector field is a set of vectors, with one vector at each point (e.g. wind speed or electric field at each point). It can be thought of as a vector-valued function of the coordinates: \( \vec{A}(x^1, x^2, x^3, \dotsc) \). The (partial) derivative of this function with respect to one of the coordinates, gives a vector that is the rate of change of \( \vec{A} \) per unit of that coordinate.

We expand it by the product rule:

\[ \frac{ \partial \vec{A} }{ \partial x^i } = \frac{\partial}{ \partial x^i }( A^j \vec{e_j} ) = \frac{\partial A^j}{ \partial x^i } \vec{e_j} + A^j \frac{\partial \vec{e_j} }{ \partial x^i } \]

Define "Christoffel Symbols", which are the rate of change of the basis vectors:
\[ \Gamma^{k}{}_{i j} \vec{e_k} = \frac{\partial \vec{e_j} }{ \partial x^i } \]

Substitute that into our formula for the partial derivative: \[ \frac{ \partial \vec{A} }{ \partial x^i } = \frac{\partial A^j}{ \partial x^i } \vec{e_j} + A^j \Gamma^{k}{}_{i j} \vec{e_k} \]

In that last term, the summation indices \( j \) and \( k \) are arbitrarily chosen, so we can replace them with whatever we like. So replace \( j \) with \( \alpha \) and replace \( k \) with \( j \). Then the partial derivative of a vector field is:
\[ \frac{ \partial \vec{A} }{ \partial x^i } = ( \frac{\partial A^j}{ \partial x^i } + A^{\alpha} \Gamma^{j}{}_{i \alpha} ) \vec{e_j} \]
This is called "covariant derivative" (to distinguish from partial derivatives of components), and has the following notation:
\[ \nabla_i \vec{A} = \frac{ \partial \vec{A} }{ \partial x^i } \]

Because \( \nabla_i \vec{A} \) is a vector field we can take its partial derivative to get the second partial derivative: \[ \nabla_j \nabla_i \vec{A} \] the partial (covariant) derivative of \( \vec{A} \) with respect to coordinate \( x^i \) and then with respect to coordinate \( x^j \).

Curvature

Curvature is measured by the Riemann curvature tensor, describing the degree to which the second covariant derivative does not commute:
\[ ( v^b R^a{}_{b c d} ) \vec{e_a} = \nabla_c \nabla_d \vec{v} - \nabla_d \nabla_c \vec{v} \] So its components are \[ R^a{}_{b c d} = (\nabla_c \nabla_d \vec{e_b} - \nabla_d \nabla_c \vec{e_b})^a \] thus describing how the second partial derivatives of the basis vectors fail to commute. The components are all zero in flat space, because the second derivatives always commute in flat space, no matter what coordinate system is chosen. So the amount of non-commutativity tells us how space is curved.

Next we consider the physical/geometric meaning of the Riemann tensor.

Saturday, April 23, 2016

Write Your Own Operating System Tutorial: Table of Contents

[This was originally published years ago at cse.unl.edu/~jgompert and then joelgompert.com.]

Write Your Own Operating System Tutorial: Lesson 7: Start Saying Goodbye To BIOS

[This is part of a larger tutorial.
Previous lesson     Table of Contents]

Now that we have a boot loader that will load our operating system, and thus can make our operating system larger than one sector, we can now begin to add some complexity to our system. One of the first things to do is to loosen our tie to BIOS. So far we have been using BIOS functions for all of our input and output. BIOS hides all of the input and output from us with its interface, so we don’t know exactly how it goes about performing its functions. BIOS can often be slower than handling I/O by ourselves, and in doing it ourselves, we can know exactly what is going on, thus giving us more power, control, and flexibility with the design of our operating system. The benefit to using BIOS is that the interface is very standard and should not vary from machine to machine. On the other hand, BIOS can only be used in real mode. Later on, if the operating system switches the processor over to protected mode, then the BIOS functions are unusable. Of course, my main reason for learning to perform the I/O myself it simply to see how it is done. If anyone has any arguments for or against the use of BIOS for I/O, let me know. Perhaps we could discuss it further.

The area we will begin with is that of text output to the screen. So far we have been using BIOS interrupt 0x10, function 0x0E. We will begin performing text output ourselves. Before we can even start to do this, we need to know a few things. First of all, video memory is mapped to main memory addresses starting at address 0xB0000 (flat address from base of the physical address space). The region of memory holding the text content of the screen starts at 0xB0000 for monochrome displays and 0xB8000 for color displays. Try the latter address first, and if you can’t get it working, perhaps try the former. I will proceed assuming the use of a color display.

The first byte (0xB8000) holds the ASCII code for the upper-leftmost character on the screen. The next byte (0xB8001) holds the color/style code for that character. These bytes are followed by two more bytes that hold the ASCII code and color/style code for the next character to the right. The video memory continues alternating ASCII code and style/color code to the end of the first row of text. The next bytes after this represent the first character on the second row, and so on for the rest of the screen.

So, all that is necessary to output text to the screen is to write ASCII codes into this region of memory. (This is referred to as memory-mapped I/O.) However, you will now need to keep track of the location of the cursor.

Speaking of the cursor, you can write characters to anywhere on the screen (anywhere in video memory). But it will look odd to the user if they are typing on the keyboard and characters are appearing one place on the screen and the little blinking cursor is elsewhere on the screen. The video controller chip (6845 on the IBM PC) takes care of drawing the blinking cursor on the screen; we just need to tell it where to move the cursor.

The 6845 video controller is connected to I/O port 0x3B4-0x3B5 for a mono display and 0x3D4-0x3D5 for a color display. As far as I can tell, the 6845 has various registers, and (assuming a color display) port 0x3D4 is used to indicate which port we would like to write to, and then we write the data to port 0x3D5. Registers 14-15 tell the 6845 where to draw the blinky cursor. The following is psuedo-code for moving the cursor.

outbyte(0x3D4, 14);                    // write to register 14 first
outbyte(0x3D5, (cursorpos>>8) & 0xFF); // output high byte
outbyte(0x3D4, 15);                    // again to register 15
outbyte(0x3D5, cursorpos & 0xFF);      // low byte in this register

The cursor position (in cursorpos) is the character number, starting with 0 and number all the characters in the order that they are arranged in video memory. (The offset in video memory for a given cursor position is cursorpos*2 for the ASCII code and (cursorpos*2)+1 for the color/style code.)

Using this region of video memory to output characters and the I/O ports to tell the video controller where to draw the cursor, it is now your job to write a text driver for your operating system. Create a set of functions that you can call to output characters, strings, numbers, pointers, etc to the screen without using BIOS (this means no software interrupts). Make sure that your text driver handles scrolling the text on the screen upward before going off the bottom. Write a function to clear the screen.

Try allowing the user to type characters with the keyboard (you can still use BIOS for keyboard input for now), and echo each character to the screen as it is typed. If you have any troubles writing your text driver, let me know and perhaps I can give you some hints.

As far as the color/style byte is concerned, you can simply use 07 (white on black) for most purposes, but for those of you who are curious, I will explain the different color/style settings. The color/style of a character is one byte. Those 8 bits are used as follows.

Bits 3-0 : Foreground color
Bit 3 2 1 0
Color Intensity Red Green Blue

These four bits can be used in any and all 16 combinations. If bit 3 is 1, it indicates full intensity, 0 indicates half intensity. For example, 3 would be cyan (blue + green) while 11 would be bright cyan (intensity+blue+green).

Bit 5: Reverse Video
Bit 6: Black on colored background, color given by bits 3-0
Bit 7: Blinking text

For example a code of 0x2C (00101100bin) would be reverse video bright red.

Previous lesson     Table of Contents

Write Your Own Operating System Tutorial: Lesson 6: Boot Loader

[This is part of a larger tutorial.
Previous lesson     Table of Contents     Next lesson]

Everything we’ve done so far has been placed entirely inside the boot sector. We can’t make our operating system very big at all if it is to fit in one sector. We need a way of expanding. We will do this by making a boot program that simply loads an executable file off the disk and begins executing it. This is called a boot loader. This file loaded off the disk can be as big as we want, since it will not be constrained to one sector.

This is more difficult than anything else we’ve done so far. It might be a good idea, now, to locate a reference on the FAT file system (or the file system of your choice, but I will be assuming the use of the FAT system). I will give a brief overview of the boot loading process.

A floppy disk contains, in this order, the DOS Boot Record (the first sector we have been working with), the File Allocation Table (FAT), the Root Directory, and then the data contained in the files on the disk. (A hard disk is more complicated. It has a Master Boot Record and multiple partitions.) Suppose we write an operating system, compile/assemble it to a file named LOADER.BIN, and place it on the disk. The boot loader will load it as follows.

  1. The DOS Boot Record (DBR) is read to determine the size of the DBR, FAT, and Root Directory. The location of each on the disk is then determined.
  2. The Root Directory is read in to memory.
  3. The Root Directory is searched for the file name LOADER.BIN. If found, we can look in the directory entry to find out which is the file’s first cluster (file allocation unit). If not found, we give an error message.
  4. The File Allocation Table is read off the disk in to memory.
  5. Starting with the file’s first cluster, we use the FAT to locate all the clusters belonging to the file. We read them all off the disk into memory at a specific location.
  6. We jump to that location to begin execution of the operating system.

All of the reading from the disk will be done using calls to BIOS. If you feel adventurous, use a reference of BIOS functions to learn how to read sectors from the disk and try writing your own boot loader. Otherwise, I have provided a slightly modified version of John S. Fine’s FAT12 bootstrap loader. Last I checked you can get a copy of his utility "partcopy" here. I recommend using this utility and his compiling and installing instructions. Otherwise, you can still copy the boot loader to the floppy disk using the same method we have used in the previous lessons.

; boot12.asm  FAT12 bootstrap for real mode image or loader
; Version 1.0, Jul 5, 1999
; Sample code
; by John S. Fine  johnfine@erols.com
; I do not place any restrictions on your use of this source code
; I do not provide any warranty of the correctness of this source code
;_____________________________________________________________________________
;
; Documentation:
;
; I)    BASIC features
; II)   Compiling and installing
; III)  Detailed features and limits
; IV)   Customization
;_____________________________________________________________________________
;
; I)    BASIC features
;
;    This boot sector will load and start a real mode image from a file in the
; root directory of a FAT12 formatted floppy or partition.
;
;    Inputs:
; DL = drive number
;
;    Outputs:
; The boot record is left in memory at 7C00 and the drive number is patched
; into the boot record at 7C24.
; SS = DS = 0
; BP = 7C00
;_____________________________________________________________________________
;
; II)   Compiling and installing
;
;  To compile, use NASM
;
;  nasm boot12.asm -o boot12.bin
;
;  Then you must copy the first three bytes of BOOT12.BIN to the first three
;  bytes of the volume and copy bytes 0x3E through 0x1FF of BOOT12.BIN to
;  bytes 0x3E through 0x1FF of the volume.  Bytes 0x3 through 0x3D of the
;  volume should be set by a FAT12 format program and should not be modified
;  when copying boot12.bin to the volume.
;
;  If you use my PARTCOPY program to install BOOT12.BIN on A:, the
;  commands are:
;
;  partcopy boot12.bin 0 3 -f0
;  partcopy boot12.bin 3e 1c2 -f0 3e
;
;  PARTCOPY can also install to a partition on a hard drive.  Please read
;  partcopy documentation and use it carefully.  Careless use could overwrite
;  important parts of your hard drive.
;
;  You can find PARTCOPY and links to NASM on my web page at
;  http://www.erols.com/johnfine/
;_____________________________________________________________________________
;
; III)  Detailed features and limits
;
;   Most of the limits are stable characteristics of the volume.  If you are
; using boot12 in a personal project, you should check the limits before
; installing boot12.  If you are using boot12 in a project for general
; distribution, you should include an installation program which checks the
; limits automatically.
;
; CPU:  Supports any 8088+ CPU.
;
; Volume format:  Supports only FAT12.
;
; Sector size:  Supports only 512 bytes per sector.
;
; Drive/Partition:  Supports whole drive or any partition of any drive number
; supported by INT 13h.
;
; Diskette parameter table:  This code does not patch the diskette parameter
; table.  If you boot this code from a diskette that has more sectors per
; track than the default initialized by the BIOS then the failure to patch
; that table may be a problem.  Because this code splits at track boundaries
; a diskette with fewer sectors per track should not be a problem.
;
; File position:  The file name may be anywhere in the root directory and the
; file may be any collection of clusters on the volume.  There are no
; contiguity requirements.  (But see track limit).
;
; Track boundaries:  Transfers are split on track boundaries.  Many BIOS's
; require that the caller split floppy transfers on track boundaries.
;
; 64Kb boundaries:  Transfers are split on 64Kb boundaries.  Many BIOS's
; require that the caller split floppy transfers on track boundaries.
;
; Cluster boundaries:  Transfers are merged across cluster boundaries whenever
; possible.  On some systems, this significantly reduces load time.
;
; Cluster 2 limit:  Cluster 2 must start before sector 65536 of the volume.
; This is very likely because only the reserved sectors (usually 1) and
; the FAT's (two of up to 12 sectors each) and the root directory (usually
; either 15 or 32 sectors) precede cluster 2.
;
; Track limit:  The entire image file must reside before track 32768 of the
; entire volume.  This is true on most media up to 1GB in size.  If it is a
; problem it is easy to fix (see boot16.asm).  I didn't expect many people
; to put FAT12 partitions beyond the first GB of a large hard drive.
;
; Memory boundaries:  The FAT, Root directory, and Image must all be loaded
; starting at addresses that are multiples of 512 bytes (32 paragraphs).
;
; Memory use:  The FAT and Root directory must each fit entirely in the
; first 64Kb of RAM.  They may overlap.
;
; Root directory size:  As released, it supports up to 928 entries in the
; root directory.  If ROOT_SEG were changed to 0x7E0 it would support up
; to 1040.  Most FAT12 volumes have either 240 or 512 root directory
; entries.
;_____________________________________________________________________________
;
; IV)   Customization
;
;   The memory usage can be customized by changing the _SEG variables (see
; directly below).
;
;   The file name to be loaded and the message displayed in case of error
; may be customized (see end of this file).
;
;   The ouput values may be customized.  For example, many loaders expect the
; bootsector to leave the drive number in DL.  You could add "mov dl,[drive]"
; at the label "eof:".
;
;   Some limits (like maximum track) may be removed.  See boot16.asm for
; comparison.
;
;   Change whatever else you like.  The above are just likely possibilities.
;_____________________________________________________________________________


; Change the _SEG values to customize memory use during the boot.
; When planning memory use, remember:
;
; *)  Each of ROOT_SEG, FAT_SEG, and IMAGE_SEG must be divisible by 0x20
;
; *)  None of ROOT, FAT or IMAGE should overlap the boot code itself, or
;     its stack.  That means: avoid paragraphs 0x7B0 to 0x7DF.
;
; *)  The FAT area must not overlap the IMAGE area.  Either may overlap
;     the ROOT area;  But, if they do then the root will not remain in
;     memory for possible reuse by the next stage.
;
; *)  The FAT area and the root area must each fit within the first 64Kb
;     excluding BIOS area (paragraphs 0x60 to 0xFFF).
;
; *)  A FAT12 FAT can be up to 6Kb (0x180 paragraphs).
;
; *)  A FAT12 root directory is typically either 0x1E0 or 0x400 paragraphs
;     long, but larger sizes are possible.
;
; *)  The code will be two bytes shorter when FAT_SEG is 0x800 than when it
;     is another value.  (If you reach the point of caring about two bytes).
;
%define ROOT_SEG 0x60
%define FAT_SEG  0x800
%define IMAGE_SEG 0x1000

%if ROOT_SEG & 31
  %error "ROOT_SEG must be divisible by 0x20"
%endif
%if ROOT_SEG > 0xC00
  %error "Root directory must fit within first 64Kb"
%endif
%if FAT_SEG & 31
  %error "FAT_SEG must be divisible by 0x20"
%endif
%if FAT_SEG > 0xE80
  %error "FAT must fit within first 64Kb"
%endif
%if IMAGE_SEG & 31
  %error "IMAGE_SEG must be divisible by 0x20"
%endif

; The following %define directives declare the parts of the FAT12 "DOS BOOT
; RECORD" that are used by this code, based on BP being set to 7C00.
;
%define sc_p_clu bp+0Dh  ;byte  Sectors per cluster
%define sc_b4_fat bp+0Eh  ;word  Sectors (in partition) before FAT
%define fats  bp+10h  ;byte  Number of FATs
%define dir_ent  bp+11h  ;word  Number of root directory entries
%define sc_p_fat bp+16h  ;word  Sectors per FAT
%define sc_p_trk bp+18h  ;word  Sectors per track
%define heads  bp+1Ah  ;word  Number of heads
%define sc_b4_prt bp+1Ch  ;dword Sectors before partition
%define drive  bp+24h  ;byte  Drive number

 org 0x7C00

entry:
 jmp short begin

; --------------------------------------------------
; data portion of the "DOS BOOT RECORD"
; ----------------------------------------------------------------------
brINT13Flag     DB      90H             ; 0002h - 0EH for INT13 AH=42 READ
brOEM           DB      'MSDOS5.0'      ; 0003h - OEM ID - Windows 95B
brBPS           DW      512             ; 000Bh - Bytes per sector
brSPC           DB      1               ; 000Dh - Sector per cluster
brSc_b4_fat DW      1               ; 000Eh - Reserved sectors
brFATs          DB      2               ; 0010h - FAT copies
brRootEntries   DW      0E0H  ; 0011h - Root directory entries
brSectorCount   DW      2880  ; 0013h - Sectors in volume, < 32MB
brMedia         DB      240  ; 0015h - Media descriptor
brSPF           DW      9               ; 0016h - Sectors per FAT
brSc_p_trk DW      18              ; 0018h - Sectors per head/track
brHPC           DW      2  ; 001Ah - Heads per cylinder
brSc_b4_prt DD      0               ; 001Ch - Hidden sectors
brSectors       DD      0         ; 0020h - Total number of sectors
brDrive  DB      0               ; 0024h - Physical drive no.
  DB      0               ; 0025h - Reserved (FAT32)
  DB      29H             ; 0026h - Extended boot record sig (FAT32)
brSerialNum     DD      404418EAH       ; 0027h - Volume serial number
brLabel         DB      'Joels disk '   ; 002Bh - Volume label
brFSID          DB      'FAT12   '      ; 0036h - File System ID
;------------------------------------------------------------------------


begin:
 xor ax, ax
 mov ds, ax
 mov ss, ax
 mov sp, 0x7C00
 mov bp, sp
 mov [drive], dl ;Drive number

 mov al, [fats] ;Number of FATs
 mul word [sc_p_fat] ; * Sectors per FAT
 add ax, [sc_b4_fat] ; + Sectors before FAT
    ;AX = Sector of Root directory

 mov si, [dir_ent] ;Max root directory entries
 mov cl, 4
 dec si
 shr si, cl
 inc si  ;SI = Length of root in sectors

 mov di, ROOT_SEG/32 ;Buffer (paragraph / 32)
 call read_16  ;Read root directory
 push ax  ;Sector of cluster two
%define sc_clu2 bp-2  ;Later access to the word just pushed is via bp

 mov dx, [dir_ent] ;Number of directory entries
 push ds
 pop es
 mov di, ROOT_SEG*16

search:
 dec dx  ;Any more directory entries?
 js error  ;No
 mov si, filename ;Name we are searching for
 mov cx, 11  ;11 characters long
 lea ax, [di+0x20] ;Precompute next entry address
 push ax
 repe cmpsb  ;Compare
 pop di
 jnz search  ;Repeat until match

 push word [di-6] ;Starting cluster number

 mov ax, [sc_b4_fat] ;Sector number of FAT
 mov si, [sc_p_fat] ;Length of FAT
 mov di, FAT_SEG/32 ;Buffer (paragraph / 32)
 call read_16  ;Read FAT

next:
 pop bx  ;Cluster number
 mov si, bx  ;First cluster in this sequence
 mov ax, bx  ;Last cluster in this sequence

.0:
 cmp bx, 0xFF8 ;End of file?
 jae .2  ; Yes
 inc ax  ;Last cluster plus one in sequence

 ;Look in FAT for next cluster
 mov di, bx  ;Cluster number
 rcr bx, 1  ;1.5 byte entry per cluster
    ;bx = 0x8000 + cluster/2
    ;c-bit set for odd clusters

 mov bx, [bx+di+FAT_SEG*16-0x8000]
 jnc .1
 shr bx, 1
 shr bx, 1
 shr bx, 1
 shr bx, 1
.1: and bh, 0xF

 cmp ax, bx  ;Is the next one contiguous?
 je .0  ;Yes: look further ahead
.2: sub ax, si  ;How many contiguous in this sequence?
 jz eof  ;None, must be done.

 push bx  ;Save next (eof or discontiguous) cluster
 
 mov bl, [sc_p_clu] ;Sectors per cluster
 mov bh, 0  ;  as a word
 mul bx  ;Length of sequence in sectors
.3: mov di, IMAGE_SEG/32 ;Destination (paragraph / 32)
 add [.3+1], ax  ;Precompute next destination
 xchg ax, si  ;AX = starting cluster ;SI = length in sectors
 dec ax
 dec ax  ;Starting cluster minus two
 mul bx  ; * sectors per cluster
 add ax, [sc_clu2] ; + sector number of cluster two
 adc dl, dh  ;Allow 24-bit result

 call read_32  ;Read it
 jmp short next ;Look for more

eof:
 jmp IMAGE_SEG:0

error: mov si, errmsg ;Same message for all detected errors
 mov ax, 0xE0D ;Start message with CR
 mov bx, 7
.1: int 10h
 lodsb
 test al, al
 jnz .1
 xor ah, ah
 int 16h  ;Wait for a key
 int 19h  ;Try to reboot

read_16:
 xor dx, dx

read_32:
;
; Input:
;    dx:ax = sector within partition
;    si    = sector count
;    di    = destination segment / 32
;
; The sector number is converted from a partition-relative to a whole-disk
; (LBN) value, and then converted to CHS form, and then the sectors are read
; into (di*32):0.
;
; Output:
;    dx:ax  updated (sector count added)
;    di     updated (sector count added)
;    si = 0
;    bp, ds preserved
;    bx, cx, es modified

.1: push dx   ;(high) relative sector
 push ax   ;(low) relative sector

 add ax, [sc_b4_prt]  ;Convert to LBN
 adc dx, [sc_b4_prt+2]

 mov bx, [sc_p_trk]  ;Sectors per track
 div bx   ;AX = track ;DX = sector-1
 sub bx, dx   ;Sectors remaining, this track
 cmp bx, si   ;More than we want?
 jbe .2   ;No
 mov bx, si   ;Yes: Transfer just what we want
.2: inc dx   ;Sector number
 mov cx, dx   ;CL = sector ;CH = 0
 cwd    ;(This supports up to 32767 tracks
 div word [heads]  ;Track number / Number of heads
 mov dh, dl   ;DH = head

 xchg ch, al   ;CH = (low) cylinder  ;AL=0
 ror ah, 1   ;rotate (high) cylinder
 ror ah, 1
 add cl, ah   ;CL = combine: sector, (high) cylinder

 sub ax, di
 and ax, byte 0x7F  ;AX = sectors to next 64Kb boundary
 jz .3   ;On a 64Kb boundary already
 cmp ax, bx   ;More than we want?
 jbe .4   ;No
.3: xchg ax, bx   ;Yes: Transfer just what we want
.4: push ax   ;Save length
 mov bx, di   ;Compute destination seg
 push cx
 mov cl, 5
 shl bx, cl
 pop cx
 mov es, bx
 xor bx, bx   ;ES:BX = address
 mov dl, [drive]  ;DL = Drive number
 mov ah, 2   ;AH = Read command
 int 13h   ;Do it
 jc error
 pop bx   ;Length
 pop ax   ;(low) relative sector
 pop dx   ;(high) relative sector
 add ax, bx   ;Update relative sector
 adc dl, dh
 add di, bx   ;Update destination
 sub si, bx   ;Update count
 jnz .1   ;Read some more
 ret

errmsg db 10,"Error Executing FAT12 bootsector",13
 db 10,"Press any key to reboot",13,10,0

size equ $ - entry
%if size+11+2 > 512
  %error "code is too large for boot sector"
%endif
 times (512 - size - 11 - 2) db 0

filename db "LOADER  BIN"  ;11 byte name
 db 0x55, 0xAA  ;2  byte boot signature

There are many user-adjustable settings in John Fine’s bootstrap loader. His loader assumes the use of a FAT12 file system (the system that is used on floppy disks). For another system, you will need to use a different loader. Things you can adjust are the locations where the operating system and various FAT data structures will be loaded into memory. You can also adjust the filename (of the operating system) that the loader loads.

By default, the loader loads a file named LOADER.BIN in the root directory (if one exists) into memory starting at address 0x1000:0000. (This is adjustable by the %define IMAGE_SEG). Thus you can compile/assemble an operating system and copy it to the floppy disk as a file named LOADER.BIN.

As an example, we will take the Hello, World operating system from Lesson 4 and run it with our boot loader. We cannot use the exact same source file from Lesson 4, however. We need to make a few changes. First, we need to take into account that this file will now be loaded into a different location in memory (0x1000:0000 instead of 0000:7C00), and, secondly, we can get rid of the DOS Boot Record data.

We can start the code by setting up the data and stack segments and the stack pointer. We will do this as shown below. The current code segment is in the CS register, and the static data assembled into the executable is here, so we will use this as the data segment as well. For now, we will use this as the stack segment, but we will likely want to change this in the future.

mov    ax, cs      ; Get the current segment
mov    ds, ax      ; The data is in this segment
cli                ; disable interrupts while changing stack
mov    ss, ax      ; We'll use this segment for the stack too
mov    sp, 0xfffe  ; Start the stack at the top of the segment
sti                ; Reenable interrupts

Finally, we can get rid of some lines at the bottom of the source code that adds the boot sector signature and the check to make sure the file is exactly 1 sector long. All of the other code should look familiar. The resulting file is as follows.

;----------------------------------------------------------------------
; Hello World Operating System
;
; Joel Gompert 2001
;
; Disclaimer: I am not responsible for any results of the use of the contents
;   of this file
;----------------------------------------------------------------------

; --------------------------------------------
;  Here is the operating system entry point
; --------------------------------------------
begin:
 mov ax, cs  ; Get the current segment
 mov ds, ax  ; The data is in this segment
 cli   ; disable interrupts while changing stack
 mov ss, ax  ; We'll use this segment for the stack too
 mov sp, 0xfffe ; Start the stack at the top of the segment
 sti   ; Reenable interrupts

 mov si, msg  ; load address of our message
 call putstr  ; print the message

hang:
 jmp hang  ; just loop forever.

; --------------------------------------------
; data for our program

msg db 'Hello, World!', 0

; ---------------------------------------------
; Print a null-terminated string on the screen
; ---------------------------------------------
putstr:
 lodsb  ; AL = [DS:SI]
 or al, al ; Set zero flag if al=0
 jz putstrd ; jump to putstrd if zero flag is set
 mov ah, 0x0e ; video function 0Eh (print char)
 mov bx, 0x0007 ; color
 int 0x10
 jmp putstr
putstrd:
 retn

Assemble this file and copy it to your disk using the following commands.

nasmw lesson6.asm –o lesson6.bin
copy lesson6.bin a:\LOADER.BIN

Then, assuming you have already installed the boot loader, you can go ahead and boot with the disk. Once you have this working, feel free to modify any other programs you have written in previous lessons, so that you can try loading them with this boot loader. Most of the following lessons will assume that you will be using this boot loader (or other boot loader of your choice) to load your operating system file(s).

Now we can make our operating system larger than a single sector.

Previous lesson     Table of Contents     Next lesson