|
|
1.1 ! root 1: OS/2 SDK MASM UPDATE ! 2: ! 3: ! 4: Installing the Assembler ! 5: ! 6: The OS/2 SDK version of the assembler does not include a SETUP ! 7: program. You install files by copying them directly from the release ! 8: disks. ! 9: ! 10: ! 11: Assembly Language Under OS/2 ! 12: ! 13: This file describes some of the differences between assembly language ! 14: under OS/2 and assembly language under DOS. It discusses new ! 15: techniques you will have to learn for protected-mode programs, and ! 16: summarizes differences in tools used for program development. ! 17: ! 18: A Sample Program ! 19: ---------------- ! 20: ! 21: The following program is an OS/2 version of the sample programs in ! 22: Chapter 1 of the Microsoft Macro Assembler Programmer's Guide: ! 23: ! 24: TITLE hellos2 ! 25: INCLUDELIB doscalls.lib ; <1> ! 26: .286 ! 27: .MODEL small ! 28: ! 29: ; <2> ! 30: pushc MACRO pushed, pushed2 ;; Define bind from command line ! 31: IFDEF bind ;; if you want to bind the program ! 32: mov ax, pushed pushed2 ;; Push constant for 8088/8086 ! 33: push ax ! 34: ELSE ! 35: push pushed pushed2 ;; Push constant for 80186+ ! 36: ENDIF ! 37: ENDM ! 38: ! 39: .STACK 800h ; <3> ! 40: .DATA ! 41: message DB "Hello, world.",13,10 ! 42: lmessage EQU $ - message ! 43: bytesout DD ? ! 44: ! 45: .CODE ! 46: EXTRN DosWrite:FAR, DosExit:FAR ; Declare OS/2 calls <4> ! 47: start: ; <5> ! 48: ! 49: ; DosWrite function used to write to screen <6> ! 50: ; <7> ! 51: pushc 1 ; Push 1 as handle for standard output ! 52: push ds ; Push far address of ! 53: pushc OFFSET message ; "message" ! 54: pushc lmessage ; Push length of "message" ! 55: push ds ; Push far address of ! 56: pushc OFFSET bytesout ; "bytesout" ! 57: ! 58: call DosWrite ; Make API call <8> ! 59: ; AX contains error code <9> ! 60: ; Variable "bytesout" contains ! 61: ; number of bytes written ! 62: ! 63: ; DosExit function used to return to DOS ! 64: ! 65: pushc 1 ; Push action 1 to end all threads ! 66: pushc 0 ; Push return code 0 ! 67: call DosExit ; Exit ! 68: ! 69: END start ! 70: ! 71: Note the following ways in which OS/2 programs differ from comparable ! 72: DOS programs: ! 73: ! 74: 1. OS/2 programs must always be linked with the DOSCALLS library. ! 75: You can specify this in the source file with the INCLUDELIB ! 76: directive. ! 77: ! 78: 2. OS/2 programs require an 80286 (or higher) processor. This means ! 79: you safely use instructions that are available on the 80826, but ! 80: not on earlier processors, since your programs can never run on ! 81: the earlier processors anyway. However, if you wish to bind the ! 82: program so that it will work either under OS/2 or DOS, you will ! 83: probably want to use instructions recognized by all processors. ! 84: For example, a constant can be pushed directly under the 80286, ! 85: but it must be loaded into a register first under the 8086. The ! 86: sample program uses a macro to conditionally handle either case. ! 87: ! 88: 3. Since OS/2 uses the stack to pass arguments to DOS calls, you ! 89: may need a larger stack for OS/2 programs than for comparable ! 90: DOS programs. ! 91: ! 92: 4. OS/2 system calls are far external routines and must be declared ! 93: as such in the source code. ! 94: ! 95: 5. In DOS a data segment must be loaded into DS, but in OS/2 a ! 96: default data segment (the one declared with .DATA) is ! 97: automatically loaded into DS. ! 98: ! 99: 6. For compatibility with the DOS examples in the Programmer's ! 100: Guide, the DosWrite function is used to write to the screen. The ! 101: VioWrtTTY function is a simpler alternative in many cases. See ! 102: the Microsoft Operating System/2 Programmer's Reference for a ! 103: complete list of OS/2 functions and their arguments. ! 104: ! 105: 7. Arguments are pushed onto the stack using the Pascal calling ! 106: convention. Passed addresses are always far. The called routine ! 107: cleans up the stack, so there is no need to pop the arguments ! 108: after the call. ! 109: ! 110: 8. For readability, the OS/2 API (Application Program Interface) ! 111: calls are given in mixed case (DosWrite rather than DOSWRITE). ! 112: Actually the routine names are all uppercase, but you can used ! 113: mixed case because MASM converts names to uppercase. If you are ! 114: writing routines for a case-sensitive language (such as C) you ! 115: should give the names in uppercase and use the /MX or /ML ! 116: assembler option. ! 117: ! 118: 9. All OS/2 calls return 0 in AX if the call was successful, or an ! 119: error code in AX if it was not. If additional information needs ! 120: to be passed back to the program, it will be placed in an ! 121: address passed as an argument to the call. For example, DosWrite ! 122: returns the number of bytes written in the variable ("bytesout" ! 123: in the example) whose address was passed as the last argument. ! 124: ! 125: Assembling, Linking, and Binding ! 126: -------------------------------- ! 127: ! 128: Assembly under OS/2 is exactly the same as under DOS. The MASM.EXE ! 129: program is bound so that it runs in either environment. For example, ! 130: use the following command line to assemble the sample program for ! 131: OS/2: ! 132: ! 133: MASM hellos2; ! 134: ! 135: If you want to assemble program to be bound so that it will run under ! 136: either OS/2 or DOS, use this command line: ! 137: ! 138: MASM /Dbind hellos2; ! 139: ! 140: This passes a message to the "pushc" macro to push constants in a ! 141: format compatible with the 8088/8086. ! 142: ! 143: The linker has an additional field for a definition file under OS/2, ! 144: as described in the CodeView and Utilities manual. This field is not ! 145: used for the sample file. You must also link with DOSCALLS.LIB (which ! 146: may be located in the directory specified by the LIB environment ! 147: variable). ! 148: ! 149: If DOSCALLS.LIB is specified in the source file with the INCLUDELIB ! 150: directive (as in the sample), use the following command line: ! 151: ! 152: LINK hellos2; ! 153: ! 154: You can also specify DOSCALLS.LIB in the command line: ! 155: ! 156: LINK hellos2,,,DOSCALLS; ! 157: ! 158: OS/2 applications use dynamic linking: procedure calls are not ! 159: resolved until the program is loaded into memory. When the program is ! 160: loaded, the code required by a call is extracted from a dynamic link ! 161: library and loaded with the program. All OS/2 system calls are ! 162: contained in dynamic link libraries. ! 163: ! 164: The DOSCALLS.LIB library does not contain any code for OS/2 system ! 165: calls. Instead, it contains dynamic link reference records. The linker ! 166: uses these records to make the connection between the OS/2 system call ! 167: in the application and the dynamic link library containing the system ! 168: procedure. ! 169: ! 170: You can write OS/2 programs that run under either OS/2 or MS-DOS 3.0 ! 171: or higher by restricting the OS/2 system calls your program uses. OS/2 ! 172: function calls are known collectively as the applications program ! 173: interface (API). If you restrict your program to a subset of these ! 174: functions, known as the Family API, you can write programs that run ! 175: under both OS/2 and MS-DOS 3.0 or higher. See the Microsoft Operating ! 176: System/2 Programmer's Reference for a list of the Family API ! 177: functions. ! 178: ! 179: Once you have written, assembled, and linked a program using only ! 180: Family API functions, you must bind the program using the BIND utility ! 181: to produce a version that runs under either operating system. Binding ! 182: resolves references to dynamic link routines so the application runs ! 183: without the dynamic link libraries under DOS. ! 184: ! 185: Because the sample program uses only Family API calls, you can bind it ! 186: using the following command: ! 187: ! 188: BIND hellos2 C:\LIB\DOSCALLS.LIB ! 189: ! 190: Note that BIND automatically includes the file API.LIB, so you ! 191: do not need to specify API.LIB on the command line. ! 192: ! 193: To debug OS/2 programs using CodeView, use the protected-mode version, ! 194: CVP.EXE. The options for specifying debug information are the same as ! 195: in DOS. For example: ! 196: ! 197: MASM /ZI hellos2; ! 198: LINK /CO hellos2; ! 199: CVP hellos2 ! 200: ! 201: Note that you cannot debug bound programs. However, you can debug a ! 202: protected-mode version of the program. If the program is free of ! 203: logical errors in protected mode, it should work the same when bound ! 204: and run under DOS. ! 205: ! 206: Register and Memory Consideration ! 207: --------------------------------- ! 208: ! 209: The startup conditions for an OS/2 program are significantly different ! 210: than conditions for a comparable DOS program. Two major differences ! 211: are that OS/2 programs do not have a PSP and memory is only allocated ! 212: for the data and code required by the program. ! 213: ! 214: Note these specific differences: ! 215: ! 216: o Under OS/2, AX contains the segment value of the start of the ! 217: program's environment. In other words, AX:0 points to the ! 218: environment. ! 219: ! 220: Under DOS, the word at 2Ch of the Program Segment Prefix (PSP) is ! 221: the segment value of the start of the environment. ! 222: ! 223: o Under OS/2 any program arguments are part of the program's ! 224: environment. BX contains the starting offset. Thus AX:BX points ! 225: to the name of the executable program name. It is followed by a ! 226: null byte and then any command line arguments exactly as typed on ! 227: the command line. A null terminates the command line. ! 228: ! 229: Under DOS, the command line is unrelated to the environment. It ! 230: starts at byte 81h of the PSP. The length of the command line is ! 231: in the byte at 80h in the PSP and the first two arguments are ! 232: parsed into uppercase file-name format at bytes 5Ch and 6Ch ! 233: respectively of the PSP. ! 234: ! 235: o Under OS/2, DS contains the segment of the automatic data ! 236: segment. This is the segment named DGROUP, and it contains both ! 237: the stack and data. If you use simplified segment directives, ! 238: this is the .DATA segment. If you do not use simplified segment ! 239: directives, you must place one data segment in a group called ! 240: DGROUP. For example: ! 241: ! 242: _DATA SEGMENT WORD PUBLIC 'DATA' ! 243: . ! 244: . ! 245: . ! 246: _DATA ENDS ! 247: ! 248: DGROUP GROUP _DATA ! 249: ASSUME ds:DGROUP ! 250: ! 251: Under DOS (.EXE format), DS points to the PSP. Before using a ! 252: data segment, you must initialize DS to the segment. Use of a ! 253: group (such as DGROUP) is optional. For example: ! 254: ! 255: _DATA SEGMENT WORD PUBLIC 'DATA' ! 256: . ! 257: . ! 258: . ! 259: _DATA ENDS ! 260: ! 261: ASSUME ds:_DATA ! 262: . ! 263: . ! 264: . ! 265: mov ax,_DATA ! 266: mov ds,ax ! 267: ! 268: o Under OS/2, only the memory required by the program is allocated. ! 269: Each segment has an allocated size. Data beyond the allocated ! 270: boundary cannot be accessed. On startup, DS and SS are the same-- ! 271: the automatic data segment is used both for data and stack. SP ! 272: and CX point to the end of the allocated automatic data segment. ! 273: CS:IP points to the start of the code segment. ! 274: ! 275: Under DOS, programs attempt to use all of memory on startup. If a ! 276: program needs to allocate dynamic memory, it must first use a DOS ! 277: call to adjust the program's memory allocation to match the ! 278: actual memory use. This is not necessary under OS/2, since the ! 279: operating system automatically allocates only what the program ! 280: needs. ! 281: ! 282: o Under OS/2, segments are actually selectors managed by the ! 283: operating system. They are not tied to actual memory addresses ! 284: and any attempt to do segment arithmetic will fail. All memory ! 285: allocation must be done through operating system calls.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.