Optimization

Once your program is running in protected mode, it is time to unravel some of the changes made for purposes of conversion and to introduce various optimizations. Three obvious categories should be considered:

1. Modifying the program's user-interface code for the more powerful OS/2 keyboard and display API functions.

1.Incorporating 80286-specific machine instructions where appropriate.

2.Revamping the application to exploit the OS/2 facilities that are unique to protected mode. (Of course, the application benefits from OS/2's virtual memory capabilities automatically; it can allocate memory until physical memory and disk swapping space are exhausted.)

Modifying subroutines that encapsulate user input and output to take advantage of the additional functionality available under OS/2 is straight-forward, and the resulting performance improvements can be quite dramatic. For example, the OS/2 video driver offers a variety of services that are far superior to the screen support in MS-DOS and the ROM BIOS, including high-speed display of strings and attributes at any screen position, "reading back" selected areas of the display into a buffer, and scrolling in all four directions.

The 80286-specific machine instructions can be very helpful in reducing code size and increasing execution speed. The most useful instructions are the shifts and rotates by an immediate count other than one, the three-operand multiply where one of the operands is an immediate (literal) value, and the push immediate value instruction (particularly handy for setting up OS/2 function calls). For example, in Figure 16-3, the sequence

mov ax,offset DGROUP:wlen

push ax

could be replaced by the single instruction

push offset DGROUP:wlen

Restructuring an application to take full advantage of OS/2's protected-mode capabilities requires close study of both the application and the OS/2 API, but such study can pay off with sizable benefits in performance, ease of maintenance, and code sharing. Often, for instance, different parts of an application are concerned with I/O devices of vastly different speeds, such as the keyboard, disk, and video display. It both simplifies and enhances the application to separate these elements into subprocesses (called threads in OS/2) that execute asynchronously, communicate through shared data structures, and synchronize with each other, when necessary, using semaphores.

As another example, when several applications are closely related and contain many identical or highly similar procedures, OS/2 allows you to centralize those procedures in a dynamic link library. Routines in a dynamic link library are bound to a program at its load time (rather than by LINK, as in the case of traditional runtime libraries) and are shared by all the processes that need them. This reduces the size of each application .EXE file and allows more efficient use of memory. Best of all, dynamic link libraries drastically simplify code maintenance; the routines in the libraries can be debugged or improved at any time, and the applications that use them will automatically benefit the next time they are executed.