From 6b5e9ef1d477e9d143603c70e6c3fded23947df4 Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Fri, 19 Feb 2016 12:23:12 -0800 Subject: [PATCH] Documentation updates --- _config.yml | 2 +- _posts/2015-12-27-revisiting-os2.md | 28 +- disks/pc/os2/ibm/1.0/README.md | 4 + disks/pc/os2/ibm/1.0/machine.xml | 2 +- .../pc/tools/microsoft/os2/sdk/1.02/README.md | 2 +- docs/x86/ops/AAD/README.md | 2 +- docs/x86/ops/AAM/README.md | 4 +- docs/x86/ops/ICEBP/README.md | 2 +- docs/x86/ops/LOADALL/README.md | 2 +- docs/x86/ops/SALC/README.md | 2 +- docs/x86/ops/UMOV/README.md | 2 +- pubs/pc/reference/intel/8086/README.md | 60 +-- .../pc/software/os2/microsoft/ptk10/README.md | 3 + .../os2/microsoft/ptk10/plguide/README.md | 47 +-- .../ptk10/plguide/chapter1/README.md | 4 +- .../ptk10/plguide/chapter2/README.md | 385 ++++++++++++++++++ .../ptk10/plguide/chapter3/README.md | 148 +++++++ 17 files changed, 626 insertions(+), 73 deletions(-) create mode 100644 pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/README.md create mode 100644 pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/README.md diff --git a/_config.yml b/_config.yml index 0526423ec..ca1fd2d21 100644 --- a/_config.yml +++ b/_config.yml @@ -17,7 +17,7 @@ right_brace: "}" # Build settings -exclude: ["index.html", "**/index.html", "**/archive", "logs", "node_modules", "**/c64", "**/private", "src", "**/src", "tmp", "videos", "web", ".git", ".idea"] +exclude: ["index.html", "**/index.html", "**/archive", "**/c64", "blog/posts", "logs", "node_modules", "**/private", "src", "**/src", "tmp", "videos", "web", ".git", ".idea"] markdown: kramdown kramdown: input: GFM diff --git a/_posts/2015-12-27-revisiting-os2.md b/_posts/2015-12-27-revisiting-os2.md index 0f94bf32e..e6d28ec6e 100644 --- a/_posts/2015-12-27-revisiting-os2.md +++ b/_posts/2015-12-27-revisiting-os2.md @@ -13,31 +13,31 @@ machines: Just for fun (because I have a warped sense of fun), I decided to revisit some of the old OS/2 software I wrote almost 30 years ago. But first, I needed an OS/2 development environment. -So I started with a clean install of IBM's OS/2 1.0 in the [8Mhz IBM PC AT](/disks/pc/os2/ibm/1.0/) machine +So I started with a clean install of [IBM OS/2 1.0](/disks/pc/os2/ibm/1.0/) in the 8Mhz IBM PC AT machine below, by booting from the "IBM OS/2 1.0 (1.44M Install)" diskette in drive A and reformatting the machine's 20Mb drive C. Next, I installed the [MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/). This SDK was released in December 1987 along with [Microsoft OS/2 1.0](/disks/pc/os2/microsoft/1.0/). I don't have any of the printed documentation that came with the SDK, such as the *Installation Guide*, but I do have the -[Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/programming/os2/microsoft/ptk/1.0/) documentation +[Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/software/os2/microsoft/ptk10/) documentation from March 1988, thanks to the [OS/2 Museum](http://www.os2museum.com/wp/os2-history/os2-library/os2-1-x-programming/). -Aside from Microsoft's assembler (MASM) and C compiler (CL), the SDK included some other useful tools, such as the -**SDK Editor** (SDKED), which was essentially an OS/2 port of Mark Zbikowski's Editor (Z) that was used internally -at Microsoft for many years. It was renamed to the **Microsoft Editor** (M or MEP) with the release of Microsoft C -5.1, and it was later integrated into **Programmer's Workbench** (PWB), the text-mode Integrated Development -Environment (IDE) that came with Microsoft C 6.0. +Aside from **Microsoft Macro Assembler 5.00A** (MASM) and **Microsoft C Compiler 5.10 (Beta)** (CL), the SDK +included some other useful tools, such as the **SDK Editor** (SDKED), which was essentially an OS/2 port of +Mark Zbikowski's full-screen editor (Z) that was used internally at Microsoft for many years. It was renamed +to the **Microsoft Editor** (M or MEP) with the release of **Microsoft C Compiler 5.10**, and it was later integrated +into **Programmer's Workbench** (PWB), the text-mode Integrated Development Environment (IDE) that came with +**Microsoft C Compiler 6.0**. With the introduction of graphical IDEs, such as Visual BASIC in 1991, Visual C++ in 1993, and Visual Studio in 1995, -this stand-alone, text-mode editor became obsolete, but in the 1980s, it was an essential tool. +this stand-alone, text-mode editor became obsolete, but in the 1980s, it was a valuable tool. You can learn more +about [SDKED](/disks/pc/tools/microsoft/os2/sdk/1.02/#using-sdked) on the +[MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/) page. -You can learn more about [SDKED](/disks/pc/tools/microsoft/os2/sdk/1.02/#using-sdked) on the -[MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/) page. I'll be adding a complete list of all the files -that came with SDK to that page in the near future. - -To boot IBM OS/2 1.0 and tinker with the [SDK](/disks/pc/tools/microsoft/os2/sdk/1.02/), scroll down and -click the "Run" button. +Our [IBM OS/2 1.0](/disks/pc/os2/ibm/1.0/) demo machine (shown below) has the +[MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/) pre-installed, so check out our copy of the +[Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/software/os2/microsoft/ptk10/) and then write some code! {% include machine.html id="ibm5170" %} diff --git a/disks/pc/os2/ibm/1.0/README.md b/disks/pc/os2/ibm/1.0/README.md index e46168ff4..e31db1afc 100644 --- a/disks/pc/os2/ibm/1.0/README.md +++ b/disks/pc/os2/ibm/1.0/README.md @@ -25,6 +25,10 @@ digits are the day of the year (294 or October 21). Directory listings of the four 1.44Mb distribution diskettes are provided below. +IBM OS/2 1.0 has been pre-installed on this machine's 20Mb hard disk, along with a copy of the +[Microsoft OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/), as discussed in this +[blog post](/blog/2015/12/27/). + {% include machine.html id="ibm5170" %} ### Directory of IBM OS/2 1.0 (1.44M Install) diff --git a/disks/pc/os2/ibm/1.0/machine.xml b/disks/pc/os2/ibm/1.0/machine.xml index 2b9fab1d3..9943df3f9 100644 --- a/disks/pc/os2/ibm/1.0/machine.xml +++ b/disks/pc/os2/ibm/1.0/machine.xml @@ -3,7 +3,7 @@ IBM PC AT (8Mhz), 128Kb EGA, 2Mb RAM, 20Mb Hard Disk - + diff --git a/disks/pc/tools/microsoft/os2/sdk/1.02/README.md b/disks/pc/tools/microsoft/os2/sdk/1.02/README.md index ba61ce7fc..36154e7b6 100644 --- a/disks/pc/tools/microsoft/os2/sdk/1.02/README.md +++ b/disks/pc/tools/microsoft/os2/sdk/1.02/README.md @@ -13,7 +13,7 @@ that allows the SDK installation script to finish. This SDK was released in December 1987 along with [Microsoft OS/2 1.0](/disks/pc/os2/microsoft/1.0/). We do not have any of the printed documentation that came with the SDK, such as the *Installation Guide*, but we do -have the [Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/programming/os2/microsoft/ptk/1.0/) documentation +have the [Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/software/os2/microsoft/ptk10/) documentation from March 1988, thanks to the [OS/2 Museum](http://www.os2museum.com/wp/os2-history/os2-library/os2-1-x-programming/). Other documentation is available for selected OS/2 SDK tools: diff --git a/docs/x86/ops/AAD/README.md b/docs/x86/ops/AAD/README.md index 9d9f9e75e..d86655e7b 100644 --- a/docs/x86/ops/AAD/README.md +++ b/docs/x86/ops/AAD/README.md @@ -9,7 +9,7 @@ AAD (0xD5) ### Description -From [http://www.rcollins.org/secrets/opcodes/AAD.html](http://www.rcollins.org/secrets/opcodes/AAD.html): +Excerpt from [http://www.rcollins.org/secrets/opcodes/AAD.html](http://www.rcollins.org/secrets/opcodes/AAD.html): Undocumented: Available to all Intel x86 processors Useful in production source code. diff --git a/docs/x86/ops/AAM/README.md b/docs/x86/ops/AAM/README.md index c7cfff0b4..2a0fbd571 100644 --- a/docs/x86/ops/AAM/README.md +++ b/docs/x86/ops/AAM/README.md @@ -4,12 +4,12 @@ title: "x86 Instructions: AAM" permalink: /docs/x86/ops/AAM/ --- -AAD (0xD4) +AAM (0xD4) --- ### Description -From [http://www.rcollins.org/secrets/opcodes/AAM.html](http://www.rcollins.org/secrets/opcodes/AAM.html): +Excerpt from [http://www.rcollins.org/secrets/opcodes/AAM.html](http://www.rcollins.org/secrets/opcodes/AAM.html): Undocumented: Available to all Intel x86 processors. Useful in production source code. diff --git a/docs/x86/ops/ICEBP/README.md b/docs/x86/ops/ICEBP/README.md index faf14b664..fce976b8e 100644 --- a/docs/x86/ops/ICEBP/README.md +++ b/docs/x86/ops/ICEBP/README.md @@ -9,7 +9,7 @@ ICEBP (0xF1) ### Description -From [http://www.rcollins.org/secrets/opcodes/UMOV.html](http://www.rcollins.org/secrets/opcodes/UMOV.html): +Excerpt from [http://www.rcollins.org/secrets/opcodes/ICEBP.html](http://www.rcollins.org/secrets/opcodes/ICEBP.html): An undocumented op code that will make debugging run-time code on an ICE easier. Normally, to set an arbitrary breakpoint in a diff --git a/docs/x86/ops/LOADALL/README.md b/docs/x86/ops/LOADALL/README.md index ca17a2aa7..dc562297f 100644 --- a/docs/x86/ops/LOADALL/README.md +++ b/docs/x86/ops/LOADALL/README.md @@ -9,7 +9,7 @@ LOADALL386 (0x070F) ### Description -From [http://www.rcollins.org/secrets/opcodes/LOADALL.html](http://www.rcollins.org/secrets/opcodes/LOADALL.html): +Excerpt from [http://www.rcollins.org/secrets/opcodes/LOADALL.html](http://www.rcollins.org/secrets/opcodes/LOADALL.html): (LOADALL) An undocumented op code used by ICE host software and diagnostics software to test CPU functionality. This instruction diff --git a/docs/x86/ops/SALC/README.md b/docs/x86/ops/SALC/README.md index 4bb370963..430494b11 100644 --- a/docs/x86/ops/SALC/README.md +++ b/docs/x86/ops/SALC/README.md @@ -9,7 +9,7 @@ SALC (0xD6) ### Description -From [http://www.rcollins.org/secrets/opcodes/SALC.html](http://www.rcollins.org/secrets/opcodes/SALC.html): +Excerpt from [http://www.rcollins.org/secrets/opcodes/SALC.html](http://www.rcollins.org/secrets/opcodes/SALC.html): An undocumented op code that performs an operation common to every Assembly language subroutine to C and many other higher diff --git a/docs/x86/ops/UMOV/README.md b/docs/x86/ops/UMOV/README.md index d17841cb4..1e0946430 100644 --- a/docs/x86/ops/UMOV/README.md +++ b/docs/x86/ops/UMOV/README.md @@ -9,7 +9,7 @@ UMOV (0x100F,0x110F,0x120F,0x130F) ### Description -From [http://www.rcollins.org/secrets/opcodes/UMOV.html](http://www.rcollins.org/secrets/opcodes/UMOV.html): +Excerpt from [http://www.rcollins.org/secrets/opcodes/UMOV.html](http://www.rcollins.org/secrets/opcodes/UMOV.html): An undocumented op code used by ICE host software to perform memory cycles to the target system during HALT mode. diff --git a/pubs/pc/reference/intel/8086/README.md b/pubs/pc/reference/intel/8086/README.md index 6430dc803..bd18332d9 100644 --- a/pubs/pc/reference/intel/8086/README.md +++ b/pubs/pc/reference/intel/8086/README.md @@ -27,22 +27,22 @@ Intel provided a fix for this on later processors, by delaying the acknowledgeme after a `MOV SS,xxx` or `POP SS` instruction; the delay lasts only one instruction, so you're obliged to change SP on the very next instruction. -Note that Intel's fix appears to have been over-broad: *all* `MOV segreg,xxx` and `POP segreg` +Intel's fix also appears to have been overbroad: *all* `MOV segreg,xxx` and `POP segreg` instructions delay interrupts, not just `MOV SS,xxx` and `POP SS`. In fact, it's been -[reported](http://www.malinov.com/Home/sergeys-projects/sergey-s-xt/historical-notes) -that all PUSH *segreg* instructions also have the same delaying effect, at least on selected 80C88 processors. +[reported](http://www.malinov.com/Home/sergeys-projects/sergey-s-xt/historical-notes) that all +`PUSH segreg` instructions may also have the same delaying effect, at least on some 80C88 processors. ### Interrupted String Instructions With Multiple Prefixes Do Not Resume Correctly -If a repeated string instruction includes more than one override; eg: +If a repeated string instruction includes more than one override prefix; eg: REP ES: MOVSB -and an interrupt occurs, the instruction will restart with only the last override. This was never fixed in any -8086/8088. +and an interrupt occurs, the instruction will restart with the last override prefix byte, ignoring any +preceding prefix bytes. This was never fixed in any 8086/8088. -The recommended work-around is to ensure that the segment override immediately precedes the instruction, and to rewrite -the sequence: +The recommended work-around is to ensure that the *segment override* is the last prefix byte, and then rewrite +the operation like this: top: REP ES: MOVSB @@ -50,6 +50,9 @@ the sequence: JMP top done: +If you're not sure your assembler will output the `REP` and `ES:` overrides in the order shown, then you should +generate the override bytes manually, using **DB** or a similar assembler directive. + 8086 Undocumented Instructions --- @@ -63,11 +66,16 @@ corresponding IP. There is no `POP CS` instruction on later x86 CPUs. The opcode was explicitly made invalid on the 80186/80188, but was reused on later CPUs (starting with the 80286) as the first byte in a series of two-byte opcodes. +### Duplicate Conditional Jumps (0x60-0x6F) + +Opcodes 0x60 through 0x6F decode identically to the conditional jump opcodes at 0x70 through 0x7F, respectively. +This is not true for any other x86 CPU. + ### MOV segreg,xxx (0x8E) Similar to `POP CS`, this instruction was of limited value when the selected *segreg* was CS. -Note that *segreg* was encoded as a 3-bit value in the second byte of the instruction, where: +Note that *segreg* is encoded as a 3-bit value in the second byte of the instruction, where: * 0 = ES * 1 = CS (invalid on 80286 and later) @@ -80,17 +88,6 @@ Note that *segreg* was encoded as a 3-bit value in the second byte of the instru On the 8086/8088/80186/80188, values 0-3 were treated the same as values 4-7, and all values were allowed. -### SETALC aka SALC (0xD6) - -Performs an operation equivalent to `SBB AL,AL`, but without modifying any flags. In other words, AL will be set to -0xFF or 0x00, depending on whether CF is set or clear. This instruction exists on all later x86 CPUs, but for some -reason, it has never been documented. - -### Duplicate Conditional Jumps (0x60-0x6F) - -Opcodes 0x60 through 0x6F decode identically to the conditional jump opcodes at 0x70 through 0x7F, respectively. -This is not true for any other x86 CPU. - ### Duplicate RET and RETF Instructions (0xC0, 0xC1, 0xC8, 0xC9) * Opcode 0xC0 decodes identically to RET n (0xC2) @@ -98,14 +95,31 @@ This is not true for any other x86 CPU. * Opcode 0xC8 decodes identically to RETF n (0xCA) * Opcode 0xC9 decodes identically to RET n (0xCB) -Starting with the 80186, opcodes 0xC0 and 0xC1 were reused for new shift and rotate instruction groups, and opcodes -0xC8 and 0xC9 became the `ENTER` and `LEAVE` instructions. +Starting with the 80186, opcodes 0xC0 and 0xC1 were reused for new shift and rotate instruction groups, +and opcodes 0xC8 and 0xC9 became the `ENTER` and `LEAVE` instructions. + +### [AAM](/docs/x86/ops/AAM/) (0xD4) + +While AAM is documented, it has undocumented features (eg, its ability to divide by values other than 10, +and its effect on the flags). See the [AAM](/docs/x86/ops/AAM/) instruction for details. + +### [AAD](/docs/x86/ops/AAD/) (0xD5) + +While AAD is documented, it has undocumented features (eg, its ability to multiply by values other than 10, +and its effect on the flags). See the [AAD](/docs/x86/ops/AAD/) instruction for details. + +### [SALC](/docs/x86/ops/SALC/) (0xD6) + +Performs an operation equivalent to `SBB AL,AL`, but without modifying any flags. In other words, AL will be set to +0xFF or 0x00, depending on whether CF is set or clear. This instruction exists on all later x86 CPUs, but for some +reason, it has never been documented. Also known as **SETALC**. ### Duplicate LOCK Prefix (0xF1) It is believed that 0xF1 decodes identically to 0xF0 (the `LOCK` prefix). -On newer processors, 0xF1 is an undocumented instruction usually called `ICEBP` or `INT1`. +On newer processors, 0xF1 is an undocumented instruction usually called `ICEBP` or `INT1`. See the +[ICEBP](/docs/x86/ops/ICEBP/) instruction for details. Assorted Publications --- diff --git a/pubs/pc/software/os2/microsoft/ptk10/README.md b/pubs/pc/software/os2/microsoft/ptk10/README.md index d42a05946..1a6abcda0 100644 --- a/pubs/pc/software/os2/microsoft/ptk10/README.md +++ b/pubs/pc/software/os2/microsoft/ptk10/README.md @@ -6,6 +6,9 @@ redirect_from: - /pubs/pc/programming/os2/microsoft/ptk/1.0/ --- +[Microsoft OS/2 Programmer's Toolkit](../../) +--- + Welcome --- diff --git a/pubs/pc/software/os2/microsoft/ptk10/plguide/README.md b/pubs/pc/software/os2/microsoft/ptk10/plguide/README.md index b6380323c..e75537af3 100644 --- a/pubs/pc/software/os2/microsoft/ptk10/plguide/README.md +++ b/pubs/pc/software/os2/microsoft/ptk10/plguide/README.md @@ -6,10 +6,7 @@ redirect_from: - /pubs/pc/programming/os2/microsoft/ptk/1.0/plguide/ --- -Programmer's Toolkit ---- - -Programmer's Learning Guide +[Microsoft OS/2 Programmer's Learning Guide](../) --- Version 1.0 @@ -17,27 +14,27 @@ Version 1.0 ### Contents -* 1.0 [Introduction](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/) - * 1.1 [Overview](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#overview) - * 1.2 [What You Need to Start](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#what-you-need-to-start) - * 1.3 [What This Guide Covers](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#what-this-guide-covers) - * 1.4 [The Lqh Sample Program](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#the-lqh-sample-program) - * 1.5 [MS OS/2 Sample Programs](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#ms-os2-sample-programs) - * 1.6 [MS OS/2 and the C Run-time Library](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#ms-os2-and-the-c-run-time-library) -* 2.0 Overview - * 2.1 Introduction - * 2.2 Creating an MS OS/2 Program - * 2.3 C-Language Header Files - * 2.4 A Simple Program: Echoing the Command Line - * 2.5 Using the MS OS/2 Naming Conventions - * 2.6 Using Structures: Getting the Time of Day - * 2.7 Using Bit Masks - * 2.8 Sharing Resources: Playing a Tune -* 3.0 Input and Output - * 3.1 Introduction - * 3.2 Opening Files - * 3.3 Reading and Writing to Files - * 3.4 Creating a File +* 1.0 [Introduction](chapter1/) + * 1.1 [Overview](chapter1/#overview) + * 1.2 [What You Need to Start](chapter1/#what-you-need-to-start) + * 1.3 [What This Guide Covers](chapter1/#what-this-guide-covers) + * 1.4 [The Lqh Sample Program](chapter1/#the-lqh-sample-program) + * 1.5 [MS OS/2 Sample Programs](chapter1/#ms-os2-sample-programs) + * 1.6 [MS OS/2 and the C Run-time Library](chapter1/#ms-os2-and-the-c-run-time-library) +* 2.0 [Overview](chapter2/) + * 2.1 [Introduction](chapter2/#introduction) + * 2.2 [Creating an MS OS/2 Program](chapter2/#creating-an-ms-os2-program) + * 2.3 [C-Language Header Files](chapter2/#c-language-header-files) + * 2.4 [A Simple Program: Echoing the Command Line](chapter2/#a-simple-program-echoing-the-command-line) + * 2.5 [Using the MS OS/2 Naming Conventions](chapter2/#using-the-ms-os2-naming-conventions) + * 2.6 [Using Structures: Getting the Time of Day](chapter2/#using-structures-getting-the-time-of-day) + * 2.7 [Using Bit Masks](chapter2/#using-bit-masks) + * 2.8 [Sharing Resources: Playing a Tune](chapter2/#sharing-resources-playing-a-tune) +* 3.0 [Input and Output](chapter3/) + * 3.1 [Introduction](chapter3/#introduction) + * 3.2 [Opening Files](chapter3/#opening-files) + * 3.3 [Reading and Writing to Files](chapter3/#reading-and-writing-to-files) + * 3.4 [Creating a File](chapter3/#creating-a-file) * 3.5 Closing a File * 3.6 Standard Input and Output Files * 3.7 Redirecting Standard Files diff --git a/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/README.md b/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/README.md index 10058d692..9bba76a6a 100644 --- a/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/README.md +++ b/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/README.md @@ -6,7 +6,7 @@ redirect_from: - /pubs/pc/programming/os2/microsoft/ptk/1.0/plguide/chapter1/ --- -Microsoft OS/2 Programmer's Learning Guide +[Microsoft OS/2 Programmer's Learning Guide](../) --- Introduction @@ -111,6 +111,7 @@ threads | Creates and manages threads. timer | Sleeps and then beeps three times. version | Prints the DOS version (bound). vioreg | Registers a Vio subsystem. + | The following sample programs are extended examples that combine many of the features illustrated in the previous samples: @@ -127,6 +128,7 @@ mandel | Displays the Mandelbrot set, using EGA high-resolution graphics. bigben | Displays a digital clock, demonstrating the Vio functions (bound). setega | Sets 25/43-line mode (bound). chaser | Demonstrates the use of threads (requires a mouse). + | ### 1.6 MS OS/2 and the C Run-time Library diff --git a/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/README.md b/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/README.md new file mode 100644 index 000000000..1649f2d2f --- /dev/null +++ b/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/README.md @@ -0,0 +1,385 @@ +--- +layout: page +title: "Microsoft OS/2 Programmer's Learning Guide: Overview" +permalink: /pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/ +--- + +[Microsoft OS/2 Programmer's Learning Guide](../) +--- + +Overview +--- + +### 2.1 Introduction + +This chapter explains the basic steps needed to create an MS OS/2 +C-language program. In particular, it explains how to do the following: + ++ Use the **main** function for your program starting point. ++ Use the *os2.h* header file for function declarations. ++ Use INCL_ constants to selectively enable function groups. ++ Use your program's command line. ++ Use MS OS/2 naming conventions in your program sources. ++ Use structures in MS OS/2 function calls. ++ Use the AND and OR operators to examine and modify bit masks. ++ Use care in programs that access shared resources. + +### 2.2 Creating an MS OS/2 Program + +Creating an MS OS/2 C-language program is no different than creating any other type of C-language program. +You use the **main** function as your program starting point and create and call as many other functions as +you need to complete the task. The following simple MS OS/2 program copies the line "Hello, world" to the screen: + + #include + + main( ) + { + USHORT cbWritten; + DosWrite(1, "Hello, world\r\n", 14, &cbWritten); + } + +The MS OS/2 system functions use many structures, data types, and constants that are not part of the standard +C language. For example, the data type **USHORT** is a special MS OS/2 data type that specifies an unsigned short +integer. To access these items, you need to include the MS OS/2 header file *os2.h* at the beginning of your program +source file. + +The MS OS/2 system functions are not standard C functions. They use the Pascal calling convention. This means, +for example, that they expect parameters to be passed in right-to-left order instead of the standard left­to-right +order of C functions. Therefore, to use the MS OS/2 functions in a C-language program, you must make sure they are +declared with the **pascal** keyword, which directs the C compiler to generate proper instructions for the function +call. Fortunately, all MS OS/2 functions are declared within the *os2.h* file, so including the file saves you the +trouble of declaring each function individually. + +The *os2.h* file also declares the parameter types for each function. This is convenient since many function +parameters would otherwise require type casting to avoid compiler errors. For example, the **DosWrite** function +shown in the previous example requires the second parameter to be a full 32-bit (far) address to the given string. +Since the *os2.h* file declares the second parameter as such, the cast is carried out for you by the compiler. + +### 2.3 C-Language Header Files + +The MS OS/2 C-language header file *os2.h* contains the definitions you need to use the functions, data types, +structures, and constants described in the *Microsoft Operating System/2 Programmer's Reference*. + +When you include the *os2.h* file, the C preprocessor automatically defines many, but not all, of the most commonly +used MS OS/2 functions. The *os2.h* header file is the first file of a set of files that contains the MS OS/2 function +definitions. Each file contains definitions for the functions, data types, structures, and constants associated with +a specific group of MS OS/2 functions. To minimize the time required to process the many header files, each function +group is conditionally processed depending on whether a corresponding constant is defined within the program source file. +The following is a list of these constants with descriptions of the function groups they represent: + +**Constant** | **Meaning** +:----------------- | :------------- +INCL_BASE | Includes all MS OS/2 1.0 system function definitions. +INCL_DOS | Includes all MS OS/2 1.0 kernel function definitions (Dos). +INCL_SUB | Includes all MS OS/2 1.0 video, keyboard, and mouse functions (Vio, Kbd, and Mou). +INCL_DOSDATETIME | Includes all date/time and timer functions. +INCL_DOSDEVICES | Includes the device and IOPL support functions. +INCL_DOSERRORS | Includes the MS OS/2 error constants. +INCL_DOSFILEMGR | Includes all file-management functions. +INCL_DOSINFOSEG | Includes all information-segment functions. +INCL_DOSMEMMGR | Includes all memory-management functions. +INCL_DOSMODULEMGR | Includes all module-manager functions. +INCL_DOSMONITORS | Includes all monitor functions. +INCL_DOSNLS | Includes national-language-support functions. +INCL_DOSPROCESS | Includes all process- and thread-support functions. +INCL_DOSQUEUES | Includes all queue and other miscellaneous functions. +INCL_DOSRESOURCES | Includes resource-support functions (not available in MS OS/2 1.0). +INCL_DOSSEMAPHORES | Includes all semaphore functions. +INCL_DOSSESMGR | Includes all session-manager functions. +INCL_DOSSIGNALS | Includes all signal functions. +INCL_NOCOMMON | Excludes any function group not explicitly defined. + | + +To use a function within your program function, you simply define the corresponding constant by using the #define +directive before including the *os2.h* file. For example, the following program includes definitions for the +memory-manager and file-system functions: + + #define INCL_DOSMEMMGR + #define INCL_DOSFILEMGR + #include + + main( ) + { + ... + } + +Once you have defined a constant, you may use any function, structure, or data type in that function group. + +### 2.4 A Simple Program: Echoing the Command Line + +In standard C-language programs, you can use the *argc* and *argv* parameters of the main function to retrieve +individual copies of the command­line arguments. You can use these parameters in MS OS/2 programs, but you can also +retrieve the entire command line, exactly as the user typed it, by using the **DosGetEnv** function. + +When it starts a program, MS OS/2 prepares an environment segment for the program that contains definitions of all +environment variables, as well as of the command line. The **DosGetEnv** function retrieves the segment selector +for the program's environment segment and the address offset within that segment for the start of the command line. + +You can echo the command line on the screen by using the **DosGetEnv** function to get the address of the command +line in the environment segment, as shown in the following sample program: + + #define INCL_DOSQUEUES + #include + + main( ) + { + SEL selEnvironment; + USHORT offCommand; + PSZ pszCommandLine; + USHORT cbWritten; + USHORT i, cch; + + DosGetEnv(&selEnvironment, &offCommand); + pszCommandLine = MAKEP(selEnvironment, offCommand); + + for (i = 0; pszCommandLine[i]; i++); + for (i++, cch = 0; pszCommandLine[cch + i]; cch++); + + DosWrite(1, &pszCommandLine[i] , cch, &cbWritten); + } + +The command line is in two parts. The first part is the program name, terminated by a zero byte. The second part +is the rest of the command line, terminated by two zero bytes. This sample program echoes the command line by skipping +over the program name, then writing everything up to the next zero byte to the screen. The first **for** statement +skips over the command name; the second for statement computes the length of the string. The **MAKEP** macro creates +the far pointer that is needed to access the command line in the environment segment. + +You can also examine your program's environment by using the selector retrieved by the **DosGetEnv** function. +The program's environment consists of the environment variables that have been declared and passed to the program. +Each program has a unique environment that is typically inherited from the program that started it; for example, +from the MS OS/2 command processor **cmd**. + +You can use the **DosScanEnv** function to scan for a specific environment variable. This function takes the name +of the environment variable that you are interested in and copies its current value to a buffer that you supply. +The following program uses **DosScanEnv** to display the value of the environment variable specified in the command +line: + + #define INCL_DOSQUEUES + #include + + main( ) + { + SEL selEnvironment; + USHORT offCommand; + PSZ pszCommandLine; + PSZ pszValue; + USHORT cbWritten; + USHORT i , cch; + + DosGetEnv(&selEnvironment, &offCommand); + pszCommandLine = MAKEP(selEnvironment, offCommand); + + for (i = 0 ; pszCommandLine[i); i++); + for (i++; pszCommandLine[i] == ' '; i++); + + if (!DosScanEnv (&pszCommandLine[i), &pszValue)) { + for (cch = 0; pszValue[cch); cch++); + DosWrite(1, pszValue, cch, &cbWritten); + } + } + +### 2.5 Using the MS OS/2 Naming Conventions + +The sample programs in this manual use the MS OS/2 naming conventions for their variables and functions. +These conventions define how to create names that indicate both the purpose and data type of an item used +with the MS OS/2 system functions. When you use the conventions in your source files, you help others +who may read your sources to readily identify the purpose and type of the functions, variables, structures, fields, +and constants. + +The following list briefly describes the MS OS/2 naming conventions: + +**Item** | **Convention** +:----------------- | :------------- +Variable | All names consist of three elements: a prefix, a base type, and a qualifier. + | The base type identifies the data type of the item; the prefix specifies additional + | information, such as whether the item is a pointer, an array, or a count of + | bytes; and the qualifier specifies the purpose of the item. The prefix and base + | type are lowercase, and the qualifier is mixed-case. + | +Parameter | Same as a variable. + | +Structure Field | Same as a variable. + | +Structure | All names consist of a word or phrase that specifies the purpose of the structure. + | All letters in the name are uppercase. + | +Constant | All names consist of a prefix, derived from the name of the function associated with + | the constant, and a word or phrase that specifies the meaning of the constant in terms + | of a value, action, color, or condition. All letters in the name are uppercase and an + | underscore separates the prefix from the rest of the name. + | +Function name | All names consist of a three-letter system prefix followed by a word or phrase that + | describes the action of the function. Each word in the function name starts with an + | uppercase letter. Verb-noun combinations, such as **DosGetDateTime**, are recommended. + | + +The following examples show some of the standard prefix and base types you will see in this manual: + + /* Base Types */ + BOOL fSuccess; /* f Boolean flag. TRUE if successful */ + CHAR chChar; /* ch 8-bit character */ + SHORT sRate; /* s 16-bit signed integer */ + LONG lDistance; /* l 32-bit signed integer */ + UCHAR uchScan; /* uch 8-bit unsigned character */ + USHORT usHeight; /* us 16-bit unsigned integer */ + ULONG ulWidth; /* ul 32-bit unsigned integer */ + BYTE bAttribute; /* b 8-bit unsigned integer */ + CHAR szName[]; /* sz zero-terminated array of characters */ + BYTE fbMask; /* fb array of flags in a byte */ + USHORT fsMask; /* fs array of flags in a short */ + ULONG flMask; /* fl array of flags in a long */ + SEL selSegment; /* sel 16-bit segment selector */ + + /* Prefixes */ + PCH pchBuffer; /* p 32-bit far pointer to a given type */ + NPCH npchBuffer; /* np 16-bit newr pointer to a given type */ + CHAR achData[1]; /* a array of a given type */ + USHORT ichIndex; /* i index to an array of a given type */ + USHORT cb; /* c count of items of a given type */ + HFILE hf; /* hf handle identifying a given object */ + USHORT offSeg; /* off offset */ + USHORT idSession; /* id identifier for a given object */ + +When you are naming variables, remember that the prefix and base type are optional for common integer +types such as **SHORT** and **USHORT**. + +### 2.6 Using Structures: Getting the Time of Day + +Many MS OS/2 functions use structures for input and output parameters. To use a structure in an MS OS/2 +function, you first define the structure in your program, then pass a 32-bit far address to the structure +as a parameter in the function call. + +For example, the **DosGetDateTime** function copies the current date and time to a **DATETIME** structure +whose address you supply. The fields of the **DATETIME** structure define the month, day, and year, as well as +the time of day (to hundredths of a second). The **DATETIME** structure, defined in the *os2.h* file, has the +following form: + + typedef struct _DATETIME { /* date */ + UCHAR hours; + UCHAR minutes; + UCHAR seconds; + UCHAR hundredths; + UCHAR day; + UCHAR month; + USHORT year; + SHORT timezone; + UCHAR weekday; + } DATETIME; + +To retrieve the date and time, you call the **DosGetDateTime** function and use the address operator (&) to +specify the address of your **DATETIME** structure in the call. The following example shows how to make the call: + + #include + + CHAR szDayName[] = "MonTueWedThuFriSatSun"; + CHAR szMonthName[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + CHAR szDate[] = "xx:xx:xx xxx xxx xx, xxxx\r\n"; + + main( ) + { + DATETIME date; + SHORT offset; + SHORT i; + USHORT usYear; + USHORT cbWritten; + + DosGetDateTime(&date); /* Address of the DATETIME structure */ + + szDate[0] = (date.hours/10) + '0'; + szDate[1] = (date.hours%10) + '0'; + szDate[3] = (date.minutes/10) + '0'; + szDate[4] = (date.minutes%10) + '0'; + szDate[6] = (date.seconds/10) + '0'; + szDate[7] = (date.seconds/10) + '0'; + offset = date.weekday * 3; + for (i = 0; i < 3; i++) + szData[i + 9] = szDayName[i + offset]; + offset = (date.month - 1) * 3; + for (i = 0; i < 3; i++) + szDate[i + 13] = szMonthName[i + offset]; + szDate[17] = (date.day < 10)?' ':(date.day/10 + '0'); + szDate[18] = (date.day%10) + '0'; + usYear = date.year; + szDate[21] = (usYear/1000) + '0'; + usYear = usYear % 1000; + szDate[22] = (usYear/100) + '0'; + usYear = usYear % 100; + szDate[23] = (usYear/10) + '0'; + szDate[24] = (usYear%10) + '0'; + + DosWrite(1, szDate, 27, &cbWritten); + } + +One drawback of using MS OS/2 functions exclusively is that there are no formatted output functions, +such as the **printf** function. This sample program, therefore, formats the data itself before displaying it. +The program uses the integer-division operators (/ and %) to convert binary numbers to ASCII characters. +The program then copies the ASCII characters to a string and displays the string by using the **DosWrite** function. + +Some MS OS/2 functions require that you fill one or more fields of the structure before making the function call. +For example, there are some structures whose length depends on the version of the operating system being used; +MS OS/2 requires that you supply the expected length so that the function does not copy data beyond the end of your +structure. + +### 2.7 Using Bit Masks + +In MS OS/2, many functions use bit masks. A bit mask (also called an array of flags) is a combination of two +or more Boolean flags in a single byte, word, or double-word value. In C-language programs, you can use the +bitwise AND, OR, and NOT operators to examine and set the values in a bit mask. + +If a function retrieves a bit mask, you can check a specific flag in the bit mask by using the AND operator, +as shown in the following example: + + USHORT fsEvents; + + if (fsEvent & 0x0004) + /* Is the flag set */ + +Or you can set a flag in a bit mask by using the OR operator, as shown in the following example: + + ULONG flFunctions; + + flFunctions = flFunctions | KR_KBDPEEK; + +Finally, you can clear a flag in a bit mask by using the AND and NOT operators, as shown in the following example: + + USHORT fsEvent; + + fsEvents = fsEvent & ~0x0004; + +### 2.8 Sharing Resources: Playing a Tune + +Many MS OS/2 functions let you use the resources of the computer, such as the keyboard, screen, disk, and even +the system speaker. Since MS OS/2 is a multitasking operating system and more than one program can run at a time, +MS OS/2 considers all resources of the computer to be shared resources. As a result, programs must cooperate with +other running programs and must not claim exclusive access to a given resource. + +Consider a simple program that plays a short tune by using the **DosBeep** function. This function, when called +by a single program, generates a tone at the system speaker, but if two programs call **DosBeep** at the same time, +the result is chaos. Try running two or more copies of the following program at the same time: + + #include + + #define CNOTES 14 + USHORT ausTune[] = { + 440,1000, + 480,1000, + 510,1000, + 550,1000, + 590,1000, + 620,1000, + 660,1000 + }; + + main( ) + { + int i; + + for (i = 0; i < CNOTES; i+= 2) + DosBeep(ausTune[i] , ausTune[i + 1]); + } + +The first argument to the **DosBeep** function specifies the frequency of the note. The second argument specifies +the duration. The array ausTune defines values for the frequency and duration of each note in the tune. + +**DosBeep** is intended to be used for signaling the user when an error occurs, such as pressing an incorrect key. +Since the system speaker is a shared resource, a process should use the **DosBeep** function sparingly. diff --git a/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/README.md b/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/README.md new file mode 100644 index 000000000..4b1e00ca1 --- /dev/null +++ b/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/README.md @@ -0,0 +1,148 @@ +--- +layout: page +title: "Microsoft OS/2 Programmer's Learning Guide: Input and Output" +permalink: /pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/ +--- + +[Microsoft OS/2 Programmer's Learning Guide](../) +--- + +Input and Output +--- + +### 3.1 Introduction + +Input and output are two of the most important tasks that any program carries out. This chapter explains how +to read from and write to files on disks and other input and output devices, such as printers, modems, and the +system console. + +### 3.2 Opening Files + +Before carrying out any input or output operation, you need a file handle. A file handle is a 16-bit value +that identifies the file or device that you want to read from or write to. You can create a file handle by using +the **DosOpen** function, which opens the specified file and returns a file handle for it. For example, in the +following statements, **DosOpen** opens the existing file *simple.txt* for reading and copies the file handle to the +*hf* variable: + + HFILE hf; + USHORT usResult; + + DosOpen("simple.txt", /* filename */ + &hf, /* file handle */ + &usResult, /* action taken */ + 0, /* size */ + 0, /* file attribute */ + 0x0001, /* open method */ + 0x0040, /* access and sharing method */ + 0); /* reserved */ + +If the **DosOpen** function opens the file, it copies the file handle to the *hf* variable and copies a value to +the *usResult* variable to indicate what action was taken (for example, 0x0001 for "existing file opened"). To open +an existing file, a size and file attribute are not needed, so the fourth and fifth arguments are set to zero. +The sixth argument, 0x0001, directs **DosOpen** to open the file if it exists or to return an error if it does not +exist. The next argument, 0x0040, directs **DosOpen** to open the file for reading only and let other programs open +the file even while the current program has it open. The final argument is reserved and should always be zero. + +The **DosOpen** function indicates that it successfully opened the file by returning zero. You can then use the file +handle returned in the *hf* variable in subsequent functions to read data from the file or to check the status or +other characteristics of the file. If **DosOpen** fails to open the file, it returns an error value. For example, +if the file cannot be found in the current directory, the function returns the value 0x0002. + +When you open a file, you must specify whether you want to read from the file, write to it, or both read and write. +You must also specify whether you want other processes to have access to the file while you have it open. You do this +by combining two values. These values specify the access and sharing methods and are described in the following list: + +**Value** | **Meaning** +:----------------- | :------------- +0x0000 | Open a file for reading. +0x0001 | Open a file for writing. +0x0002 | Open a file for reading and writing. +0x0010 | Open a file for exclusive use, denying read and write access by other processes. +0x0020 | Deny write access to a file by other processes. +0x0030 | Deny read access to a file by other processes. +0x0040 | Open a file with no sharing restrictions, granting read and write access to all processes. + | + +In general, you may combine any access method (read, write, or read and write) with any sharing method +(deny reading, deny writing, deny reading and writing, or grant any access). Some combinations have to be +handled carefully, however, such as opening a file for writing without denying access to it by other processes. + +### 3.3 Reading and Writing to Files + +Once you have opened a file and have a file handle, you can read from or write to the file by using the +**DosRead** or **DosWrite** function. The **DosRead** function copies a specified number of bytes (up to the +end of the file) from the file to the buffer you specify. The **DosWrite** function copies bytes from a buffer +to the file. + +To read from a file, you must open it for reading, or reading and writing. The following example shows how to +open the file named *sample.txt* and read the first 512 bytes from it: + + HFILE hf; + USHORT usResult; + BYTE abBuffer[512]; + USHORT cbRead; + + if (!DosOpen("sample.txt", &hf, &usResult, 0, 0, + 0x0001, 0x0040, 0)) { + DosRead(hf, abBuffer, 512, &cbRead); + DosClose(hf); + } + +If the file does not have 512 bytes, **DosRead** reads up to the end of the file and copies the number of bytes +read to the *cbRead* variable. If the function has already read to the end of the file and there are no more bytes +to read, it copies zero to the *cbRead* variable. + +To write to a file, you must open it first for writing, or for reading and writing. The following example shows +how to open the file *sample.txt* again and write 512 bytes to it: + + HFILE hf; + USHORT usResult; + BYTE abBuffer[512); + USHORT cbWritten; + + if (!DosOpen("sample.txt", &hf, &usResult, 0, 0, + 0x0011, 0x0041, 0)) { + DosWrite(hf, abBuffer, 512, &cbWritten); + DosClose(hf); + } + +The **DosWrite** function writes the contents of the buffer to the file. If it fails to write 512 bytes +(for example, if the disk is full), the function copies the number of bytes written to the *cbWritten* variable. + +### 3.4 Creating a File + +You can also create new files by using the **DosOpen** function. Once you have created a new file, you may read +from or write to it just as you would with an existing file. + +To create a new file, set the sixth parameter to the value 0x0010. The **DosOpen** function then creates the file +if it does not already exist. In the following example, the **DosOpen** function creates the file *newfile.txt*: + + HFILE hf; + USHORT usResult; + + DosOpen("newfile.txt", /* filename */ + &hf, /* file handle */ + &usResult, /* action taken */ + 0, /* size */ + 0x0000, /* normal file attribute */ + 0x0010, /* Creates the file if it does not exist */ + 0x0011, /* write access, share with none */ + 0); + +In this example, **DosOpen** creates the file and opens it for writing. Note that the sharing method denies +any access to all processes, so no other process can open the file while it remains open. The new file is empty +(it contains no data). + +When a new file is created, the attribute argument (fifth) specifies the file attribute. In the preceding example, +the attribute argument is 0x0000, so the file is created as a normal file. Other possible file attributes are +read­only and hidden, which correspond to the values 0x0001 or 0x0002, respectively. + +The file attribute affects how other processes access the file. For example, if the file is read-only, no process +may open the file for writing. The one exception to this rule is that the process that creates the read-only file +may write to it immediately after creating it. After closing the file, however, the process may not open it for +writing again. + +When a file is created, the size argument (fourth) specifies the original size of the new file. For example, +if 256 is specified, the new file is 256 bytes long. These 256 bytes, however, are undefined. It is up to the +program to write valid data to the file. In any case, no matter what size you specify, subsequent calls to the +**DosWrite** function copy data to the beginning of the file.