DnA 6-7: x86 Assembly Language Tutorial [2/?] by Horsepowr
This article is the second in a series of documents of which aim to teach the novice, or experienced high-level language programmer x86 assembly language. The previous article covered hexidecimal notation of binary numerics and the representative decimal equivalents. This is a topic that is necessary to wholly comprehend to procede further in this tutorial. If you do not grasp the concept of hexadecimal notation, please read my previous article, or obtain some other instruction on this topic. This passage will cover the registers of the 8086/8088 microprocessor. The 80186, 80286, 80386, 80486, and P5 based machines are all downwardly compatible with the 8086's architecture. There are many advanced and extended registers on these higher level microprocessors, which we'll get into as the topic progresses to 80386 protected mode programming.
The 8086 is a 16 bit processor, designed to operate on a 16 bit bus. The only factor that separates the 8086 and the 8088 microprocessors are the bus widths, as the 8088 is intended for an 8 bit bus. To the programmer, they are identical, much as the 80386DX and 80386SX are. They only differ at the hardware level, which is taken care of by the controllers built in to the motherboard and the processor itself, and are not accessible to the programmer. All microprocessors have registers, which are areas within the microprocessor which handle data, and can be directly addressed and accessed by the programmer to give the processor data with which to calculate or manipulate, or for the processor to return resultant values for the program to handle. Think of a register as the processor's "hands". You must put data into the processor's "hands" for it to do anything with, and after it is done it "hands" it back to the programmer. With a human being, hands are very versatile, not so with a microprocessor. Many registers have specific purposes, and while some may be used for generic duties as well, some do not allow you to alter or access them without going through a great deal of effort, and others require a specific register to perform a duty, and no other register may be substituted.
There are 4 general purpose registers on the 8086, which can be used for basic instructions that do not require data to be placed in a specific register. These are the Accumulator register (AX), Base register (BX), Count register (CX), and Data register (DX). The AX, BX, CX, and DX registers are all 16 bits large, and can be given 16 bits as a whole by indicating their full name (AX, BX, CX, and DX) or can be given 8 bit items of data by splitting them up into high and low registers (AH/AL, BH/BL, CH/CL, DH/DL). For example, lets say you want to pass the number 0A724h as a parameter. Since this is a 16 bit number, you would want to put it as a whole into the AX register, but you could also insert 0A7h into AH and 24h into AL to achieve the same result. If you only need to pass an 8 bit number you can use only a high or low register, for example, if the parameter was only 0F2h, then you could fit the entire number into the AL register to save the AH register for later use. Registers are your most powerful tools when programming, as the data in a register is already in the processor, it doesn't have to travel along the slow bus as when dealing with data in memory. If you can perform an entire calculation strictly within the registers, the difference in speed between that approach and one which access memory only once or twice is often more than tenfold. This direct access to the registers is one of the most powerful benefits of programming in assembly language. One thing to remember about splitting up the 16 bit general registers is the fact that unless you physically put zeros into the adjacent register (i.e. AH-AL) the twin register contains relevant data. This can cause concern when a procedure is expecting data in the full AX register, and since the number you have to pass is only 8 bits, you put it in the AL register. If you fail to clear out the AH register, it will contain data and will not pass your intended 8 bit number, instead you will get a garbage 16 bit number that will wreak havok with your program. For example, Procedure XYZ is expecting a value in the CX register. Since your parameter is 72h, you place it in the CL register, unbeknownst to you that the CX register contained 0FF23h before, the CX register will now contain 0FF72h, as you only modified CL, not CH, so CH remains the same.
The other Registers are more specific in purpose, and do not share the ability to be split into separate halves like the general registers. They are split up into sections: Index registers, Segment registers, Pointer registers, Index registers, and Control registers. All of these registers are 16 bits wide on the 8086, some of which are expanded to 32 or 64 bits on later processors. The Index registers are the Stack Index register (SI) and the Data Index register (DI). These registers are used to provide a means for offsetting (adding to a constant) an address (base address, the constant). The Segment registers contain the address of the current segments (up to 64k blocks of memory) in use by the processor. The segment registers consist of the Code Segment register (CS - contains the base address of the current segment of code being executed by the processor), Stack Segment register (SS - contains the base address of the Stack in use), Data Segment register (DS - contains the base address of the current segment of main data), and the Extra Segment register (ES - contains the base address of the secondary data segment). The pointer registers are typically used as placeholders within the stack but may be used for other purposes, they are made up of the Base Pointer register (BP) and the Stack Pointer register (SP). Finally there remains the the Control registers. They are the Flags register (FLAGS) and the Instruction Pointer register (IP - It contains the offset within the code segment of the next instruction for the processor to execute. It is not used in the same manner as the other pointer registers so it is classified as a control register because it cannot be modified directly and cannot be used for an alternate use). The Flags register contains a bitfield of status indicators which are:
more>>>>
_________________________________________________________________________________
| | | | | | | | | | | | | | | | |
| xx | xx | xx | xx | OF | DF | IF | TF | SF | ZF | xx | AF | xx | PF | xx | CF |
| | | | | | | | | | | | | | | | |
---------------------------------------------------------------------------------
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
xx- denotes flag bits reserved for later use by Intel, some of which
have been implemented on the 80186-80486.
The value of the flag bits indicate a condition or state of the processor, or signal a result of an operation. They are used by comparison and string operations which will be explained in later issues. The full names for the flags, in ascending bit order (Least significant bit (LSB) -> Most significant bit (MSB) ) are: Carry flag (Indicates a math operation generated a carry), Parity flag (Contains the parity of an instruction), Auxiliary flag (Used with decimal arithmetic operations), Zero flag (Set when the result of a previous instruction equated to zero), Sign flag (Indicates a negative result), Trap flag (Used in debugging work), Interrupt Enable flag (Allows or disallows maskable interrupts), Direction flag (Sets the direction of order for string operations), and the Overflow flag (Indicates the result of an operation was to large to fit in the specified destination register).
Now that you are completely confused with all of the information you're probably feeling is irrelevant, we come to the end of this article. Readers of the first article will note I promised to discuss the use of memory on the x86 platform, but I have now realized that this topic is an article within itself, so that will be the subject of my next article. Stay tuned! If you have any questions, feel free to channel any feedback, requests, hate mail, or whatever through DnA, or direct to me at my system:
The Finish Line (714) 572-8696 ZyXEL 16.8 / v.32bis
Hasta -HP ---tURB@---