ECP4166: Advanced Microprocessors AM2 Page 1 of 14 AM2: Protected-Mode Programming Duration: 3 hours Components: Lab exercises and report. Objectives: (a) To examine how protected-mode programming is done on x86 based computer. (b) To evaluate the advantages of protected-mode programming compared to real-mode programming in x86 microprocessor. (c) To develop protected-mode assembly language programs which utilize the floating- point unit (FPU) on x86 based computer. (d) To develop Win32 Console programs based on x86 assembly language. 1. Floating-Point Unit The Intel 8086 processor was designed to handle only integer arithmetic. This turned out to be a problem for graphics and calculation-intensive software using floating-point calculations. It was possible to emulate floating-point arithmetic purely through software, but the performance penalty was severe. Programs such as AutoCad (by Autodesk) demanded a more powerful way to perform floating-point math. Intel sold a separate floating-point coprocessor chip named the 8087, and upgraded it along with each processor generation. Beginning from Intel 80486, the floating-point hardware was integrated into the processor and known as the floating-point unit (FPU). 1.1 FPU Register Stack The FPU does not use the general-purpose registers (EAX, EBX, etc.). Instead, it has its own set of registers called a register stack. It loads values from memory into the register stack, performs calculations, and stores stack values into memory. FPU instructions evaluate mathematical expressions in postfix format. The following, for example, is called an infix expression: (5 * 6) + 4. The postfix equivalent is 5 6 * 4 + The infix expression (A + B) * C requires parenthesis to override the default precedence rules (multiplication before addition). The parenthesis is not required in the equivalent postfix expression: A B + C * 1.1.1 Expression Stack A stack holds intermediate values during the evaluation of postfix expressions. Figure 1.1 shows the steps required to evaluate the postfix expression 5 6 * 4 –. The stack entries are labelled ST(0) and ST(1), with ST(0) indicating where the stack pointer would normally be pointing.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
ECP4166: Advanced Microprocessors AM2
Page 1 of 14
AM2: Protected-Mode Programming
Duration: 3 hours
Components: Lab exercises and report.
Objectives: (a) To examine how protected-mode programming is done on x86 based computer.
(b) To evaluate the advantages of protected-mode programming compared to real-mode
programming in x86 microprocessor.
(c) To develop protected-mode assembly language programs which utilize the floating-
point unit (FPU) on x86 based computer.
(d) To develop Win32 Console programs based on x86 assembly language.
1. Floating-Point Unit The Intel 8086 processor was designed to handle only integer arithmetic. This turned out to
be a problem for graphics and calculation-intensive software using floating-point calculations.
It was possible to emulate floating-point arithmetic purely through software, but the
performance penalty was severe. Programs such as AutoCad (by Autodesk) demanded a more
powerful way to perform floating-point math. Intel sold a separate floating-point coprocessor
chip named the 8087, and upgraded it along with each processor generation. Beginning from
Intel 80486, the floating-point hardware was integrated into the processor and known as the
floating-point unit (FPU).
1.1 FPU Register Stack The FPU does not use the general-purpose registers (EAX, EBX, etc.). Instead, it has its own
set of registers called a register stack. It loads values from memory into the register stack,
performs calculations, and stores stack values into memory. FPU instructions evaluate
mathematical expressions in postfix format. The following, for example, is called an infix
expression: (5 * 6) + 4. The postfix equivalent is
5 6 * 4 +
The infix expression (A + B) * C requires parenthesis to override the default precedence
rules (multiplication before addition). The parenthesis is not required in the equivalent postfix
expression:
A B + C *
1.1.1 Expression Stack A stack holds intermediate values during the evaluation of postfix expressions. Figure 1.1
shows the steps required to evaluate the postfix expression 5 6 * 4 –. The stack entries are
labelled ST(0) and ST(1), with ST(0) indicating where the stack pointer would normally be
Floating-point instruction names begin with the letter F to distinguish them from CPU
instructions. The second letter of the instruction mnemonic (often B or I) indicates how a
memory operand is to be interpreted: B indicates a BCD operand, and I indicates a binary
integer operand. If neither is specified, the memory operand is assumed to be in real-number
format. For example, FBLD operates on BCD numbers, FILD operates on integers, and FLD
operates on real numbers.
ECP4166: Advanced Microprocessors AM2
Page 4 of 14
1.3.1 Operands A floating-point instruction can have zero operands, one operand, or two operands. If there
are two operands, one must be a floating-point register. There are no immediate operands, but
certain predefined constants (such as 0.0, _and log2 10) can be loaded into the stack.
General-purpose registers such as EAX, EBX, ECX, and EDX cannot be operands. (The only
exception is FSTSW, which stores the FPU status word in AX.) Memory-to-memory
operations are not permitted. Integer operands must be loaded into the FPU from memory
(never from CPU registers); they are automatically converted to floating-point format.
Similarly, when storing floating-point values into integer memory operands, the values are
automatically truncated or rounded into integers.
1.3.2 Initialization (FINIT) The FINIT instruction initializes the FPU. It sets the FPU control word to 037Fh, which
masks (hides) all floating-point exceptions, sets rounding to nearest even, and sets the
calculation precision to 64 bits. We recommend calling FINIT at the beginning of your
programs, so you know the starting state of the processor.
1.3.3 Floating-Point Data Types Let’s quickly review the floating-point data types supported by MASM (QWORD, TBYTE,
REAL4, REAL8, and REAL10), listed in Table 1.2. You will need to use these types when
defining memory operands for FPU instructions. For example, when loading a floating-point
variable into the FPU stack, the variable is defined as REAL4, REAL8, or REAL10: .data bigVal REAL10 1.212342342234234243E+864 .code fld bigVal ; load variable into stack
Table 1.2: Intrinsic Data Types. Type Usage
QWORD 64-bit integer
TBYTE 80-bit (10-byte) integer
REAL4 32-bit (4-byte) IEEE short real
REAL8 64-bit (8-byte) IEEE long real
REAL10 80-bit (10-byte) IEEE extended real
1.3.4 Reading and Writing Floating-Point Values In this experiment, the following two procedures for floating-point input-output (created by
William Barrett of San Jose State University) are used:
ReadFloat: Reads a floating-point value from the keyboard and pushes it on the floating-
point stack. It accepts a wide variety of floating-point formats. Some examples
are shown below: 35 3.5E005
+35. -3.5E+5 -3.5 3.5E-4 .35 +3.5E-4 3.5E5
WriteFloat: Writes the floating-point value at ST(0) to the console window in exponential
format.
ShowFPUStack: Another useful procedure, written by James Brink of Pacific Lutheran
University, displays the FPU stack. It is called with no parameters: call ShowFPUStack
ECP4166: Advanced Microprocessors AM2
Page 5 of 14
Example 1.1 The following example program pushes two floating-point values on the FPU stack, displays
it, inputs two values from the user, multiplies them, and displays their product:
Note: Please refer to Appendix A on how to build and run this program.
Sample input/output (user input shown in bold type):
------ FPU Stack ------
ST(0): +1.0000000E+001
ST(1): +1.2345600E+002
Please enter a real number: 3.5
Please enter a real number: 4.2
Their product is: +1.4700000E+001
Example 1.2 Let’s code the expression valD = -valA + (valB * valC). A possible step-by-step solution is:
Load valA on the stack and negate it. Load valB into ST(0), moving valA down to ST(1).
Multiply ST(0) by valC, leaving the product in ST(0). Add ST(1) and ST(0) and store the
sum in valD:
ECP4166: Advanced Microprocessors AM2
Page 6 of 14
Please refer to Appendix B on how to debug this program.
Exercise 1.1 Write a program that prompts the user for the radius of a circle. Calculate and display the
circle’s circumference and area. Use the ReadFloat and WriteFloat procedures. Use the
FLDPI instruction to load onto the register stack. Please refer to Appendix A on how to
create, build and run your program.
Exercise 1.2 Write a program that asks the user to enter the X and Y coordinates of two points on a
straight line. Calculate and display the gradient of the straight line. Use the ReadFloat and
WriteFloat procedures in your program.
2. Win32 Console Programming On the surface, 32-bit console mode programs look and behave like 16-bit MS-DOS
programs running in text mode. There are differences, however: The former runs in 32-bit
protected mode, whereas MS-DOS programs run in real-address mode. They use different
function libraries. Win32 programs call functions from the same library used by graphical
Windows applications. MS-DOS programs use BIOS and MS-DOS interrupts that have
existed since the introduction of the IBM-PC.
2.1 Application Programming Interface An Application Programming Interface (API) is a collection of types, constants, and
functions that provide a way to directly manipulate objects through programming. Therefore,
the Win32 API lets you tap into the functions in the 32-bit version of MS-Windows. The
Irvine32 link library used in this experiment is completely built on Win32 console functions.
It is compatible with Win32 API functions and can be used for basic input output, simulations,
timing, and other useful operations. Table 2.1 gives a complete list of procedures in the
Irvine32 link library.
Table 2.1: Procedures in the Irvine32 link library Procedure Description
CloseFile Closes a disk file that was previously opened.
Clrscr Clears the console window and locates the cursor at the upper left corner.
CreateOutputFile Creates a new disk file for writing in output mode.
Crlf Writes an end-of-line sequence to the console window.
Delay Pauses the program execution for a specified n -millisecond interval.
DumpMem Writes a block of memory to the console window in hexadecimal.
DumpRegs Displays the EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EFLAGS, and EIP registers in hexadecimal. Also displays the most common CPU status flags.
GetCommandTail Copies the program’s command-line arguments (called the command tail) into an array of bytes.
ECP4166: Advanced Microprocessors AM2
Page 7 of 14
GetDateTime Gets the current date and time from the system.
GetMaxXY Gets the number of columns and rows in the console window’s buffer.
GetMseconds Returns the number of milliseconds elapsed since midnight.
GetTextColor Returns the active foreground and background text colors in the console window.
Gotoxy Locates the cursor at a specific row and column in the console window.
IsDigit Sets the Zero flag if the AL register contains the ASCII code for a decimal digit (0–9).
MsgBox Displays a popup message box.
MsgBoxAsk Display a yes/no question in a popup message box.
OpenInputFile Opens an existing disk file for input.
ParseDecimal32 Converts an unsigned decimal integer string to 32-bit binary.
ParseInteger32 Converts a signed decimal integer string to 32-bit binary.
Random32 Generates a 32-bit pseudorandom integer in the range 0 to FFFFFFFFh.
Randomize Seeds the random number generator with a unique value.
RandomRange Generates a pseudorandom integer within a specified range.
ReadChar Waits for a single character to be typed at the keyboard and returns the character.
ReadDec Reads an unsigned 32-bit decimal integer from the keyboard, terminated by the Enter key.
ReadFromFile Reads an input disk file into a buffer.
ReadHex Reads a 32-bit hexadecimal integer from the keyboard, terminated by the Enter key.
ReadInt Reads a 32-bit signed decimal integer from the keyboard, terminated by the Enter key.
ReadKey Reads a character from the keyboard’s input buffer without waiting for input.
ReadString Reads a string from the keyboard, terminated by the Enter key.
SetTextColor Sets the foreground and background colors of all subsequent text output to the console.
Str_compare Compares two strings.
Str_copy Copies a source string to a destination string.
Str_length Returns the length of a string in EAX.
Str_trim Removes unwanted characters from a string.
Str_ucase Converts a string to uppercase letters.
WaitMsg Displays a message and waits for a key to be pressed.
WriteBin Writes an unsigned 32-bit integer to the console window in ASCII binary format.
WriteBinB Writes a binary integer to the console window in byte, word, or doubleword format.
WriteChar Writes a single character to the console window.
WriteDec Writes an unsigned 32-bit integer to the console window in decimal format.
WriteHex Writes a 32-bit integer to the console window in hexadecimal format.
WriteHexB Writes a byte, word, or doubleword integer to the console window in hexadecimal format
WriteInt Writes a signed 32-bit integer to the console window in decimal format.
WriteStackFrame Writes the current procedure’s stack frame to the console.
WriteStackFrameName Writes the current procedure’s name and stack frame to the console.
WriteString Writes a null-terminated string to the console window.
WriteToFile Writes a buffer to an output file. WriteWindowsMsg Displays a string containing the most recent error generated by MS-
Windows.
ECP4166: Advanced Microprocessors AM2
Page 8 of 14
Some of the procedures that are used in this experiment are described in the following
sections.
2.1.1 MsgBox The MsgBox procedure displays a graphical popup message box with an optional caption.
(This works when the program is running in a console window.) Pass it the offset of a string
in EDX, which will appear in the inside the box. Optionally, pass the offset of a string for the
box’s title in EBX. To leave the title blank, set EBX to zero. Sample call: .data caption db "Dialog Title", 0 HelloMsg BYTE "This is a pop-up message box.", 0dh,0ah
BYTE "Click OK to continue...", 0 .code mov ebx,OFFSET caption mov edx,OFFSET HelloMsg call MsgBox
Sample output:
2.1.2 MsgBoxAsk The MsgBoxAsk procedure displays a graphical popup message box with Yes and No
buttons. (This works when the program is running in a console window.) Pass it the offset of
a question string in EDX, which will appear in the inside the box. Optionally, pass the offset
of a string for the box’s title in EBX. To leave the title blank, set EBX to zero. MsgBoxAsk
returns an integer in EAX that tells you which button was selected by the user. The value will
be one of two predefined Windows constants: IDYES (equal to 6) or IDNO (equal to 7).
Sample call: .data caption BYTE "Survey Completed",0 question BYTE "Thank you for completing the survey."
BYTE 0dh,0ah BYTE "Would you like to receive the results?",0
.code mov ebx,OFFSET caption mov edx,OFFSET question call MsgBoxAsk ;(check return value in EAX)
ECP4166: Advanced Microprocessors AM2
Page 9 of 14
Sample output:
2.1.3 ReadString The ReadString procedure reads a string from the keyboard, stopping when the user presses
the Enter key. Pass the offset of a buffer in EDX and set ECX to the maximum number of
characters the user can enter, plus 1 (to save space for the terminating null byte). The
procedure returns the count of the number of characters typed by the user in EAX. Sample call: .data buffer BYTE 21 DUP(0) ; input buffer byteCount DWORD ? ; holds counter .code mov edx,OFFSET buffer ; point to the buffer mov ecx,SIZEOF buffer ; specify max characters call ReadString ; input the string mov byteCount,eax ; number of characters
ReadString automatically inserts a null terminator in memory at the end of the string. The
following is a hexadecimal and ASCII dump of the first 8 bytes of buffer after the user has
entered the string “ABCDEFG”:
41 42 43 44 45 46 47 00 ABCDEFG
The variable byteCount equals 7.
2.1.4 WriteString The WriteString procedure writes a null-terminated string to the console window. Pass the
string’s offset in EDX. Sample call: .data prompt BYTE "Enter your name: ",0 .code mov edx,OFFSET prompt call WriteString
2.1.5 WriteDec The WriteDec procedure writes a 32-bit unsigned integer to the console window in decimal
format with no leading zeros. Pass the integer in EAX. Sample call: mov eax,295 call WriteDec ; displays: "295"
2.1.6 WriteToFile The WriteToFile procedure writes the contents of a buffer to an output file. Pass it a valid file
handle in EAX, the offset of the buffer in EDX, and the number of bytes to write in ECX.
When the procedure returns, if EAX is greater than zero, it contains a count of the number of
bytes written; otherwise, an error occurred. The following code calls WriteToFile: