Documentation updates
This commit is contained in:
parent
12439f8cd0
commit
6b5e9ef1d4
17 changed files with 626 additions and 73 deletions
|
|
@ -17,7 +17,7 @@ right_brace: "}"
|
||||||
|
|
||||||
# Build settings
|
# 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
|
markdown: kramdown
|
||||||
kramdown:
|
kramdown:
|
||||||
input: GFM
|
input: GFM
|
||||||
|
|
|
||||||
|
|
@ -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
|
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.
|
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
|
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.
|
drive C.
|
||||||
|
|
||||||
Next, I installed the [MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/). This SDK was released
|
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
|
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
|
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/).
|
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
|
Aside from **Microsoft Macro Assembler 5.00A** (MASM) and **Microsoft C Compiler 5.10 (Beta)** (CL), the SDK
|
||||||
**SDK Editor** (SDKED), which was essentially an OS/2 port of Mark Zbikowski's Editor (Z) that was used internally
|
included some other useful tools, such as the **SDK Editor** (SDKED), which was essentially an OS/2 port of
|
||||||
at Microsoft for many years. It was renamed to the **Microsoft Editor** (M or MEP) with the release of Microsoft C
|
Mark Zbikowski's full-screen editor (Z) that was used internally at Microsoft for many years. It was renamed
|
||||||
5.1, and it was later integrated into **Programmer's Workbench** (PWB), the text-mode Integrated Development
|
to the **Microsoft Editor** (M or MEP) with the release of **Microsoft C Compiler 5.10**, and it was later integrated
|
||||||
Environment (IDE) that came with Microsoft C 6.0.
|
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,
|
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
|
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/) page. I'll be adding a complete list of all the files
|
[MS OS/2 SDK 1.02](/disks/pc/tools/microsoft/os2/sdk/1.02/) pre-installed, so check out our copy of the
|
||||||
that came with SDK to that page in the near future.
|
[Microsoft® Operating System/2 Programmer’s Toolkit](/pubs/pc/software/os2/microsoft/ptk10/) and then write some code!
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
{% include machine.html id="ibm5170" %}
|
{% include machine.html id="ibm5170" %}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
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" %}
|
{% include machine.html id="ibm5170" %}
|
||||||
|
|
||||||
### Directory of IBM OS/2 1.0 (1.44M Install)
|
### Directory of IBM OS/2 1.0 (1.44M Install)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<machine id="ibm5170" class="pc" border="1" pos="center" background="#FAEBD7">
|
<machine id="ibm5170" class="pc" border="1" pos="center" background="#FAEBD7">
|
||||||
<name>IBM PC AT (8Mhz), 128Kb EGA, 2Mb RAM, 20Mb Hard Disk</name>
|
<name>IBM PC AT (8Mhz), 128Kb EGA, 2Mb RAM, 20Mb Hard Disk</name>
|
||||||
<computer id="at-ega-2048k" name="IBM PC AT" buswidth="24"/>
|
<computer id="at-ega-2048k" name="IBM PC AT" buswidth="24"/>
|
||||||
<cpu id="cpu286" model="80286" cycles="8000000"/>
|
<cpu id="cpu286" model="80286" cycles="8000000" autostart="true"/>
|
||||||
<ram id="ramLow" addr="0x00000" test="false" size="0xa0000" comment="ROM BIOS memory test has been disabled"/>
|
<ram id="ramLow" addr="0x00000" test="false" size="0xa0000" comment="ROM BIOS memory test has been disabled"/>
|
||||||
<ram id="ramExt" addr="0x100000" size="0x160000" comment=""/>
|
<ram id="ramExt" addr="0x100000" size="0x160000" comment=""/>
|
||||||
<rom id="romEGA" addr="0xc0000" size="0x4000" file="/devices/pc/video/ibm/ega/ibm-ega.json" notify="videoEGA"/>
|
<rom id="romEGA" addr="0xc0000" size="0x4000" file="/devices/pc/video/ibm/ega/ibm-ega.json" notify="videoEGA"/>
|
||||||
|
|
|
||||||
|
|
@ -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/).
|
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
|
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/).
|
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:
|
Other documentation is available for selected OS/2 SDK tools:
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ AAD (0xD5)
|
||||||
|
|
||||||
### Description
|
### 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
|
Undocumented: Available to all Intel x86 processors
|
||||||
Useful in production source code.
|
Useful in production source code.
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ title: "x86 Instructions: AAM"
|
||||||
permalink: /docs/x86/ops/AAM/
|
permalink: /docs/x86/ops/AAM/
|
||||||
---
|
---
|
||||||
|
|
||||||
AAD (0xD4)
|
AAM (0xD4)
|
||||||
---
|
---
|
||||||
|
|
||||||
### Description
|
### 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.
|
Undocumented: Available to all Intel x86 processors.
|
||||||
Useful in production source code.
|
Useful in production source code.
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ ICEBP (0xF1)
|
||||||
|
|
||||||
### Description
|
### 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
|
An undocumented op code that will make debugging run-time code
|
||||||
on an ICE easier. Normally, to set an arbitrary breakpoint in a
|
on an ICE easier. Normally, to set an arbitrary breakpoint in a
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ LOADALL386 (0x070F)
|
||||||
|
|
||||||
### Description
|
### 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
|
(LOADALL) An undocumented op code used by ICE host software and
|
||||||
diagnostics software to test CPU functionality. This instruction
|
diagnostics software to test CPU functionality. This instruction
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ SALC (0xD6)
|
||||||
|
|
||||||
### Description
|
### 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
|
An undocumented op code that performs an operation common to
|
||||||
every Assembly language subroutine to C and many other higher
|
every Assembly language subroutine to C and many other higher
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ UMOV (0x100F,0x110F,0x120F,0x130F)
|
||||||
|
|
||||||
### Description
|
### 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
|
An undocumented op code used by ICE host software to perform
|
||||||
memory cycles to the target system during HALT mode.
|
memory cycles to the target system during HALT mode.
|
||||||
|
|
|
||||||
|
|
@ -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
|
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.
|
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
|
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)
|
[reported](http://www.malinov.com/Home/sergeys-projects/sergey-s-xt/historical-notes) that all
|
||||||
that all PUSH *segreg* instructions also have the same delaying effect, at least on selected 80C88 processors.
|
`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
|
### 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
|
REP ES: MOVSB
|
||||||
|
|
||||||
and an interrupt occurs, the instruction will restart with only the last override. This was never fixed in any
|
and an interrupt occurs, the instruction will restart with the last override prefix byte, ignoring any
|
||||||
8086/8088.
|
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 recommended work-around is to ensure that the *segment override* is the last prefix byte, and then rewrite
|
||||||
the sequence:
|
the operation like this:
|
||||||
|
|
||||||
top:
|
top:
|
||||||
REP ES: MOVSB
|
REP ES: MOVSB
|
||||||
|
|
@ -50,6 +50,9 @@ the sequence:
|
||||||
JMP top
|
JMP top
|
||||||
done:
|
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
|
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,
|
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.
|
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)
|
### MOV segreg,xxx (0x8E)
|
||||||
|
|
||||||
Similar to `POP CS`, this instruction was of limited value when the selected *segreg* was CS.
|
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
|
* 0 = ES
|
||||||
* 1 = CS (invalid on 80286 and later)
|
* 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.
|
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)
|
### Duplicate RET and RETF Instructions (0xC0, 0xC1, 0xC8, 0xC9)
|
||||||
|
|
||||||
* Opcode 0xC0 decodes identically to RET n (0xC2)
|
* 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 0xC8 decodes identically to RETF n (0xCA)
|
||||||
* Opcode 0xC9 decodes identically to RET n (0xCB)
|
* 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
|
Starting with the 80186, opcodes 0xC0 and 0xC1 were reused for new shift and rotate instruction groups,
|
||||||
0xC8 and 0xC9 became the `ENTER` and `LEAVE` instructions.
|
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)
|
### Duplicate LOCK Prefix (0xF1)
|
||||||
|
|
||||||
It is believed that 0xF1 decodes identically to 0xF0 (the `LOCK` prefix).
|
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
|
Assorted Publications
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@ redirect_from:
|
||||||
- /pubs/pc/programming/os2/microsoft/ptk/1.0/
|
- /pubs/pc/programming/os2/microsoft/ptk/1.0/
|
||||||
---
|
---
|
||||||
|
|
||||||
|
[Microsoft OS/2 Programmer's Toolkit](../../)
|
||||||
|
---
|
||||||
|
|
||||||
Welcome
|
Welcome
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,7 @@ redirect_from:
|
||||||
- /pubs/pc/programming/os2/microsoft/ptk/1.0/plguide/
|
- /pubs/pc/programming/os2/microsoft/ptk/1.0/plguide/
|
||||||
---
|
---
|
||||||
|
|
||||||
Programmer's Toolkit
|
[Microsoft OS/2 Programmer's Learning Guide](../)
|
||||||
---
|
|
||||||
|
|
||||||
Programmer's Learning Guide
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Version 1.0
|
Version 1.0
|
||||||
|
|
@ -17,27 +14,27 @@ Version 1.0
|
||||||
|
|
||||||
### Contents
|
### Contents
|
||||||
|
|
||||||
* 1.0 [Introduction](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/)
|
* 1.0 [Introduction](chapter1/)
|
||||||
* 1.1 [Overview](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#overview)
|
* 1.1 [Overview](chapter1/#overview)
|
||||||
* 1.2 [What You Need to Start](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#what-you-need-to-start)
|
* 1.2 [What You Need to Start](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.3 [What This Guide Covers](chapter1/#what-this-guide-covers)
|
||||||
* 1.4 [The Lqh Sample Program](/pubs/pc/software/os2/microsoft/ptk10/plguide/chapter1/#the-lqh-sample-program)
|
* 1.4 [The Lqh Sample Program](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.5 [MS OS/2 Sample Programs](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)
|
* 1.6 [MS OS/2 and the C Run-time Library](chapter1/#ms-os2-and-the-c-run-time-library)
|
||||||
* 2.0 Overview
|
* 2.0 [Overview](chapter2/)
|
||||||
* 2.1 Introduction
|
* 2.1 [Introduction](chapter2/#introduction)
|
||||||
* 2.2 Creating an MS OS/2 Program
|
* 2.2 [Creating an MS OS/2 Program](chapter2/#creating-an-ms-os2-program)
|
||||||
* 2.3 C-Language Header Files
|
* 2.3 [C-Language Header Files](chapter2/#c-language-header-files)
|
||||||
* 2.4 A Simple Program: Echoing the Command Line
|
* 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
|
* 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
|
* 2.6 [Using Structures: Getting the Time of Day](chapter2/#using-structures-getting-the-time-of-day)
|
||||||
* 2.7 Using Bit Masks
|
* 2.7 [Using Bit Masks](chapter2/#using-bit-masks)
|
||||||
* 2.8 Sharing Resources: Playing a Tune
|
* 2.8 [Sharing Resources: Playing a Tune](chapter2/#sharing-resources-playing-a-tune)
|
||||||
* 3.0 Input and Output
|
* 3.0 [Input and Output](chapter3/)
|
||||||
* 3.1 Introduction
|
* 3.1 [Introduction](chapter3/#introduction)
|
||||||
* 3.2 Opening Files
|
* 3.2 [Opening Files](chapter3/#opening-files)
|
||||||
* 3.3 Reading and Writing to Files
|
* 3.3 [Reading and Writing to Files](chapter3/#reading-and-writing-to-files)
|
||||||
* 3.4 Creating a File
|
* 3.4 [Creating a File](chapter3/#creating-a-file)
|
||||||
* 3.5 Closing a File
|
* 3.5 Closing a File
|
||||||
* 3.6 Standard Input and Output Files
|
* 3.6 Standard Input and Output Files
|
||||||
* 3.7 Redirecting Standard Files
|
* 3.7 Redirecting Standard Files
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ redirect_from:
|
||||||
- /pubs/pc/programming/os2/microsoft/ptk/1.0/plguide/chapter1/
|
- /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
|
Introduction
|
||||||
|
|
@ -111,6 +111,7 @@ threads | Creates and manages threads.
|
||||||
timer | Sleeps and then beeps three times.
|
timer | Sleeps and then beeps three times.
|
||||||
version | Prints the DOS version (bound).
|
version | Prints the DOS version (bound).
|
||||||
vioreg | Registers a Vio subsystem.
|
vioreg | Registers a Vio subsystem.
|
||||||
|
|
|
||||||
|
|
||||||
The following sample programs are extended examples that combine many of the features illustrated in the previous
|
The following sample programs are extended examples that combine many of the features illustrated in the previous
|
||||||
samples:
|
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).
|
bigben | Displays a digital clock, demonstrating the Vio functions (bound).
|
||||||
setega | Sets 25/43-line mode (bound).
|
setega | Sets 25/43-line mode (bound).
|
||||||
chaser | Demonstrates the use of threads (requires a mouse).
|
chaser | Demonstrates the use of threads (requires a mouse).
|
||||||
|
|
|
||||||
|
|
||||||
### 1.6 MS OS/2 and the C Run-time Library
|
### 1.6 MS OS/2 and the C Run-time Library
|
||||||
|
|
||||||
|
|
|
||||||
385
pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/README.md
Normal file
385
pubs/pc/software/os2/microsoft/ptk10/plguide/chapter2/README.md
Normal file
|
|
@ -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 <os2.h>
|
||||||
|
|
||||||
|
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 leftto-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 <os2.h>
|
||||||
|
|
||||||
|
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 commandline 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 <os2.h>
|
||||||
|
|
||||||
|
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 <os2 .h>
|
||||||
|
|
||||||
|
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 <os2.h>
|
||||||
|
|
||||||
|
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 <os2.h>
|
||||||
|
|
||||||
|
#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.
|
||||||
148
pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/README.md
Normal file
148
pubs/pc/software/os2/microsoft/ptk10/plguide/chapter3/README.md
Normal file
|
|
@ -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
|
||||||
|
readonly 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.
|
||||||
Loading…
Reference in a new issue