NOTES ON ASSEMBLY LANGUAGE FOR THE PENTIUM 4-24-1999 1. For some reason, the turbo debugger (TD) will not work on an int 31h instruction. I get a program error when running DPMITEST. (I think you use TD32.) 2. DPMITEST works stand alone. I had to change an out of range jump. 2A. DPMITEST is a sample program from chapter 16 of Master Class Assembly Language. It is a skeleton which shows how to switch to protected mode and use large memory segments. 3. You can switch to 32 bit protected mode. In this mode 32 bit registers are assumed. It is EAX, not AX. 4. The protected mode call address is given back to you in ES:DI when you do an int 2Fh with AX = 1687h. This is a segment and offset since you are still in 16 bit mode at this time. Call that address, and you will switch from real to protected mode. 4A. To switch to 32 bit protected mode, set AH to 1 before calling to protected mode call address. To switch to 16 bit proteced mode, set AH to 0 before the call. 5. When you switch to 32 bit protected mode, you do it in execution with the call to the proteced mode gate. You need to inform the assembler to use 32 bit registers as the default. Call a proc in a 32 bit segment right after the switch from real to protected mode. This way the assembler and the cpu will be in synch. The 32 bit proc is your proteced mode program. (Previous version of these notes had an error.) .286 and .386 actually restrict the instructions which are allowed. These directives do not change the way instructions are assembled. They just give an error message if you code an instruction which is for a more advanced machine. 5A. At the top of the program, you need to have a .286 assembler directive so the assember will only allow 16 bit instructions. You also need a .286 directive before any 16 bit subroutines. 6. Remember, the processor uses the instruction prefix 66h to execute an instruction in the opposite mode. If you are in 16 bit mode, 66h prefix causes the cpu to execute the instruction in 32 bit mode. 32 bit registers are used. An instruction that uses AX will not have the prefix. An instruction that uses EAX will have the prefix. 6A. In 32 bit mode, the 66h prefix causes the instruction to execute in 16 bit mode. AX is used, not EAX. 6B. Instructions in a 16 bit code segment are assembled in 16 bit mode. An instruction using AX has no prefix. An instruction using EAX has a prefix. 6C. Instructions in a 32 bit code segment are assembled in 32 bit mode. An instruction using AX has a prefix. An instruction using EAX has no prefix. 6D. 16 bit mode is called real mode. 32 bit mode is called protected mode. Memory segments are protected from invalid access in 32 bit mode. 7. Some code sequences are not dependent on cpu mode. They will execute correctly no matter what. Notable examples are the exit code. This code sequence: mov ax,4C00h int 21h terminates a DOS program with a return code of zero. AX will have the correct value regardless if EAX is set, or AX is set. 7A. The printing sequence for a $ terminated string: mov ah,9 int 21h will work regardless of mode. mov ah,9 is an 8 bit instruction. It assembles the same and executes the same in both 16 bit and 32 bit mode. 7B. The traditional DOS functions used with int 21h all work, no matter what mode you are in. Int 21h works in real or pretected mode, 16 bit or 32 bit mode. DOS seems to know what mode you are in an execute correctly. You can read and write from files, and print strings just like always. 7C. Even in protected mode, with selectors instead of segment registers, DOS gets addressing right. DS:DX for printing a string uses DS as a selector in protected mode. 8. In protected mode, segment registers are called selectors. The selector selects an 8 byte entry in a descriptor table. Each 8 byte descriptor entry describes a block of memory called a segment. They are big segments, as large as 32 bits can address, up to 4 gigabytes. 8A. In order to speed things up, the cpu keeps the current 8 byte descriptor in special cpu registers. These special registers are loaded when a selector register is loaded. So you must always load a valid value into each selector register. If you have no valid value, and you wish to put a value in a selector register, use zero. 0000h is an valid selector value which means no selector. You cannot use the first descriptor (address 0) as a result of this feature. 8C. When you switch to protected mode, CS will be the selector for your code segment descriptor. DS will be the selector for your data segment. ES will be the selector for your PSP. FS and GS will be zero. 8D. A PSP is the program segment prefix. That is the 256 byte block at the beginning when a .COM file is loaded. The PSP is a seperate segment in an .EXE file. 8E. The PSP has the command tail as the right half for 128 bytes. The command tail is the text that you type next to the program name when you run the program. You can pass arguements to an assembly program. This can be file names, or numbers, or switches, or nothing, or anything you want. 9. There are two descriptor tables. There is the global descriptor table or GDT. There is only one GDT. And there is the local descriptor table or LDT. There may be more than one LDT. 9A. In DPMI version 0.9 there is an LDT for each virtual machine. Windows is a virtual machine. When you are in a DOS box, DOS is a virtual machine. You make a DOS box by choosing an MSDOS prompt from windows. 9C. Since DOS has its own LDT, the assembly language programmer does not have to create one. You just use the LDT which is there. You ask DPMI to create the LDT entry for you in the existing table. 9D. DPMI is accessed with int 2fh and int 31h. 9E. It is necessary, however to have an 8 byte descriptor layout in your program. You have to tell DPMI what 8 bytes you want to put in the LDT. 10. When you ask DPMI for available memory when running a DOS program, you get all of memory, less 1 meg. It looks like windows is paged out, and you DOS application has access to all available RAM ! 11. The best book on protected mode programming I have seen is: Master Class Assembly Language by multiple authors from Wrox press. It cost $45 at Josepth Beth Booksellers. 11A. A good intro to protected mode programming with a lot of random pieces of information is: Windows and Assembly Language Programming by Barry Kuhler It cost $38 plus shipping at amazon.com Barry's book has a few little pieces of information which were not elsewhere. He makes several little details very clear, but I never got the big picture, or was able to write a working program, even with examples. 11B. You can get a set of 3 free books by calling INTEL's 800 number. Get the three volume set: The pentium cpu reference. The instruciton set reference. The pentium software programmer's reference. 11C. Whizkid on the internet has a bunch of really good examples of windows programming. 11D. You can find out about the extra registers: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP most anywhere. 12. Note that the method for protected mode programming on the 286 has all sorts of stuff not needed on a pentium. It is only necessary to fool with address line 20 on a 286, and not on a pentium. 13. Software wise, there is little difference between a 386, 486, or a pentium. The newer chips are just faster. There are a few instructions in the more advanced chips. 14. This is my opinion. Trying to optamize assembly language for a given cpu is pointless. With a new generation of cpu every 2 years or so, the program you write will not be run on the cpu you have now. Just use the fewest instructions possible. Trying to pair instructions for a pentium's two instruction pipes is a waste of time. The pentium pro has three pipes and out of order execution. Let the cpu do the work. You worry about the algorythm and writing bug free code. The new cpu generation will just be faster. Don Ader zipfast@mis.net