<-- /BYTE* / Microsoft Macro Assembler (MASM) Unofficial Changelist 
Microsoft Macro Assembler (MASM) Unofficial Changelist

*LEGAL DISCLAIMER: All references to Microsoft products, including but not limited to: Microsoft Macro Assembler (MASM), MS-DOS, Visual C++, Visual Basic, Visual Studio, Windows, Windows NT, Windows Software Development Kit (SDK) and associated logos or images are trademarks owned and copyright by Microsoft Corporation.

NOTE: If you notice any incorrect version information here or you have information to add, please use the Contact Form!

Before Microsoft's Macro Assembler popularized the acronym MASM, MASM previously meant Meta Assembler (essentially an assembler-generation tool whose application is primarily used in mainframe computing). In the pre-DOS era, there were many macro-style assemblers produced by different companies, primarily targetting mainframes or the newly emerging proprietary chipsets for personal computers or gaming systems. During this time, someone invented the notion of a “macro”, which is essentially a series of keystrokes assigned to a name or keyboard sequence as a time saving construct. In these days, macro support was popular and used in many utilities from spreadsheets to command line shells, not just programming languages. This was at a time where the major programming languages in widespread use today were still under development, so it was common for entire applications to be written purely in assembly language. As programming in assembly language is just one small step above programming directly in machine language (programming in numeric codes), it takes many separate instructions to perform even the most simple tasks such as writing a single character to a display terminal. This is why assembly language is known as a tedious programming language. When used in assembly language, macros enable programmers to assign a group of commonly used instructions to a name and insert those instructions anywhere the name appears in as many places as that common task is needed. Microsoft's Macro Assembler (MASM), initially appearing in 1981 near the release of Microsoft's IBM PC-DOS, is an assembler using the Intel syntax/notation. MASM became the most popular assembler likely due to the success of DOS and Windows. As of this writing, MASM is the oldest IBM PC assembler still being actively developed and supported.

Origins of MASM:
After some guesswork as to the origins of MASM being possibly related to the 8086 Assembler created by Tim Paterson of SCP (Seattle Computer Products), I was able to contact him for his help in clearing things up. Tim Patterson, the original creator of DOS and the famous DEBUG.COM, wrote an 8086 assembler (ASM) to assemble 86-DOS, the predecessor to MS-DOS. Here is what he said:

MASM was written in Pascal by Marc McDonald (Microsoft employee #1, after Bill & Paul). Microsoft had been doing all their development on DEC computers, and the macro capability put in MASM was modeled after DEC assemblers. Because MASM was such a large macro assembler, one of the guys referred to it as "McDonald's big mac".
MASM does not have lineage back to M80. It was written specifically for the 8086 and attempted some level of compatibility with Intel's 8086 assembler. I remember it was different from what I was used to. When MS bought DOS from SCP I was at MS. After finishing up DOS 1.0, I translated DOS from SCP's assembler to MASM, and I needed Marc to explain some of the syntax to me.

He also had the following to say about his 8086 Assembler he wrote while at SCP:

The 8086 assembler I wrote originally was in Z80 assembly language and ran under CP/M. I believe it was distributed with the SCP 8086 CPU card as ASM86. I also wrote a translator that converted Z80 source code to inefficient but workable 8086 source code (Intel promoted this idea with a published translation table). This was called TRANS86 and was also written in Z80 assembly for CP/M. Once DOS was working, I applied the translator to ASM86 (and to itself) to create 8086 versions that ran under DOS. I do not have the change history in front of me (I see you deleted it from your history page), but I believe that versions >= 2 marked the translated (DOS) version. If any history shows version numbers < 2, that was the CP/M version.

Although the SCP 8086 Assembler was used to build early versions of DOS (86-DOS, MS-DOS 1.x), Microsoft's major rewrite of DOS 2.0 included changing the build system to use Microsoft's own assembler, MASM. More information about Tim's 8086 Assembler (ASM) can be found at the Computer History Museum's Microsoft MS-DOS early source code article. From here you may download the now freely available MS-DOS 1.1 and 2.0 source code which includes the source code to Tim's 8086 Assembler and the Z80 to 8086 translator.

Evolution of MASM:
From MASM 1.0 in 1981 (corresponding to the release of MS-DOS 1.0), MASM enjoyed almost 13 years as a distinct Microsoft product. This status was lost with MASM version 6.11 in 1993 where Microsoft stated MASM is no longer available as a retail product. With the popularity of the new and various programming languages available, the demand for people wanting to write in pure assembler declined, so Microsoft followed suit and downgraded MASM to a system-level C/C++ tool. Microsoft would release patches for new versions of MASM (primarily to accommodate changes in Intel's upcoming chipsets) up to version 6.14 in 1999. In the year 2000, the Microsoft released MASM 6.15, not as a patch, but as an add-on to Visual C++ 6.0 and no official changelist was officially published. Since version 6.15, MASM has been bundled with every release of Visual C++ to date (VIA Visual Studio) along with the rest of the C/C++ related command-line toolset.

Version 6.15 is why I created this page. I spent a good deal of time scouring the internet for "official" information on version 6.15, but I found nothing but unofficial tidbits. Figuring I might as well save someone else the hassle, I decided to put this MASM page up and pair the 6.15 findings with the rest of "what changed" in the other 6.x versions (for completeness). As you can tell, this page quickly got out of control. Eventually I added whatever information I could find on all known versions.

I have attempted obtain the most complete version information for Microsoft's MASM throughout its history using official information when available and falling back to bits and pieces from other sources when information is limited. This includes printed manuals, readme's and other information shipping with the product, MSDN content, or other Microsoft websites. When appropriate, opinions and hearsay are also included (and noted as such), as this helps develop a clearer picture of how the product impacted those who used it, circumventing the usual biased rhetoric from official sources.

Changelist for this document
    2017-07-18     * version 12.0: added blurb about the Visual Studio Community Edition debut for Visual Studio 2013

    2017-07-14     * version 8.x added Intel/AMD .686 call-gate instructions

    2017-07-09     * added versions 11.0, 12.0 and 14.0

    2017-04-20     * added info for one of the earliest known MASM386 5.NT.02 variants from an MSDN Win32 DDK
                     CD for NT 3.1 Build 1.239.1; also incorporated it into the summary

    2017-04-05     * version 7.1: quoted "Practical Malware Analysis" book for more SafeSEH details

    2017-04-04     * added "Detect It Easy" results for versions 1.0 IBM, 1.0, 1.06, 1.10, 1.25, 2.04, and 4.0
                     (built using IBM PC Pascal, possibly assembler and Microsoft C)

    2017-03-21     * updated version 6.14 to include that it was additionally bundled with first two XP DDK's for Windows ME
                   * updated version 6.11d to include that it was also the last version (in addition to MS-DOS)
                     that would run under Windows 3.x and quoted a readme from an MSDN VC6 SP5/MASM bundle CD

    2017-03-02     * added MASM386.EXE build 3.50.794.1 (newer) that shipped with the Win32 SDK for NT 3.5 and reworked summary

    2017-02-08     * added unofficial change to MASM 6.13; addition of @comp.id COFF symbol to OBJ files for consistency with other
                     Visual C++ tools to support Microsoft's undocumented "Rich" header.

    2017-01-02     * updated version 9.0 to include that it was distributed with the WDK 7.1.0

    2016-11-03     * MASM 9 summary edited to include that SP1 is required to obtain MASM when using the Express Edition

    2016-11-02     * added first batch of 64-bit assembler info for versions 8, 9 and 10
                   * edited summaries for version 8 (incl. official BETA REFRESH package link), and 10 mostly for 64-bit assembler support
                   * added minimum OS required for versions 6.12, 9 and 10

    2016-11-01     * added OS/2 versions of ML.EXE to 6.0 and 6.00B
                   * designated DOS/Dual Mode executables for 5.10A variations
                   * version 8 summary now emphasizes first public Win64 release for the amd64 architecture (a.k.a. x64, x86-64, EM64T, Intel 64)

    2016-10-09     * added dual-mode executable information for version 5.10 and alternate dates for both
                   * normalized version references from version 5.1 to 5.10

    2016-09-29     * added version 1.06
                   * added "Runs Under" OS column
                   * removed 12:00am time from associated table and version header timestamps where time was unavailable
                   * 2.04 changes: added "SEATTLE COMPUTER Utility" disk, updated timestamps and reworded summary
                   * moved incorrectly placed comment by r_harvey (about MASM386/5.NT.02) from MASM 5.10B to MASM386 5.NT.02 section
                   * normalized version references; where docs and command-line version string differ, we'll give priority to the command-line string:
                        -6.0B to 6.00B 
                        -1.1 to 1.10
    2016-09-08     * 6.0B changes:
                        -added README.DOC
                        -added changelist info from corresponding README.DOC
                        -added OLDSTDCALL (6.0B) to table of Non-Reserved Operands
                        -refactored summary to reflect changes above

                   * this changelist section added! :)

Jump to MASM Version Info / 41 Versions Listed

VersionCopyrightRuns UnderMain Program Date/File/Size@VersionBuild Version
MACRO-801979CPM12/09/1981M80.COM20 k3.4
MASM 1.0 IBM1981DOS12/07/1981 10:00pmMASM.EXE66 k
MASM 1.01981DOS02/05/1982 12:49pmM.EXE66 k
MASM 1.061982DOS02/08/1982MASM.EXE69 k
MASM 1.101982DOS02/01/1983 01:13pmMASM.EXE76 k
MASM 1.251983DOS08/25/1982MASM.EXE79 k
MASM 1.271984DOS11/27/1984 09:25amMASM.EXE79 k
MASM 2.0 IBM1984DOS07/18/1984 12:01pmMASM.EXE75 k
MASM 2.041982DOS03/02/1982MASM.EXE66 k
MASM 3.01984DOS11/21/1984 02:49pmMASM.EXE76 k
MASM 3.011984DOS11/21/1984 02:49pmMASM.EXE76 k
MASM 4.01985DOS10/16/1985 04:00amMASM.EXE84 k
MASM 4.011985DOS07/24/1987 12:00amMASM401.EXE100 k
MASM 5.01987DOS07/31/1987 12:00amMASM.EXE101 k
MASM/2 1.0 IBM1987OS/2,DOS09/03/1987 04:00pmMASM.EXE112 k
MASM 5.101988DOS,OS/202/01/1988 01:00pmMASM.EXE108 k510
MASM 5.10A1989DOS,OS/201/16/1989 11:10amMASM.EXE108 k510
MASM 5.10B1989DOS,OS/201/04/1992 12:52pmMASM5.EXE109 k510
MASM386 5.NT.021989WIN3211/01/1993 06:28amMASM386.EXE207 k5103.10.508.1
MASM 6.01991DOS,OS/204/03/1991 02:59pmML.EXE239 k600
MASM 6.00A
MASM 6.00B1992DOS,OS/203/18/1992 05:31pmML.EXE244 k600
MASM 6.11992DOS,WIN3211/16/1992 04:00pmML.EXE352 k610
MASM 6.1a1992DOS,WIN3203/12/1993 01:59pmML.EXE353 k610
MASM 6.111993DOS,WIN3209/24/1993 08:25amML.EXE380 k611
MASM 6.11a1994DOS,WIN3203/21/1994 12:22pmML.EXE374 k611
MASM 6.11c1994DOS,WIN3208/25/1994 06:30pmML.EXE373 k611
MASM 6.11d1995DOS,WIN3209/19/1995 01:18pmML.EXE379 k611
MASM 6.121997WIN3208/27/1997 03:49pmML.EXE358 k6126.12.7164
MASM 6.131997WIN3212/05/1997 01:43pmML.EXE344 k6136.13.7299
MASM 6.141997WIN3204/12/1999 03:05pmML.EXE364 k6146.14.8444
MASM 6.152000WIN3203/16/2000 03:20pmml.exe376 k6156.15.8803
MASM 7.0WIN3201/05/2002 03:36amml.exe404 k6157.00.9466 / VS.NET 2002 7.0 (any*)
MASM 7.1WIN3207/11/2006 06:15pmml.exe404 k7107.10.6030 / VS.NET 2003 PRO 7.1
MASM 8.0WIN32/6404/21/2006 06:11pmml.exe342 k8008.00.50727.104 / VS 2005 8.0 Express
MASM 9.0WIN32/6407/30/2008 12:05pmml.exe353 k9009.00.30729.01 / VS 2008 9.0 (any*) / Win32
MASM 10.0WIN32/6403/19/2010 02:02pmml.exe388 k100010.00.30319.01 / Win32
MASM 11.0WIN32/6407/26/2012 07:08pmml.exe424 k110011.00.50727.1 / Win32
MASM 12.0WIN32/6410/05/2013 02:38amml.exe429 k120012.00.21005.1 / From VS 2013 Express for Desktop / Win32
MASM 14.0WIN32/6406/25/2015 11:34pmml.exe436 k140014.00.23026.0 / From VS 2015 Community 14.0.23107.0 D14REL / Win32

Jump to Keyword Version Info

Special thanks to Vernon from pcdosretro for sending the version information up to 6.14 in the tables shown below.

Vernon also extracted the MASM 6.0B QuickHelp Documentation into a single text file for quick reference and simple search lookups for the various MASM keywords and operators. Despite being derived from the version 6.00B documentation, the majority of the information still applies to current versions of MASM.

*NOTE: It is to be expected many characters in this file will not display as intended through your web browser, specifically the high-ASCII line drawing characters. If you save the page as a text file and open it in a command prompt under Windows (using "edit", "more" or any other text editor), the high-ASCII characters will display as intended.

Types / Allocation
Macros / Procedures
.ALLOCSTACK (x64)8.0
.ENDPROLOG (x64)8.0
.FPO5.10.NT, 6.11A, 8.0
.PUSHFRAME (x64)8.0
.PUSHREG (x64)8.0
.SAVEREG (x64)8.0
.SAVEXMM128 (x64)8.0
.SETFRAME (x64)8.0
Scope / Module
NAME<=4.0 / ignored 5.0+
Options / Echoing
Equates / Assignment
Repeat Blocks
Conditional Assembly
Conditional Control Flow
Conditional Error
Listing Control
Macro Functions
Control Flow
Logical and Shift
Languages, Models and Registers
Calling conventions
Memory Models
Reserved and Non-reserved operands
Reserved Operands
Non-Reserved Operands (many are used with OPTION directive)

MACRO-80 © 1979
M80.COM20,096 bytes (20k)md5=cb37415442c76354003024e3a7cdeff3date=12/9/1981build 3.4(time of day from file stamp unknown)
M80.COM19,200 bytes (19k)md5=19c63f05a7541b95ff28249e6c913448build 3.4(file date unknown)
Retail Price: $200.00

The original Microsoft assembler product was for the 8080 Intel archtecture typically running the CP/M operating system, predating DOS. Although Tim Paterson (creator of DOS) has confirmed with us that MASM did not originate from MACRO-80, it is included here for historical purposes as it appears to have been Microsoft's first commercial assembler product. According to EMSPS, the list price was $200. The Intel 8080 Wikipedia Page describes the 8-bit 8080 2 MHz microprocessor released in April 1974 as follows:

"The 8080 has sometimes been labeled "the first truly usable microprocessor", although earlier microprocessors were used for calculators, cash registers, computer terminals, industrial robots and other applications. The architecture of the 8080 strongly influenced Intel's 8086 CPU architecture, which spawned the x86 family of processors."

The following snippet is from the TRS-80 Manual: Macro-80 Assembler Introduction:

"MACRO-80 is a relocatable macro assembler for the 8080 and Z80 microcomputer systems. It assembles 8080 or Z80 code on any 8080 or Z80 development system running the CP/M, ISIS-II, TRSDOS or TEKDOS operating system. The MACRO-80 package includes the MACRO-80 assembler, the LINK-*) linking loader, and the CRED-80 cross reference facility. CP/M versions also include the LIB-80 Library Manager. MACRO-80 resides in approximately 14K of memory and has an assembly rate of over 1000 lines per minute.

MACRO-80 incorporates almost all "big computer" assembler features without sacrificing speed or memory space. The assembler supports a complete, Intel standard macro facility, including IRP, IRPC, REPEAT, local variables and EXITM. Nesting of macros is limited only by memory. Code is assembled in relocatable modules that are manipulated with the flexible linking loader. Conditional assembly capability is enhanced by an expanded set of conditional pseudo operations that include testing of assembly pass, symbol definition, and parameters to macros. Conditionals may be nested up to 255 levels."

MACRO-86 © 1981

Microsoft's next assembler (a two-pass assembler) targeted the 8086, a 16-bit microprocessor released by Intel in 1978. This was the first in the series of microprocessors that later became known as the x86 architecture. This was the first Microsoft assembler product for the 8086 architecture. Microsoft's assembler (and main product line) has remained with this architecture to date. Later versions of the assembler would be renamed to "Microsoft MACRO Assembler".

The manual states, "MACRO-86 supports most of the directives found in Microsoft's MACRO-80 Macro Assembler. Macros and conditionals are Intel 8080 standard."

The Microsoft Utility Software Package Reference Manual for 8086 Microprocessors was the primary source for the information shown below.

MACRO-86 was distributed on a single disk along with 4 files: M86.EXE, LINK.EXE, LIB.EXE and CREF.EXE.

    MACRO-86 - 96K bytes of memory minimum:
               64K bytes for code and static data
               32K bytes for run space
    MS-LINK - 54K bytes of memory minimum:
              44K bytes for code
              10K bytes for run space
    MS-LIB - 38K bytes of memory minimum:
             28K bytes for code
             10K bytes for run space
    MS-CREF - 24K bytes of memory minimum:
              14K bytes for code
              10K bytes for run space
    1 disk drive
             1 disk drive if and only if output is sent to the
             same physical diskette from which the input was
             taken.   None of the utility programs in this
             package   allow    time to swap diskettes during
             operation on a one-drive configuration. Therefore,
             two disk drives is a more practical configuration.

MASM 1.0 IBM © 1981 [Command Line / Help]
MASM.EXE67,584 bytes (66k)md5=0c68bde13bf46f813b41fc5b19ed56d8date=12/7/1981 10:00pm

This was an IBM-branded OEM version of MASM developed by Microsoft specifically for the IBM PC, executing only 8086 instructions. Detect It Easy identifies this version as being built with "IBM PC Pascal". Vernon from pcdosretro says this version of MASM supports ESC and an archaic syntax which could be used to specify floating-point opcodes.

The command line displays "The IBM Personal Computer MACRO Assembler" rather than the "The Microsoft MACRO Assembler" displayed by the unbranded Microsoft version. It is not known how much this version differs from the unbranded version although if the file dates we have are correct, the IBM version pre-dates the unbranded version by just about 2 months.

Embedded within MASM.EXE at offset 0xE50D (58637) is the date string:
"8/24/81 Ver"
This may be a possible build timestamp. Although I don't have documentation on this version of MASM, I suspect you can get the program to emit this string one way or another (via the command line or possibly using a predefined macro combined with the old %out directive during assembly). This version date string is not displayed on the command line when MASM is run with no options, but instead the copyright year of 1981.

The IBM versions of MASM also distributed a small companion assembler named ASM.EXE. This assembler lacked some of the features present in MASM.EXE (such as the ability to use macros) so it would run in PCs with only 64k of memory.

The original distribution contains the following directory list of 14 files, on a 160K 5¼ inch floppy disk:
09/24/1981  10:00 PM     137 $$EDASM.BAT
09/24/1981  10:00 PM     140 $$EDMASM.BAT
10/28/1981  10:00 PM     622 $ASML.BAT
10/28/1981  10:00 PM     614 $EDASM.BAT
10/28/1981  10:00 PM     614 $EDMASM.BAT
09/24/1981  10:00 PM      23 $LINK.ARF
10/28/1981  10:00 PM     615 $MASML.BAT
12/07/1981  10:00 PM  52,736 ASM.EXE
10/04/1981  10:00 PM  13,824 CREF.EXE
11/08/1981  10:00 PM   6,580 EXMP1M.ASM
11/08/1981  10:00 PM   5,621 EXMP1S.ASM
09/15/1981  10:00 PM   2,015 EXMP2M.ASM
09/15/1981  10:00 PM   1,861 EXMP2S.ASM
12/07/1981  10:00 PM  67,584 MASM.EXE
NOTE: Like Microsoft's unbranded MASM 1.0 (shown below), DOSBox hangs when the executable is run, although it appears to work fine running in a command window under XP or under a MS-DOS 6.22 environment simulated by VirtualBox. Thanks to Vernon from pcdosretro who offered the following explanation for this behavior:

FCBs are file control blocks which originated with CP/M and were used to access files in DOS 1.x. DOS 2 added file handle support so FCB usage was quickly deprecated but maintained in all successive versions of DOS. FILES and FCBS were CONFIG.SYS statements to specify how many system file tables (FILES) and FCB system file tables (FCBS) were allocated. I'm guessing that DOSbox doesn't properly support FCBS since very few if any DOS games used them.

MASM IBM 1.0 Disk
MASM IBM 1.0 Disk

MASM 1.0 © 1981 [Command Line / Help]
M.EXE67,840 bytes (66k)md5=82e78c6a076a3c581c5df33bc7766de8date=2/5/1982 12:49pm(file time of day may not be official)

This version likely supports the same features as the IBM branded version. Also like the IBM version, Detect It Easy identifies this version as being built with "IBM PC Pascal". The directory listing of the 160k distribution disk is as follows (courtesy of pcjs.org):
 Volume in drive A has no label

Directory of A:\

M        EXE     67840 02-05-82  12:49p
LINK     EXE     41216 02-04-82   1:47p
        2 file(s)     109056 bytes

Total files listed:
        2 file(s)     109056 bytes
                       50688 bytes free
When this version is run with no command line options, the name the MASM reports to the console is "The Microsoft MACRO Assembler". This name appears in all of the 1.xx series versions (at least those known on this page). Successive versions dropped the leading "The" resulting in "Microsoft MACRO Assembler". This internal name would change slightly once more in version 4.0 to "Microsoft (R) Macro Assembler", which would stick for all future versions.

Embedded within the oddly-named executable (M.EXE, the only version of MASM I'm aware of with this short name) at offset 0xED83 (60803) is the identical date string we saw in the IBM branded MASM:
"8/24/81 Ver"
The file dates listed here (see below) differ by almost 6 months. Also like the IBM version, this date string is not displayed on the command line when MASM is run with no options.

Two separate distributions I've seen of the plain (non OEM IBM) Microsoft MASM 1.0 have identical file content but differing timestamps. The timestamps are identical except for being off by two hours (a time zone difference perhaps); the time stamps between the versions of LINK.EXE were also off by two hours. This might be viewed as an indication of an official release date since two archives had the same day in common... or not.

Mainstream Distribution (consistent with directory listing above):
    02/05/1982  12:49 PM  67,840 M.EXE
    02/04/1982  01:47 PM  41,216 LINK.EXE
Alternate Distribution:
    02/05/1982  10:49 AM  67,840 M.EXE
    02/04/1982  11:47 AM  41,216 LINK.EXE
Although this version of MASM appears to run under XP, it hangs when run under DOSBox just as the IBM-branded version does. See the explanation in the MASM 1.0 IBM section.

According to reports, this version was compatible with IBM PC-DOS 1.0.

  • IBM PC-DOS 1.0 and later

MASM 1.06 © 1981,82 [Command Line / Help]
MASM.EXE70,784 bytes (69k)md5=9446dcc509686be2772bf9c852a5df5bdate=2/8/1982(from date embedded within executable)

I haven't found any public information about this version. It may also be an internal or unofficial release. Similar to all prior 1.x versions, Detect It Easy identifies this version as being built with "IBM PC Pascal". Vernon from pcdosretro said it definitely falls in between versions 1.0 and 1.1 as it has floating-point support but does not yet support DOS 2+ file handles. Like MASM 1.0 it only supports /D /O /X.

The archive I found this in was bundled with the same LINK.EXE that came with version 1.10.

MASM 1.10 © 1981,82 [Command Line / Help]
MASM.EXE77,440 bytes (76k)md5=a9f9df1d0afd30c46f8facffffc72c64date=2/1/1983 1:13pm(file from MS-DOS source code)

This was the first version to support the 8087 opcodes. Similar to all prior 1.x versions, Detect It Easy identifies this version as being built with "IBM PC Pascal". File handles were also supported if running DOS 2.0 or higher (clearly Microsoft had already added file handle support to the in-development DOS 2.0 at that point).

Little public information is available about this version, however it can be downloaded free along with the rest of the MS-DOS 1.1 and 2.0 operating system source code as of early 2014.

The link below leads you to an article where the source code archive can be downloaded. This archive contains MASM 1.10 (found as v20object/MASM.EXE), reportedly used to compile the MS-DOS 2.0 source code (in the v20source directory) according to computerhistory.org. Version 2.0 of MS-DOS (the version MASM 1.10 was to compile) was the first version of DOS to support subdirectories, hard disks, device drivers, TSRs (terminate and stay resident programs), file redirection and 360k floppy disks (versus the previously supported 320k floppies).

Microsoft, while retaining the MS-DOS rights throughout the years, has released the source code to the Computer History Museum (computerhistory.org) making it freely available to all for non-commercial use. The source code can be downloaded directly from the Microsoft MS-DOS early source code article. After accepting the agreement, you will download: msdos.zip size=888958 (869K) md5=1687f7bcc762aac46aabf9d18fdc7622.

The changelist below was derived from Vernon of pcdosretro.

  • Support for the Intel 8087 opcodes (coprocessor) via the /R switch
  • Support for DOS 2.0+ file handles / verified with an INT 21h function tracer

MASM 1.25 © 1981,82,83 [Command Line / Help]
MASM.EXE80,856 bytes (79k)md5=2d7c908056d8e9ce4de37ca2df416aa4date=8/25/1982(from date embedded within executable)

Little public information is available about this version. Starting with this version, it appears "IBM PC Pascal" was no longer used to build MASM according to Detect It Easy as no signature was recognized (it may have been ported to assembler). It is not until version 4.0 that the MASM EXE signatures change again as originating from Microsoft C.

The command line display for versions 1.25 and 1.27 are somewhat unique amongst the MASM series. The command line displays spaces surrounding the comma between the name and the version, which looks odd. These versions also center the copyright line which is not done in any other known versions.

This version was referenced by Microsoft in KB24953 and Q24962.

The original file date stamp was not preserved, but embedded internally within the executable at offset 0x10BC7 (68551) is the string:
"8/25/82 Ver"
For this version of MASM, this was the only accurate date information available to me.

The changelist below was derived from Vernon of pcdosretro.

  • Floating point emulation support (via the /E switch), causing the resulting .OBJ file to have an external reference to FIDRQQ and additional fixups.

MASM 1.27 © 1981,1984 [Command Line]
MASM.EXE81,280 bytes (79k)md5=6a036d58988a65dbcae927005f5a26cfdate=11/27/1984 9:25am(from ACT/Apricot BETA Programmer's Toolkit)

Little public information was previously available about this version until it surfaced in the ACT/Apricot archive on a disk labeled:

This was an Apricot/Xi RAM BIOS boot disk including the MS-DOS versions of MASM, LINK, LIB, CREF, EXE2BIN and DEBUG utilities. This disk did include a README.DOC which was the source of the changelist information below. It appears this was the first version of MASM to be distributed with a README document. Also included within the README was changelist information for LINK 2.44 and LIB 2.20. Although the LIB version on the disk matched, the disk only included LINK 2.30.

The command line display for versions 1.25 and 1.27 are somewhat unique amongst the MASM series. The command line displays spaces surrounding the comma between the name and the version, which looks odd. These versions also center the copyright line which is not done in any other known versions.

The version 3.0 README.DOC hints that 1.27 may have been the predecessor to 3.0 (at least for non-IBM versions of MASM).

  • IFB & IFNB have been corrected
  • Recognizes memory greater than 512K
  • fsubr, fdiv & fdivr have been corrected

MASM 2.0 IBM © 1981, 1983, 1984 [Command Line / Help]
MASM.EXE76,544 bytes (75k)md5=3bd07c55ce4161e0a644f0e8f870e8e3date=7/18/1984 12:01pm

This was the last DOS-only version Microsoft made with the IBM brand. Future versions of MASM would be Microsoft-only with exception of IBM's 1.0 "Assembler/2" which was a rebranded MASM 4.0 with OS/2 support 3 years later.

According to the PC Magazine article below, this version came with a manual that was one of the best instruction set references (of the time) in the opinion of the writer. This was reportedly a solid version that was the "top choice in the field" due to the added stability of bugfixes, a 2-volume manual that was reported as one of the best instruction set references at the time, and the inclusion of the LIB tool. This version fixed some problems with the SHR and SHL pesudo-op instructions and improved type-checking. The author of the article found the in-depth inclusion of the SALUT tool in the manual (38 pages), was misplaced, especially with no documentation beyond the command line-syntax for much-needed LIB tool. IBM SALUT, written by Scott T Jones, stood for Structured Assembly Language Utilities; it essentially allowed the inclusion of structured flow-controlling statements into assembly language programs that output .ASM files. According to the author, it was a "wimpy preprocessor" written in BASIC. Microsoft must have realized this as SALUT never showed up again in any Microsoft MASM releases, though IBM's MASM 1.0 for OS/2 (3 years later) included the last known version.

MASM 3.0 was released 4 months from this release (based on the file dates). This is also confirmed on page 137 of the article.

The changelist was derived from Vernon of pcdosretro and the October 1985 PC magazine article below.

  • 186, 286 and 287 instruction support (.186, .286c and .287 directives)
    Analysis of the binary showed 286 protected-mode instructions in the instruction tables but can't actually be used as there is no .286p directive (wouldn't be present until version 3.0)
  • SHR and SHL pesudo-op instructions fixed
  • LIB tool added
  • IBM SALUT tool added
Article: Assembly, a Devilishly Difficult Language will Reward You
Review of IBM MASM 2.0, Microsoft's MASM 3.0 and Phoenix BIOS' Pasm86
PC Magazine
October 29, 1985
Assembler, a Devilishly Difficult Language will Reward You / MASM 2.0 p1 Assembler, a Devilishly Difficult Language will Reward You / MASM 2.0 p2 Assembler, a Devilishly Difficult Language will Reward You / MASM 2.0 p3 Assembler, a Devilishly Difficult Language will Reward You / MASM 3.0 p4 Assembler, a Devilishly Difficult Language will Reward You / MASM 3.0 p5 Assembler, a Devilishly Difficult Language will Reward You / MASM 3.0 p6

MASM 2.04 © 1982 [Command Line]
MASM.EXE67,968 bytes (66k)md5=8e97eff1ceb2a0120188b8d855e125cfdate=3/2/1982(from date embedded within executable)

This version was found in at least two distribution sets, so more branded sets probably exist:
  • An MS-DOS 1.25 distribution OEM branded for Columbia Data Products R2.11 for their MPC 1600 and VP computers / timestamp 3/15/1982 10:00pm
  • A disk labeled "SEATTLE COMPUTER Utility Software Package Version 2.04 March 1982" / timestamp 3/16/1982 2:17pm
Despite appearing to be in the MASM version 2 series, this version has a copyright year and file date placing it around the 1.0 timeframe. Also similar to all versions prior to 1.25, Detect It Easy identifies this version as being built with "IBM PC Pascal".

  • According to Vernon from pcdosretro, this version of MASM appears to have only been called 2.04 to match the overall utility software package(s) as it is not technically in the MASM 2.x series. This version is clearly a rebranded MASM 1.0 as its features predate even those present in MASM 1.10.

MASM 3.0 © 1981, 1983, 1984 [Command Line / Help]
MASM.EXE77,362 bytes (76k)md5=3ba4307324e6595fe2dcf621b21f0b15date=11/21/1984 2:49pm

This version of MASM indicates in its README.DOC that it is "a significantly enhanced version of Microsoft Macro Assembler Package v 1.27". This indicates that after version 1.27, Microsoft's version numbering likely skipped directly to 3.0, and that a non-IBM MASM 2.0 never existed. I was never able to find a reference to a version 2.0 either, officially or unofficially.

The directory listing of the 360k distribution disk is as follows (courtesy of pcjs.org):
 Volume in drive A has no label

Directory of A:\

MASM     EXE     77362 11-21-84   2:49p
SYMDEB   EXE     27136 12-07-84   1:39p
MAPSYM   EXE     17290 11-09-84   4:22p
CREF     EXE     10544 11-21-84   2:51p
LINK     EXE     41114 11-14-84   2:48p
LIB      EXE     24138 10-31-84   4:57p
MAKE     EXE     18675 08-13-84   1:24a
README   DOC      4085 12-07-84   2:30p
        8 file(s)     220344 bytes

Total files listed:
        8 file(s)     220344 bytes
                      138240 bytes free
This appeared to be the 2nd version of MASM to be distributed with a README.DOC (1.27 was the first). Since I have found two different distributions of MASM 3.0, both with the exact Nov 1984 date (matching the copyright), I believe the file timestamp is the original released version.

On the command line, Microsoft abandoned the previously named "The Microsoft MACRO Assembler" for the more concise "Microsoft MACRO Assembler" the 3.xx versions.

In the October 1985 PC Magazine Article (above), the author claimed the Microsoft manual was a "disaster" for this version, in comparison with the IBM MASM 2.0 manual. It was reportedly "badly printed" and only documented each instruction by exactly one line of text. In contrast, the IBM MASM 2.0 manual was a 2 volume reference and was reported as "simply the best reference source" for 8086/8088 instructions. However, the Microsoft manual was applauded in its more in-depth discussion of the LIB tool beyond the command line syntax. The inclusion of the SYMDEB tool was hailed as the "jewel" of this release, noting that Microsoft's MASM was the only place you could get it and the primary reason for his purchase. SYMDEB was good for debugging programs written with other Microsoft language compilers such as C, FORTRAN and Pascal.

The changelist below was derived from the website: pcdosretro.

  • Support for the Intel 80286 (286) protected-mode instruction set (via the .286p directive)
  • Introduction of the MAKE, SYMDEB and MAPSYM utilities

MASM 3.01 © 1981, 1983, 1984 [Command Line / Help]
MASM.EXE77,362 bytes (76k)md5=3ba4307324e6595fe2dcf621b21f0b15date=11/21/1984 2:49pm

The actual MASM.EXE binary is identical to the 3.0 version with the 11/21/1984 date (note the identical file hashes). Version 3.01 represents what Microsoft calls a "Technical Update" of version 3.0 which only contains changes to MAPSYM and SYMDEB as identified in the README.DOC.

The directory listing of the 360k distribution disk is as follows (courtesy of pcjs.org):
 Volume in drive A has no label

Directory of A:\

MASM     EXE     77362 11-21-84   2:49p
LINK     EXE     41114 11-14-84   2:48p
SYMDEB   EXE     36538 06-07-85   4:26p
MAPSYM   EXE     51904 06-21-85  10:21a
CREF     EXE     10544 11-21-84   2:51p
LIB      EXE     24138 10-31-84   4:57p
MAKE     EXE     18675 08-13-84   1:24a
README   DOC     22986 06-21-85  10:03a
        8 file(s)     283261 bytes

Total files listed:
        8 file(s)     283261 bytes
                       74752 bytes free
  • Modifications to the SYMDEB and MAPSYM utilities (described in the README.DOC)

MASM 4.0 © 1985 [Command Line / Help]
MASM.EXE85,566 bytes (84k)md5=51dc11f7a303f3d25809e5e9f36d05ebdate=10/16/1985 4:00am

The directory listing of the 360k distribution disk is as follows (courtesy of pcjs.org):
 Volume in drive A has no label

Directory of A:\

MASM     EXE     85566 10-16-85   4:00a
LINK     EXE     43988 10-16-85   4:00a
SYMDEB   EXE     37021 10-16-85   4:00a
MAPSYM   EXE     18026 10-16-85   4:00a
CREF     EXE     15028 10-16-85   4:00a
LIB      EXE     28716 10-16-85   4:00a
MAKE     EXE     24300 10-16-85   4:00a
EXEPACK  EXE     10848 10-16-85   4:00a
EXEMOD   EXE     11034 10-16-85   4:00a
COUNT    ASM      5965 10-16-85   4:00a
README   DOC      7630 10-16-85   4:00a <--View Readme
       11 file(s)     288122 bytes

Total files listed:
       11 file(s)     288122 bytes
                       69632 bytes free
This version was also included in the TOOLS directory of the Microsoft MS-DOS 3.3 OEM Adaptation Kit (OAK), described in its README as "masm.exe from Retail Macro Assember 4.00 Product". This version of MASM didn't include an installation program, as it was meant to be copied to a working floppy (or hard drive) and run as-is.

This was the last version of MASM to ship with the manuals in the form of a 3-ring binder. The manuals in version 5.0 and up were released as soft-bound booklets. This was also the last version of MASM that did not have the capability to display its own command line options. The information listed in the New Features section from version 4.0 User's Guide is listed below. The section opened with this blurb:

Version 4.0 of the Microsoft Macro Assembler (MASM) has been optimized to improve performance. It now assembles code two to three times faster than any prior release. In addition, the input/output buffers and macro text have been moved out of the symbol space, allowing assembly of larger source files.

This was the first version of MASM to be written in Microsoft C as indicated in the Microsoft Languages Newsletter below as well as EXE dectection tools such as Detect It Easy. Previous versions up to 1.10 have "IBM PC Pascal" signatures. A binary analysis of this version also shows evidence of linking with the C-Runtime libraries.

This version of MASM changed the name reported on the command line. The name changed from:
"Microsoft MACRO Assembler"
from version 3.0 to:
"Microsoft (R) Macro Assembler"
Microsoft kept the new name for all future versions.

  • A computer with one of the 8086/80186/80286 family of microprocessors
  • Version 2.0 or later of the MS-DOS® or PC-DOS operating system (The manual also says "Since these two operating systems are essentially the same, this manual uses the term MS-DOS to include both variations")
  • 128K memory (The Shell command (!) of SYMDEB may require more memory)
  • One double-sided disk drive (two floppy drives or one floppy with a hard disk recommended)
  • A text editor capable of producing ASCII format files with no control codes
  • New Conditional Error Directives:
    These directives allow you to check parameters, boundaries, and other assembly-time values, and generate an error if predefined conditions are not true.
  • Listing File Format Changes:
    The format of the listing files produced by MASM has changed in several ways. Several new exit codes have been added.
  • New Options for MASM:
    The following command-line options have been added:

    /Bnumber- Sets the file buffer to any size between 1K and 63K in order to minimize disk access.
    /C- Creates a cross-reference file.
    /L- Creates an assembly listing.
    /Dsymbol- Defines a symbol (for conditional directives) from the command line or from prompts when starting MASM.
    /Ipath- Sets path by which assembler will search for files specified with an INCLUDE directive.
    /N- Suppresses symbol table in listing.
    /P- Checks for impure code that would cause problems in 80286 protected mode.
    /T- Suppresses all messages if no errors are encountered.
    /V- Displays extra statistics to the screen after assembly.
    /Z- Displays source lines containing errors on the screen (without the option, only the error message is shown). Previous versions of MASM always showed both source line and error message.
  • The command line option /O(Octal) was removed as it is no longer supported.
  • Linker Changes:
    LINK has two new options: the /EXEPACK option allows you to pack executable files during linking, while the /HELP option allows you to see a list of LINK options. In addition, LINK has been optimized to make linking faster.
  • New Options for SYMDEB:
    The following command-line options have been added:

    /K- Enables SCROLL LOCK or BREAK key as an interactive break-point key.
    /N- Enables non-maskable interrupt break systems for non-IBM computers.
    /S- Enables screen swapping between SYMDEB screen and a program screen.
    /"commands"- Executes the specified commands on start-up.

    Undocumented SYMDEB Options (versions 3.0 and 4.0) (courtesy of Vernon at pcdosretro):
    /D- don't assume computer is IBM compatible
    /F- ignore .SYM file
    /R- stay resident when SYMDEB exits
  • CREF Changes:
    CREF now uses all available memory space, allowing the program to process larger cross-reference files.
  • MAKE Changes:
    Two new capabilities and several options have been added to the MAKE utility. MAKE now supports macro definitions and inference rules.
  • Introduction of Two New Utilities:
    EXEPACK- allows you to pack executable files.
    EXEMOD- allows you to modify the MS-DOS file header of .EXE files.
  • Within a couple months of the MASM 4.0 release, Microsoft published a utility to allow redirection of the standard error device for use with MASM.EXE. This allowed the screen output in its entirety (errors and all) to be sent to another display device such as a printer. This redirection worked pre-4.0, but no longer worked with version 4.0. View the document (README / file_date=12/11/1985) or download the whole MASMFIX4.ZIP package consisting of 6 files.
  • According to a circulating document (named MASM4FIX.DOC / file_date=11/20/1986), Microsoft released manual patching instructions to address some problems MASM had with INCLUDE files. The document also contains a "homebrew" patch, to address the inability of MASM to redirect errors sent to the CRT.
  • Eric Cohane put together a document (named MASM.DOC) dated 1/31/1986 whose purpose is to "accumulate comments pertaining to the Microsoft Macro Assembler version 4.0 documentation that appear to be confusing, misleading, or difficult to reconcile with experience with the assembler."
  • Borland's Roger Schlafly created a bug list (named MASM400.BUG / file_date=5/11/1986)
MASM 4.0 Manual and 360K Disk Images
MASM 4.0 360k Disk MASM 4.0 Disk and Manual in Binder

Vintage MASM ad from Computer Language magazine
Issue 11 - July 1985 (presumably version 4.0)
vintage masm advertisement from computer language magazine

Microsoft Languages Newsletters published in PC Tech Journal
Snippets About MASM 4.0
(Images Courtesy of pcjs.org)
News that MASM 4.0 Written in Microsoft C
Jan 1986
MASM Rewritten in C
News that MASM 4.0 Good for Cullinet Mainframe Software
May 1986
Good for Mainframe Software
News of MASM 4.0 Absolute Value Optimization Tip
May 1987
Absolute Value Tip

MASM 4.01 © 1985 [Command Line]
MASM401.EXE102,120 bytes (100k)md5=1361f99163ec397dbaaa8e36335b8ca2date=7/24/1987 12:00am

This obscure version version appeared in the TOOLS directory of the Microsoft MS-DOS 3.3 OEM Adaptation Kit (OAK). The OAK's README had the following description: "masm401.exe special masm used to build IO.SYS". It is not known if this version appeared anywhere else, but this version was 16K larger than vesion 4.0!

MASM 5.0 © 1981-1985, 1987 [Command Line / Help]
MASM.EXE103,175 bytes (101k)md5=781113d15ee597108af0cde54bd1698ddate=7/31/1987 12:00am
Retail Price: $150.00

This was the first version of MASM capable of displaying its own help from the command line when run with the /H option. Additionally, it added support for the 80386 (i386) processor released by Intel in October of 1985.

Intel 80386 Processor

This was also the first version of MASM to be distributed with nicely bound printed manuals (not spiral). The first disk of the two disk distribution (5¼ inch floppies) included the file PACKING.LST (shown below) illustrating the pre-install contents of the disks:
The following documentation pieces are provided with the Macro

  Macro Assembler Programmer's Guide
  Macro Assembler Reference
  CodeView and Utilities Guide
  Mixed-Language Programming Guide
  CodeView Keyboard Templates
      Old-style keyboard
      New-style keyboard

The following files are provided with the Macro Assembler:

Disk 1 Root         Disk 1 \MIXED        Disk 2 Root

  WHAT.ASM            BA.ASM               PAGER.ASM
  RUNME.BAT           CA.ASM               SHOW.ASM
  SETUP.BAT           FA.ASM               DEMO.BAT
  SETUP2.BAT          PA.ASM               RUNME.BAT
  README.DOC          POWER2.ASM           E_AUTO.CV
  CREF.EXE            BAMAIN.BAS           M_AUTO.CV
  ERROUT.EXE          CAMAIN.C             Q_AUTO.CV
  EXEMOD.EXE          FAMAIN.FOR           U_AUTO.CV
  LIB.EXE             PAMAIN.PAS           W_AUTO.CV
  LINK.EXE            MIXED.DOC            CV.HLP
  MAKE.EXE            MIXED.INC            CV.EXE
  MASM.EXE                                 EXEPACK.EXE
  SETENV.EXE                               SHOW.EXE
  SHOW.EXE                                 WHAT.EXE
  WHAT.EXE                                 MACRO.DOC
  PACKING.LST                              BIOS.INC
  \MIXED                                   DOS.INC
All 45 files on both disks had the date of midnight, July 31, 1987. The README.DOC was a source of some of the new features listed below as some of the late breaking features apparently did not make it into the manual. According to Dr. Dobbs: Examining Room / Feb 1, 1988, the price for MASM 5.0 was $150.

The Introduction page had this to say in the Version 5.0 Programmer's Guide:

Welcome to the Microsoft® Macro Assembler (MASM). This package provides all the tools you need to create assembly-language programs.

The Macro Assembler provides a logical programming syntax suited to the segmented architecture of the 8086, 8088, 80186, 80188, 80286, and 80386 microprocessors (8086-family), and the 8087, 80287, and 80387 math coprocessors (8087-family).

The assembler produces relocatable object modules from assembly-language source files. These object modules can be linked using LINK, the Microsoft Overlay Linker, to create executable programs for the MS-DOS® operating system. Object modules created with MASM are compatible with many high-level-language object modules, including those created with the Microsoft BASIC, C, FORTRAN, and Pascal compilers.

MASM has a variety of standard features that make program development easier:
• It has a full set of macro directives.
• It allows conditional assembly of portions of a source file
• It supports a wide range of operators for creating complex assembly-time expressions.
• It carries out strict syntax checking of all instruction statements, including strong typing for memory operands.

Most of the information below was derived from the "New Features" section of the Introduction and "Appendix A: New Features" from the Version 5.0 Programmer's Guide.

  • A computer with one of the 8086-family processors (PC or PS/2 and compatibles)
  • MS-DOS or IBM® PC-DOS Version 2.0 or later (The manual indicates these distributions of DOS are "essentially the same")
  • 192K memory / CodeView debugger requires at least 320K
  • Dr. Dobbs said: 256K minimum memory and hard disk recommended
  • Support for the Intel 386 (80386) processor:
    All instructions and addressing modes of the 80386 processor and 80387 coprocessor are now supported. The 80386 processor is a superset of other 8086-family processors. Most new features are simply 32-bit extensions of 16-bit features. If you understand the features of the 16-bit 8086-family processors, then using the 32-bit extensions is not difficult. The new 32-bit registers are used in much the same way as the 16-bit registers. However, some features of the 80386 processor are significantly different. Areas of particular importance include the .386 directive for initializing the 80386, the USE32 and USE16 segment types for setting the segment word size, and indirect addressing modes. The 8038 processor and the 80387 coprocessor also have these new instructions listed below:

    Bit Scan Forward- BSF
    Bit Scan Reverse- BSR
    Bit Test- BT
    Bit Test and Complement- BTC
    Bit Test and Reset- BTR
    Bit Test and Set- BTS
    Move with Sign Extend- MOVSX
    Move with Zero Extend- MOVZX
    Set Byte on Condition- SET condition
    Double Precision Shift Left- SHLD
    Double Precision Shift Right- SHRD
    Move to/from Special Registers- MOV
    Sine- FSIN
    Cosine- FCOS
    Sine Cosine- FSINCOS
    IEEE Partial Remainder- FPREM1
    Unordered Compare Real- FUCOM
    Unordered Compare Real and Pop- FUCOMP
    Unordered Compare Real and Pop Twice- FUCOMPP
  • New segment directives allow simplified segment definitions (New Memory Model support):
    A new system of defining segments is available in MASM Version 5.0. These optional directives implement the segment conventions used in Microsoft high-level languages. The simplified segment directives use the Microsoft naming conventions. If you are willing to accept these conventions, segments can be defined more easily and consistently. However, this feature is optional. You can still use the old system if you need more direct control over segments or if you need to be consistent with existing code. When you use simplified segment directives, ASSUME and GROUP statements that are consistent with Microsoft conventions are generated automatically.

    NOTE: The simplified segment directives cannot be used for programs written in the .COM format. You must specifically define the single segment required for this format.

    A new DOSSEG directive enables you to specify DOS segment order in the source file. This directive is equivalent to the /DOSSEG option of the linker.

    [bytepointer.com edit] What is not explicitly mentioned in the official changelist is that version 5.0 introduced the .MODEL and .CODE directives, two significant directives seen in almost all modern assembly language source code files. The memory model and simplified segment directive information below was copied from the 5.0 manual from various portions of sections 5.1.1. thru 5.1.7:

    Memory Models:
      To use simplified segment directives, you must declare a memory model for your program. The memory model specifies the default size of data and code used in a program. Microsoft high-level languages require that each program have a default size (or memory model). Any assembly-language routine called from a high-level-language program should have the same memory model as the calling program.

      The .MODEL directive is used to initialize the memory model. This directive should be used early in the source code before any other segment directive. If one of the other simplified segment directives (such as .CODE or .DATA) is given before the .MODEL directive, an error is generated.

      • Syntax
      .MODEL memorymodel
      The memorymodel can be SMALL, MEDIUM, COMPACT, LARGE, or HUGE. Segments are defined the same for large and huge models, but the @datasize equate is different.

      The most common memory models are described below:

      Model  Description
      Tiny All data and code fits in a single segment. Tiny model programs must be written in the .COM format. Microsoft languages do not support this model. Some compilers from other companies support tiny model either as an option or as a requirement. You cannot use simplified segment directives for tiny-model programs.
      Small All data fits within a single 64K segment, and all code fits within a 64K segment. Therefore, all code and data can be accessed as near. This is the most common model for stand-alone assembler programs. C is the only Microsoft language that supports this model.
      Medium All data fits within a single 64K segment, but code may be greater than 64K. Therefore, data is near, but code is far. Most recent versions of Microsoft languages support this model.
      Compact All code fits within a single 64K segment, but the total amount of data may be greater than 64K (although no array can be larger than 64K). Therefore code is near, but data if far. C is the only Microsoft language that supports this model.
      Large Both code and data may be greater than 64K (although no array can be larger than 64K). Therefore, both code and data are far. All Microsoft languages support this model.
      Huge Both code and data may be greater than 64K. In addition, data arrays may be larger than 64K. Both code and data are far, and pointers to elements within an array must also be far. Most recent versions of Microsoft languages support this model. Segments are the same for large and huge models.

      [bytepointer.com edit] It is interesting Microsoft mentions the tiny model. Microsoft was clear that "Some compilers from other companies support tiny model" indicating Microsoft might not have coined the term, but was aware of it. Microsoft eventually followed suit 4 years later and in version 6.0, added support for the tiny model, using simplified segment directives.

      Stand-alone assembler programs can have any model. Small model is adequate for most programs written entirely in assembly language. Since near data or code can be accessed more quickly, the smallest memory model that can accommodate your code and data is usually the most efficient.

      Mixed-model programs use the default size for most code and data but override the default for particular data items. Stand-alone assembler programs can be written as mixed-model programs by making specific procedures or variables near or far. Some Microsoft high-level languages have NEAR, FAR, and HUGE keywords that enable you to override the default size of individual data or code items.

      If you are writing an assembler routine for a high-level language, the memory model should match the memory model used by the compiler or interpreter. If you are writing a stand-alone assembler program, you can use any model. Small model is the best choice for most stand-alone assembler programs.

      • Example 1
      .MODEL  small
      This statement defines default segments for small-model programs and creates the ASSUME and GROUP statements used by small-model programs. The segments are automatically ordered according to the Microsoft convention. The example statements might be used at the start of the main (or only) module of a stand-alone assembler program.

      • Example 2
      This statement defines default segments for large-model programs and creates the ASSUME and GROUP statements used by large-model programs. It does not automatically order segments according to the Microsoft convention. The example statement might be used at the start of an assembly module that would be called from a large-model C, BASIC, FORTRAN, or Pascal program.

      • 80386 Only

      If you use the .386 directive before the .MODEL directive, the segment definitions defines 32-bit segments. If you want to enable the 80386 processor with 16-bit segments, you should give the .386 directive after the .MODEL directive.

    Specifying DOS Segment Order:
      The DOSSEG directive specifies that segments be ordered according to the DOS segment-order convention. This is the convention used by Microsoft high-level-language compilers.

      • Syntax
      Using the DOSSEG directive enables you to maintain a consistent logical segment order without actually defining segments in that order in your source file. Without this directive, the final segment order of the executable file depends on a variety of factors, such as segment order, class name, and order of linking.

      Since segment order is not crucial to the proper functioning of most stand-alone assembler programs, you can simply use the DOSSEG directive and ignore the whole issue of segment order.

      NOTE: Using the DOSSEG directive (or the /DOSSEG linker option) has two side effects. The linker generates symbols called _end and _edata. You should not use these names in programs that contain the DOSSEG directive. Also, the linker increases the offset of the first byte of the code segment by 16 bytes in small and compact models. This is to give proper alignment to executable files created with Microsoft compilers.

      If you want to use the DOS segment-order convention in stand-alone assembler programs, you should use the DOSSEG argument in the main module. Modules called from the main module need not use the DOSSEG directive. You do not need to use the DOSSEG directive for modules called from Microsoft high-level languages, since the compiler already defines DOS segment order.

      Under the DOS segment-order convention, segments have the following order:
      1. All segment names having the class name 'CODE'
      2. Any segments that do not have class name 'CODE' and are not part of the group DGROUP
      3. Segments that are part of DGROUP, in the following order:

        a. Any segments of class BEGDATA (this class name is reserved for Microsoft use)
        b. Any segments not of class BEGDATA, BSS, or STACK
        c. Segments of class BSS d. Segments of class STACK
      Using the DOSSEG directive has the same effect as using the /DOSSEG linker option.

      The directive works by writing to the comment record of the object file. The Intel title for this record is COMENT. If the linker detects a certain sequence of bytes in this record, it automatically puts segments in the DOS order.

    New Predefined Equates:
    • @curseg: This name has the segment name of the current segment. This value may be convenient for ASSUME statements, segment overrides, or other cases in which you need to access the current segment. It can also be used to end a segment, as show below:
      @curseg ENDS    ; End current segment
              .286    ; Must be outside segment
              .CODE   ; Restart segment
    • @filename: This value represents the base name of the current source file. For example, if the current source file is task.asm, the value of @filename is task. This value can be used in any name you would like to change if the file name changes. For example, it can be used as procedure name:
      @filename   PROC
      @filename   ENDP
    • @codesize and @datasize: If the .MODEL directive has been used, the @codesize value is 0 for small and compact models or 1 for medium, large, and huge models. The @datasize value is 0 for small and medium models, 1 for compact and large models, and 2 for huge models. These values can be used in conditional-assembly statements:
      IF      @datasize
      les     bx,pointer          ; Load far pointer
      mov     ax,es:WORD PTR [bx]
      mov     bx,WORD PTR pointer ; Load near pointer
      mov     ax,WORD PTR [bx]
    • @code, @data, etc.: For each of the primary segment directives, there is a corresponding equate with the same name, except that the equate starts with an at sign (@) but the directive starts with a period. For example, the @code equate represents the segment name defined by the .CODE directive. Similarly, @fardata represents the .FARDATA segment name and @fardata? represents the .FARDATA? segment name. The @data equate represents the group name shared by all the near data segments. It can be used to access the segments created by the .DATA, .DATA?, .CONST, and .STACK segments.

      These equates can be used in ASSUME statements and at any other time a segment must be referred to by name, for example:
      ASSUME es:@fardata ; Assume ES to far data
                         ;   (.MODEL handles DS)
      mov    ax,@data    ; Initialize near to DS
      mov    ds,ax
      mov    ax,@fardata ; Initialize far to ES
      mov    es,ax
    • NOTE: Although predefined equates are part of the simplified segment system, the @curseg and @filename equates are also available when using full segment definitions.

    Defining Simplified Segments:
      The .CODE, .DATA, .DATA?, .FARDATA, .FARDATA?, .CONST, and .STACK directives indicate the start of a segment. They also end any open segment definition used earlier in the source code.

      • Syntax
      .STACK [size]       Stack segment
      .CODE [name]        Code segment
      .DATA               Initialized near-data segment
      .DATA?              Uninitialized near-data segment
      .FARDATA [name]     Initialized far-data segment
      .FARDATA? [name]    Uninitialized far-data segment
      .CONST              Constant-data segment
      For segments that take an optional name, a default name is used if none is specified. Each new segment directive ends the previous segment. The END directive closes the last open segment in the source file.

      The size argument of the .STACK directive is the number of bytes to be declared on the stack. If no size is given, the segment is defined with a default size of one kilobyte. Stand-alone assembler programs in the .EXE format should define a stack for the main (or only) module. Stacks are defined by the compiler or interpreter for modules linked with a main module from a high-level language.

      Code should be placed in a segment initialized with the .CODE directive, regardless of the memory model. Normally, only one code segment is defined in a source module. If you put multiple code segments in one source file, you must specify name to distinguish the segments. The name can only be specified for models allowing multiple code segments (medium and large). Name will be ignored if given with small or compact models.

      Uninitialized data is any variable declared by using the indeterminate symbol (?) and the DUP operator. When declaring data for modules that will be used with a Microsoft high-level language, you should follow the convention of using .DATA or .FARDATA for initialized data and .DATA? or .FARDATA? for uninitialized data. For stand-alone assembler programs, using the .DATA? and .FARDATA? directives is optional. You can put uninitialized data in any data segment.

      Constant data is data that must be declared in a data segment but is not subject to change at run time. Use of this segment is optional for stand-alone assembler programs. If you are writing assembler routines to be called from a high-level language, you can use the .CONST directive to declare strings, real numbers, and other constant data that must be allocated as data.

      Data in segments defined with the .STACK, .CONST, .DATA or .DATA? directives is placed in a group called DGROUP. Data in segments defined with the .FARDATA or .FARDATA? directives is not placed in any group. When initializing the DS register to access data in a group-associated segment, the value of DGROUP should be loaded into DS.

      • Example 1
                  .MODEL  SMALL
                  .STACK  100h
      ivariable   DB      5
      iarray      DW      50 DUP (5)
      string      DB      "This is a string"
      uarray      DW      50 DUP (?)
                  EXTRN   xvariable:WORD
      start:      mov     ax,DGROUP
                  mov     ds,ax
                  EXTRN   xprocedure:NEAR
                  call    xprocedure
                  END     start
      This code uses simplified segment directives for a small-model, stand-alone assembler program. Notice that initialized data, uninitialized data, and a string constant are all defined in the same data segment.

      • Example 1 Equivalent (when not using simplified segment directives)
                  EXTRN   xvariable:WORD
                  EXTRN   xprocedure:NEAR
      DGROUP      GROUP   _DATA,_BSS
                  ASSUME  cs:_TEXT,ds:DGROUP,ss:DGROUP
      start:      mov     ax,DGROUP
                  mov     ds,ax
      _TEXT       ENDS
      ivariable   DB      5
      iarray      DW      50 DUP (5)
      string      DB      "This is a string"
      uarray      DW      50 DUP (?)
      _DATA       ENDS
                  DB      100h DUP (?)
      STACK       ENDS
                  END     start
      This example is equivalent to the Example 1 using simplified segment directives. Notice that the segment order must be different in this version to achieve the segment order specified by using the DOSSEG directive in the first example. The external variables are declared at the start of the source code in this example. With simplified segment directives, they can be declared in the segment in which they are used.

      • Example 2
                  .MODEL  LARGE
      fuarray     DW      10 DUP (?)          ; Far uninitialized data
      string      DB      "This is a string"  ; String constant
      niarray     DB      100 DUP (5)         ; Near initialized data
                  EXTR    xvariable:FAR
      fiarray     DW      100 DUP (10)        ; Far initialized data
                  .CODE   TASK
                  EXTR    xprocedure:PROC
      task        PROC
      task        ENDP
      This example uses simplified segment directives to create a module that might be called from a large-model, high-level-language program. Notice that different types of data are put in different segments to conform to Microsoft compiler conventions.

      • Example 2 Equivalent (when not using simplified segment directives)
                  ASSUME  cs:TASK_TEXT,ds:FAR_DATA,ss:STACK
                  EXTRN   xprocedure:FAR
                  EXTR    xvariable:FAR
      fuarray     DW      10 DUP (?)         ; Far uninitialized data
      FAR_BSS     ENDS
      string      DB      "This is a string" ; String constant
      CONST       ENDS
      niarray     DB      100 DUP (5)        ; Near initialized data
      _DATA       ENDS
      fiarray     DW      100 DUP (10)
      FAR_DATA    ENDS
      TASK_TEXT   SEGMENT WORD PUBLIC 'CODE  ; < -- [bytepointer.com edit] doc bug - manual forgot closing single-quote on 'CODE'
      task        PROC    FAR
      task        ENDP
      This example is equivalent to the Example 2 using simplified segment directives. Notice that the segment order is the same in both versions. The segment order shown here is written to the object file, but it is different in the executable file. The segment order specified by the compiler (the DOS segment order) overrides the segment order in the module object file.

    Simplified Segment Defaults:
      When you use the simplified segment directives, defaults are different in certain situations than they would be if you gave full segment definitions. Defaults that change are listed below:

    • If you give full segment definitions, the default size for the PROC directive is always NEAR. If you use the .MODEL directive, the PROC directive is associated with the specified memory model: NEAR for small and compact models and FAR for medium, large, and huge models.
    • If you give full segment definitions, the segment address used as the base when calculating an offset with the OFFSET operator is the data segment (the segment associated with the DS register). With the simplified segment directives, the base address is the DGROUP segment for segments that are associated with a group. This includes segments declared with the .DATA, .DATA?, and .STACK directives, but not segments declared with the .CODE, .FARDATA, and FARDATA? directives.

      For example, assume the variable test1 was declared in a segment defined with the .DATA directive and test2 was declared in a segment defined with the .FARDATA directive. The statement
      mov     ax,OFFSET test1
      loads the address of test1 relative to DGROUP. The statement
      mov     ax,OFFSET test2
      loads the address of test2 relative to the segment defined by the .FARDATA directive.

    Default Segment Names:
      If you use the simplified segment directives by themselves, you do not need to know the names assigned for each segment. However, it is possible to mix full segment definitions with simplified segment definitions. Therefore, some programmers may wish to know the actual names assigned to all segments. The table below shows the default segment names created by each directive.

      Model    Directive    Name    Align    Combine    Class    Group
      Small .CODE


      Medium .CODE


      Compact .CODE


      Large or huge .CODE


      The name used as part of the far-code segment names is the file name of the module. The default name associated with the .CODE directive can be overridden in medium and large models. The default names for the .FARDATA and .FARDATA? directives can always be overridden.

      The segment and group table at the end of listings always shows the actual segment names. However, the group and assume statements generated by the .MODEL directive are not shown in listing files. For a program that uses all possible segments, group statements equivalent to the following would be generated:
      For small and compact models, the following would be generated:
                  ASSUME  cs:_TEXT,ds:DGROUP,ss:DGROUP
      For medium, large, and huge models the following statement is given:
                  ASSUME  cs:name_TEXT,ds:DGROUP,ss:DGROUP
      80386 Only:
      If the .386 directive is used, the default align type for all segments is DWORD.

    Example EXE and COM source code:
      [bytepointer.com edit] The version 5.0 manual has an example a source file to build an .EXE using the simplified segment directives and another example source file to build an equivalent .COM file (simplified segment directives not supported) on pages 14-16. Those examples are shown below:

      The source to build an .EXE file:
                  TITLE   hello
                  DOSSEG                     ; Use Microsoft segment conventions
                  .MODEL  SMALL              ;   conventions and small model
                  .STACK  100h               ; Allocate 256-byte stack
      message     DB      "Hello, world.",13,10  ; Message to be written
      lmessage    EQU     $ - message            ; Length of message
      start:      mov     ax,@DATA           ; Load segment location
                  mov     ds,ax              ;   into DS register
                  mov     bx,1               ; Load 1 - file handle for
                                             ;   standard output
                  mov     cx,lmessage        ; Load length of message
                  mov     dx,OFFSET message  ; Load address of message
                  mov     ah,40h             ; Load number for DOS Write function
                  int     21h                ; Call DOS
                  mov     ax,4C00h           ; Load DOS Exit function (4Ch)
                                             ;   in AH and 0 errorlevel in AL
                  int     21h                ; Call DOS
                  END     start
      The following example shows source code that can be used to create the same program as above, but in .COM format:
                  TITLE   hello
      _TEXT       SEGMENT                    ; Define code segment
                  ASSUME  cs:_TEXT,ds:_TEXT,ss:_TEXT
                  ORG     100h               ; Set location counter to 256
      start:      jmp     begin              ; Jump over data
      message     DB      "Hello, world.",13,10    ; Message to be written
      lmessage    EQU     $ - message              ; Length of message
      begin:      mov     bx,1               ; Load 1 - file handle for
                                             ;   standard output
                  mov     cx,lmessage        ; Load length of message
                  mov     dx,OFFSET message  ; Load address of message
                  mov     ah,40h             ; Load number for DOS Write function
                  int     21h                ; Call DOS
                  mov     ax,4C00h           ; Load DOS Exit function (4Ch)
                                             ;   in AH and 0 errorlevel in AL
                  int     21h                ; Call DOS
      _TEXT       ENDS
                  END     start
      [bytepointer.com edit] Note, to build the COM file sample, you had to perform these steps in MASM 5.0:

      1. assemble with MASM to obtain the OBJ file
      2. masm example.asm;
      3. LINK the OBJ file to produce the unusable/dummy EXE file (ignore the linker warning "L4021: no stack segment")
      4. link example.obj;
      5. run EXE2BIN from your DOS distribution passing the dummy EXE filename and specifying the output COM filename
      6. exe2bin example.exe example.com
      Jump to the improved COM file support and updated example for version 6.0. The COM file support in version 6.0 removed the need to run EXE2BIN as the linker will produce the COM file directly. MASM also added support for the tiny model, allowing for the use of simplified segment directives; this greatly simplified the COM source-code mess above. It is implied that debugging info for COM files was supported in version 6.0, although CodeView didn't support COM debugging until 1994 when the following patch was released: cv41patch.exe
  • Performance Improvements:
    The performance of MASM has been enhanced in two ways: faster assembly and larger symbol space. Version 5.0 of the assembler is significantly faster for most source files. The improvement varies depending on the relative amounts of code and data in the source file, and on the complexity of expressions used. Symbol space is now limited only by the amount of system memory available to your machine.
  • Enhanced Error Handling:

    • Messages have been reworded/clarified, enhanced, or reorganized.
    • Messages are divided into three levels: severe errors, serious warnings, and advisory warnings. The level of warning can be changed with the /W option. Type-checking errors are now serious warnings rather than severe errors.
    • During assembly, messages are output to the standard output device (by default, the screen). They can be redirected to a file or device. In Version 4.0 they were sent to the standard error device.
  • New Options:
    The following command-line options have been added:

    /W[0|1|2]- Sets the warning level to determine what type of messages will be displayed. The three kinds are severe errors, serious warnings, and advisory warnings.
    /ZI and /ZD- Sends debugging information for symbolic debuggers to the object file. The /ZD option outputs line-number information, whereas the /ZI option outputs both line-number and type information.
    /H- Displays the MASM command line and options.
    /Dsym[=val]- Allows definition of a symbol from the command line. This is an enhancement of a current option.
    /LA- The /LA option has been added to specify a complete listing of all symbols, macros, and false conditionals. It is equivalent to using the .LIST, .LFCOND, .LALL, and .CREF directives throughout the source file. The option overrides any conflicting directives in the source file.

    NOTE: This was formally documented in version 5.1 as a new feature over 5.0, but that was a documentation bug. This feature was present in version 5.0, but only documented in the README.DOC.

    In addition, the new directives .ALPHA and .SEQ have been added; these directives have the same effect as the /A and /S options.
  • Environment Variables:
    MASM now supports two environment variables: MASM for specifying default options, and INCLUDE for specifying the search paths for include files.
  • String Equates:
    String equates have been enhanced for easier use. By enclosing the argument to the EQU directive in angle brackets, you can ensure that the argument is evaluated as a string equate rather than as an expression. The expression operator (%) can now be used with macro arguments that are text macros as well as arguments that are expressions.
  • RETF and RETN Instructions:
    The RETF (Return Far) and RETN (Return Near) instructions are now available. These instructions enable you to define procedures without the PROC and ENDP directives.
  • Communal Variables:
    MASM now allows you to declare communal variables. These uninitialized global data items can be used in include files. They are compatible with variables declared in C include files.
  • Including Library Files:
    The INCLUDELIB directive enables you to specify in the assembly source file any libraries that you want to be linked with your program modules.
  • Flexible Structure Definitions:
    Structure definitions can now include conditional-assembly statements, thus enabling more flexible structures.
  • New Macro Files:
    Macro files have been added to the Macro Assembler package. The following files are provided:

    MIXED.INC - For defining assembler procedures that can be called from high-level languages
    MIXED.DOC - Documentation for the macros in MIXED.INC.
    DOS.INC - For calling common DOS interrupts
    BIOS.INC - For calling common BIOS interrupts used on IBM and IBM-compatible computers
    MACRO.DOC - Description, syntax, and reference for using the macros in DOS.INC and BIOS.INC.
  • Link Enhancements:

    LINK has several new features. These enhancements are summarized below:

    • The LINK environment variable specifies default linker options.
    • The TMP environment variable specifies a directory in which LINK can create temporary files if it runs out of memory.
    • The /CODEVIEW option puts debugging information in executable files for the CodeView debugger.
    • The /INFORMATION option displays each step of the linking process including parsing the command line, Pass 1, and so on. The path and name of each module are displayed as the modules are linked.
    • The /BATCH option disables the linker's prompting interface so that make or batch files are not be [sic] stopped by LINK errors.
    • The /QUICKLIB option creates a user's library for a Microsoft Quick language (such as QuickBASIC).
    • The /FARCALLTRANSLATION and /PACKCODE options enable two optimizations that may make code faster in certain situations.
    • The following new LINK message warns about a practice that is legal in real mode, but illegal in protected mode:
          warning L4003: intersegment self-relative fixup at <position>
      In assembly-language, the warning only occurs if the DOSSEG directive or /DOSSEG linker option is used. It indicates a 16-bit jump to an address in another segment. For example, the following code produces the error:
        _TEXT   SEGMENT
            EXTRN    doit:NEAR
            jmp      _TEXT2:doit
        _TEXT   ENDS
        _TEXT2  SEGMENT
            PUBLIC   doit
        doit    PROC     NEAR
        doit    ENDP
        _TEXT2  ENDS
      The warning usually indicates a fatal error in high-level- language programs. It can occur when the /NT option is used to compile a small-model C program.
  • Real-number format changed to IEEE floats:
    The default format for initializing real-number variables has been changed from Microsoft Binary to the more common IEEE (Institute of Electrical and Electronic Engineers, Inc.) format.
  • Introduction of the CodeView debugger:
    The new CodeView® window-oriented debugger allows source-level debugging on assembly language files and has many other powerful features. In Version 5.0 of the Macro Assembler package, the CodeView debugger replaces SYMDEB.

    [bytepointer.com edit] CodeView also replaced the MAPSYM utility.

    The CodeView debugger is a source-level symbolic debugger capable of working with programs developed with MASM or with Microsoft high-level-language compilers. The CodeView debugger features a window-oriented environment with multiple windows displaying different types of information. Commands can be executed with a mouse, function keys, or command lines. Variables can be watched in a separate window as the program executes. MASM and LINK have been enhanced to support the features of the CodeView debugger.

    • The /R option has been added to enable the CodeView debugger to use the debug registers (DR0, DR1, DR2, and DR3) of the 80386 processor. The option is ignored if you do not have an 80386 processor.

      The display does not change to indicate that the debug registers are in use, but debugger operations with tracepoint or trace memory statements (but not with watchpoint statements) will be much faster. Any of the following conditions will prevent the debugger from using debug registers:

      1) /E is used.
      2) More than four tracepoints are set.
      3) A tracepoint watches more than four bytes of memory.
      4) A watchpoint is set.
  • CREF.EXE has new Modifier Symbol:
    Cross-reference listing files created with CREF now have an additional symbol. A line number followed by + indicates that a symbol is modified at the given line. For example:
    TST . . . . . . . . . . . . . .  134#   237    544+
    The symbol TST is defined at line 134, used at line 237, and modified at line 544.
    Since MASM and LINK now support more environment variables, users may wish to define environment strings that exceed the default size of the DOS environment. The SETENV program in the CodeView and Utilities manual is provided as a means of modifying the environment size for DOS Versions 2.0 to 3.1.
  • Compatibility with Assemblers and Compilers:
    If you are upgrading from a previous version of the Microsoft or IBM Macro Assembler, you may need to make some adjustments before assembling source code developed with previous versions. The potential compatibility problems are listed below:

    • All previous versions of the Macro Assembler assembled initialized real-number variables in the Microsoft Binary format by default. Version 5.0 assembles initialized real-number variables in the IEEE format. If you have source modules that depend on the default format being Microsoft Binary, you must modify them by placing the .MSFLOAT directive at the start of the module before the first variable is initialized.

      In previous versions of the Macro Assembler, the default conditions were 8086 instructions enabled, coprocessor instructions disabled, and real numbers assembled in Microsoft Binary format. The /R option, the .8087 directive, or the .287 directive was required to enable coprocessor instructions and IEEE format. In Version 5.0, the default conditions are 8086 and 8087 instructions enabled and real numbers assembled in IEEE format. Although the /R option is no longer used, it is recognized and ignored so that existing make and batch files work without modification.
    • Some previous versions of the IBM Macro Assembler wrote segments to object files in alphabetical order. MASM Version 5.0 writes segments to object files in the order encountered in the source file. You can use the /A option or the .ALPHA directive to order segments alphabetically if this segment order is required for your existing source code.
    • Some early versions of the Macro Assembler did not have strict type checking. Later versions had strict type checking that produced errors on source code that would have run under the earlier versions. MASM Version 5.0 solves this incompatibility by making type errors into warning messages. You can set the warning level so that the type warnings will not be displayed, or you can modify the code so that the type is given specifically.
    The programs in the Microsoft Macro Assembler package are compatible with Microsoft (and most IBM) high-level languages. An exception occurs when the current version of LINK is used with IBM COBOL 1.0, IBM FORTRAN 2.0, or IBM Pascal 2.0. If source code developed with these compilers has overlays, you must use the linker provided with the compiler. Do not use the new version of LINK provided with the assembler.
  • "There's no excuse for using an Assembler earlier than MASM 5.0--you might as well use DEBUG. Version 5.00 was much faster than 4.00, and miles ahead in bug fixes. The most significant improvement was simplified segment declarations like .MODEL and .CODE. But 5.00 didn't hang around long; it was quickly replaced..."
  • REFERENCE: r_harvey

  • "The real purpose of this letter is to complain that MASM 5.0 no longer supports .COM files and nobody says anything about it. CodeView does not offer symbolic debugging of .COM files and MASM 5.0's symbol file is not compatible with Symdeb or other symbolic disassemblers. So even if you're satisfied with the creepy-crawly rate at which MASM 5.0 assembles and links, you have to give up .COM files or symbolic debugging."
    "In comparison with earlier releases, MASM 5.0 is "screamingly" faster. There are even faster assemblers, and I'll take George's word that A86 is one of them. It's true that MASM 5.0 doesn't produce .COM files directly; you have to run the end product through EXE2BIN if you want a .COM. It's also true that I didn't mention that, and I apologize on behalf of all us reviewers who haven't said anything about it."
  • REFERENCE: Dr. Dobbs: MASM Complaints / May 1, 1988

  • "To that end, MASM 5.0 furnishes a macro library for mixed-language programming. This file, MIXED.INC, includes macros for passing and receiving anguments, allocating local variables on the stack, segment fixups, exit processing, and other high-level interfacing needs. The macro library is propped up by and excellent 1440-page guide covering a range of mixed-language programming issues."
    "The overall quality of the manuals is much better than any previous Microsoft documentation. In addition to the mixed-language guide, there are two soft-bound books, a 467-page Programmer's Guide and a 401-page volume covering CodeView and other utilities. Rounding out the documentation is a 148-page wire-bound reference divided into five tabbed sections. Intended to be kept at the programmer's elbow, this reference summarizes every instruction, pseudo-op, and command-line switch. There are several brochures and a function-key template for operating CodeView."
    "If you haven't worked with CodeView before, you're missing out on the finest thing Microsoft has done to date. This is how God intended a symbolic debugger to be. It's a wonderfully visual environment that lets you watch your code execute while keeping an eye on registers and selected memory locations. Codeview runs in a secondary video page, thus not interfering with programs that do graphics or fancy text screens, and you can easily toggle back and forth between the CodeView display and your program's output. Accommodating to all and sundry, CodeView lets you control it via pulldown menus, function keys, typed commands, or a mouse: your choice."
  • REFERENCE: Dr. Dobbs: Examining Room / Feb 1, 1988

  • In September 1987, some users of DANNYSOFT BBS reported certain problems encountered in version 5.0 in a compilation document (named MASMV5P1.TXT).
MASM 5.0 Mixed-Language Guide and 5¼ inch disks
MASM 5.0 Mixed-Language Guide and 5¼ inch disks

MASM 5.0 Features
Microsoft Languages Newsletters
September 1987
(Images Courtesy of pcjs.org)
MASM 5.0 Features Article

MASM/2 1.0 IBM © 1981-1985, 1987 [Command Line]
MASM.EXE114,522 bytes (112k)md5=4c7a1562e1151c5168238cbbc8d86858date=9/3/1987 4:00pm

This is a unique version of MASM displaying the name "IBM Macro Assembler/2" and "Version 1.00". It is important to note that this is actually a rebranded variant of MASM 4.0 with OS/2 support, although DOS remains supported.

The executable size in this version was nearly 30k larger than in MASM 4.0 because this was a "bound" executable, allowing it to be run in both DOS and OS/2. Likewise, the LINK, LIB, CREF, MAKE and EXEMOD utilities were also bound executables. However, CodeView was distributed in pure DOS and OS/2 executable forms as CV and CVP respectively.

Archive.org has a copy of this version's Reference Manual available for viewing or download.

The mainstream Microsoft MASM wouldn't have OS/2 support until the following year in version 5.1. IBM did not appear to release another "Assembler/2" or another rebranded MASM.

  • IBM Disk Operating System Version 3.30 or IBM Operating System/2

MASM 5.10 © 1988
MASM.EXE110,703 bytes (108k)md5=6828fe2509ebad3ca10d2f51c71a2d94date=2/1/1988 1:00pm(dos version)[Command Line]
MASM.EXE124,712 bytes (122k)md5=c1a93ab5293080614af1fe0302e5420adate=1/31/1988 11:00pm(dual mode version)[Command Line]
@Version reports: 510
Retail Price: $150.00

I have seen multiple file dates for both the DOS and "dual mode" versions of the MASM.EXE files. Note that differences of a couple hours may be from an inadvertent time zone adjustment rather than an official time stamp.
  • DOS version: 1/31/1988 9:00pm, 2/1/1988 1:00pm
  • Dual mode version: 1/31/1988 9:00pm, 1/31/1988 11:00pm, 3/10/1988 1:10pm (on EXTRA disk, #6)
Despite the the minor number increment over 5.0, this release of MASM had enough changes to warrant a major release. The was the first Microsoft branded version of MASM to support OS/2 (see the IBM rebranded MASM "Assembler/2"). This version of MASM was a 5 disk distribution of 5¼ inch floppies. It is not known if this version was released on 3 ½ inch floppies.

The PACKING.LST file distributed on disk #1 illustrates the pre-install contents of the disks. Additionally, the other documentation files provided include: README.DOC, MACRO.DOC, and MIXED.DOC. Although this version shipped with the 5.0 User's Guide, it included an additional lengthy booklet divided into three sections labeled: "5.1 Update"; "Microsoft® CodeView® and Utilities Update"; and "Microsoft Editor". The majority of the information below was derived from the official 5.1 Update manual.

Note: Not all the OS/2 changes were listed.

SYSTEM REQUIREMENTS (from "Technical Highlights" card below):
  • 320K available user memory
  • MS OS/2 1.0 or MS-DOS 2.1 or higher
  • Two double-sided disk drives
  • Regular DOS programs:
    [bytepointer.com edit] I couldn't find anything explicitly said, but the minimum requirement for running this version of MASM was DOS 2.1 and up; assembled programs in version 6.0 had a minimum requirement of DOS 2.1 and up, so a DOS 2.1 or higher requirement seems logical.
  • Bound Hybrid (dual-mode) OS/2 and DOS Programs:
    OS/2 and DOS version 3.0 or higher is required for dual-mode programs that run under either DOS or OS/2, but the OS/2 API calls must be restricted to the "Family API". A dual-mode executable can however be run in DOS 2.x environments, but only if the name of an executable file produced by BIND is not changed.
  • New OS/2 Support:
    Version 5.1 runs under both OS/2 and DOS operating systems, enabling you to develop powerful applications for OS/2. Version 5.1 includes the necessary supporting libraries including bound and real-mode versions.

    [bytepointer.com edit] This includes the introduction of the BIND utility, used for creating "bound" programs. A bound program was a single executable that was capable of running under both DOS and OS/2.
  • Text-macro and directive extensions:
    New directives, text-macro directives, and predefined text macros let you write more sophisticated macros for powerful and portable code. Extensions to text macros let you write more flexible and powerful macros for your programs. Version 5.1 includes new built-in text macros as well as text macro directives that let you directly manipulate string equates. An extension to the expression operator (%) allows you to evaluate text macros anywhere in your source.

    Version 5.1 of the Macro Assembler includes four text-macro string directives that let you manipulate literal strings or text-macro values.

    • SUBSTR: Returns a substring of its text macro or literal string argument. The SUBSTR directive requires a text-macro label.
    • CATSTR: Concatenates a variable number of strings (text macros or literal strings) to form a single string. The CATSTR directive requires a text-macro label.
    • SIZESTR: Returns the length, in characters, of its argument string. The SIZESTR directive requires a numeric label.
    • INSTR: Returns an index indicating the starting position of a substring within another string. The INSTR directive requires a numeric label.

    Version 5.1 of the Macro Assembler includes three new predefined text-macros:

    • @WordSize: The @WordSize text macro returns the word size of the segment word size in bytes. It returns 4 when the word size is 32 bits and 2 when the word size is 16 bits. By default, the segment word size is 16 bits with the 80286 and other 16-bit processors, and 32 bits with the 80386.
    • @Cpu: The @Cpu text macro returns a 16-bit value containing information about the selected processor. You select a processor by using one of the processor directives such as the .286 directive. You can use the @Cpu text macro to control assembly of processor-specific code. Individual bits in the value returned by @Cpu indicate information about the selected processor.
    • @Version: The @Version text macro returns a string containing the version of MASM in use. With the @Version macro, you can write macros for future versions of MASM that take appropriate actions when used with inappropriate versions of MASM. Currently, the @Version macro returns 510 as a string of three characters.
  • High-level-language support:
    Version 5.1 contains several features that simplify the writing of assembly routines to be called from high-level languages. The high-level-language support features incorporate and extend the features of the mixed-language programming macros distributed with Version 5.0. Features of the MIXED.INC macro file shipped with Version 5.0 are now built into the macro assembler, along with additional supporting directives and extensions:

    • New Language parameter to .MODEL:
      Along with simplifying the process if writing procedures to be called from other languages, the high-level-language calling features also make it easier to use a procedure with more than one language. For example, to change function(s) so they can be called from Pascal, rather than C, you would change the .MODEL directive. Additionally:

      • Possible values:
        You can use C, PASCAL, FORTRAN, or BASIC as the language argument.
      • Makes procedures public:
        If you use the language argument, MASM automatically makes all procedure names public. In Version 5.0 of MASM, a procedure required a PUBLIC directive to make the name of the procedure available outside the module. The PUBLIC directive is no longer required when used with the new language parameter.
      • Sets naming conventions:
        If you use C for the language parameter, all public and external names are prefixed with an underscore (_) in the .OBJ file. Specifying any other language has no effect on the names.

        NOTE: The only change MASM makes to a procedure name is to add an underscore for C. MASM does not truncate names in order to match the conventions of specific languages such as FORTRAN or Pascal.
      • Sets parameter order:
        The language parameter also affects how arguments passed on the stack are interpreted. If you specify FORTRAN, PASCAL, or BASIC, then MASM assumes the arguments have been pushed onto the stack from left to right - the last argument is nearest to the top of the stack. Specifying C assumes arguments have been pushed on the stack in the opposite order.
      • Sets return conventions:
        Pascal, FORTRAN, and BASIC programs require the called procedure to remove arguments from the stack. If you specify PASCAL, FORTRAN or BASIC as the language argument, MASM replaces you return instruction (ret) with a return that removes the correct number of bytes from the stack. In C, the calling program removes arguments from the stack, and MASM leaves the return instruction unchanged.

        NOTE: To write procedures for use with more than one language, you can use text macros for the memory model and language arguments, and define the values from the command line. For example, the following .MODEL directive uses text macros for the memory and language arguments:
        %   .MODEL memmodel,lang   ; Use % to evaluate memmodel, lang
        The values of the two text macros can be defined from the command line using the /D switch:
        MASM /Dmemmodel=MEDIUM /Dlang=BASIC
    • Changes to EXTRN and PUBLIC syntax:
      EXTRN and PUBLIC now allow the langtype parameter:
      EXTRN [langtype] varname:type
      PUBLIC [langtype] varname
    • Extensions to the PROC directive:

      In Version 5.1, the PROC directive has this syntax:
      name PROC [NEAR|FAR] [langtype] [USES [reglist],] [argument[,argument]...]
      • Automatically save specified registers on the stack with USES:
        reglist specifies a list of registers that the procedure uses and that should be saved on entry. Registers in the list must be separated by blanks or tabs.
      • Automatically generate text macros for arguments passed on the stack:
        In Version 5.0, the type and number of arguments were handled as displacements from the base pointer, BP. Version 5.1 extends the PROC directive to specify the type and number of arguments passed to the procedure on the stack and generates text macros for the arguments. Additionally, MASM now generates the code for setting up the stack and restoring it based on the information in the high-level-language-directives.

        The argument is the name of the argument. The type is the type of the argument and may be WORD, DWORD, FWORD, QWORD, TBYTE, or the name of a structure defined by a STRUC structure declaration. If you omit type, the default is the WORD type (the DWORD type when a 386 directive is used). MASM creates a text macro for each argument. You can use these text macros to access the arguments in the procedure. The FAR, NEAR, PTR, and type arguments are all optional. If you specify that the variable is a pointer, MASM sets up a text macro to access the variable on the stack, but also generates CodeView information so that the variable is treated as a pointer during debugging.

      The following is a routine using the old high-level-language techniques present in Version 5.0 (a procedure to be called from a C program as a function adding two integers and returning the result AX, used by C for returning integer function values):
      ; Assemble with /MX or ML to preserve case of procedure name
                      PUBLIC _myadd
                      .MODEL MEDIUM
      _myadd          PROC FAR
      arg1            EQU     <WORD PTR [bp+6]>
      arg2            EQU     <WORD PTR [bp+8]>
                      push    bp              ; Set up stack frame
                      mov     bp,sp
                      mov     ax,arg1         ; Load first argument
                      add     ax,arg2         ; Add second argument
                      pop     bp
      _myadd          ENDP
      Here is the same procedure written using the new high-level-lanaguage features:
      myadd           PROC arg1:WORD, arg2:WORD
                      mov     ax,arg1         ; Load first argument
                      add     ax,arg2         ; Add second argument
      myadd           ENDP
    • The new LOCAL directive:
      [bytepointer.com edit] Its not just for Macro's anymore!

      With the LOCAL directive, you can allocate local variables from the stack and MASM will generate text equates for the variables. Usually this is done by decrementing the stack pointer the required number of bytes after setting up the stack frame. For example, the following sequence allocates two, two-byte variables from the stack and sets up text macros to access them:
      locvar1         EQU     <WORD PTR [bp-2]>
      locvar2         EQU     <WORD PTR [bp-4]>
              push    bp
              mov     bp,sp
              sub     sp,4
              mov     localvar1,ax
      With the LOCAL directive you can do the same thing in a single line:
      LOCAL locvar1:WORD, locvar2:WORD
              mov     localvar1,ax
      The LOCAL directive has the following syntax:
      LOCAL vardef [,vardef]...
      Each vardef has the form:
      variable[[count]][:[[NEAR | FAR]PTR]type]...
      The LOCAL directive arguments are as follows:

      variable- The name given to the local variable. MASM automatically defines a text macro you may use to access the variable.
      count- The number of elements of this name and type to allocate on the stack. Using count allows you to allocate a simple array on the stack. The brackets around count are required.
      type- The type of variable to allocate. The type argument may be one of the following: WORD, DWORD, FWORD, QWORD, TBYTE, or the name of a structure defined by a STRUC structure declaration.

      MASM sets aside space on the stack, following the same rules as for procedure arguments. MASM does not initialize local variables. Your program must include code to perform any necessary initializations.
    • Variable Scope:
      Labels can be made local to a procedure, allowing better isolation of the procedures. When you use the extended form of the .MODEL directive, MASM makes all identifiers inside a procedure local to the procedure. Labels ending with a colon (:), procedure arguments, and local variables declared in a LOCAL directive are undefined outside of the procedure. Variables defined outside of any procedure are available inside a procedure.

      Because labels are local when you use the language option on the .MODEL directive, you may use the same labels in different procedures. You can make a label in a procedure global (make it available outside the procedure) by ending it with two colons.
  • Local Labels for Jumps:
    Version 5.1 of the Macro Assembler allows automatic generation of local labels for jump instructions. Automatic local labels free you from having to write labels for small code sections. To define a local label, use two at signs (@@) followed by a colon (:). To jump to the nearest preceding local label, use @B (back) in the jump instruction's operand field; to jump to the nearest following local label, use @F (forward) in the operand field.
  • Conditional Assembly:
    The ELSEIF directive simplifies the writing of complex conditional assembly sections in your macros and programs. MASM includes an ELSEIF directive corresponding to each of the IF directives: ELSEIF, ELSEIF1, ELSEIF2, ELSEIFB, ELSEIFDEF, ELSEIFDIF, ELSEIFDIFI, ELSEIFE, ELSEIFIDN, ELSEIFIDNI, ELSEIFNB, ELSEIFNDEF
  • Data Declarations:
    A new type of data declaration makes it possible to generate Microsoft CodeView® information for pointer variables. Version 5.1 of the Macro Assembler extends data definitions to include explicit allocation of a pointer. Pointer-data definitions may now have the following form:
    symbol[DW | DD | DF]type PTR initialvalue
    For example, in the following fragment, ndptr is declared as a near pointer to a date structure and is initialized to zero:
    date        STRUC
      month     DB    ?
      day       DB    ?
      year      DB    ?
    date        ENDS
    ndptr       DW  date PTR 0
    Similarly, the following lines declare a string and two pointers to the string. The declaration also initializes the pointers to the address of the string:
    string      DB  "from swerve of shore to bend of bay"
    pstring     DW  BYTE PTR string  ; Declares a near pointer.
    fpstring    DD  BYTE PTR string  ; Declares a far pointer.
    Using an explicit pointer declaration generates CodeView information, allowing the variable to be viewed as a pointer during debugging.

    NOTE: This use of PTR is in addition to the use of PTR to specify the type of a variable or operator. MASM 5.1 determines the meaning of PTR by context.
  • Changes to the .CODE directive:
    A change in the register assumptions used in the .CODE directive makes it easier to create multiple code segments. In Version 5.1, the .CODE directive always assumes CS is the current segment. This change makes it easier to use multiple code segments in a single module. Version 5.0 assumed CS once at the beginning of the program, making it necessary to use an ASSUME for a second segment.
  • Mixed-Mode Programming with .386:
    When assembling code for .386 mode, the assembler now supports direct- addressing modes between segments with different USE sizes. (Segments can have the USE16 or USE32 attribute; these attributes refer to the default size of offsets.) Direct-addressing references to labels in other segments are correctly resolved. In the following example, the assembler correctly uses a 32-bit offset to access the data at label a32:
    a32     DD      ?
    SEG32   ENDS
            assume ds:seg32
            mov     eax,a32
    SEG16   ENDS
    You can also execute a CALL or a JMP to a label in a segment with a different USE size. However, the label must be declared FAR, and the CALL or JMP must not be a forward reference. The following example shows the correct method for executing such a CALL or JMP:
    COD16   SEGMENT USE16   'CODE'
    proc16  PROC    FAR
    proc16  ENDP
    lab16   LABEL   FAR
    COD16   ENDS
    COD32   SEGMENT USE32   'CODE'
            call    proc16
            jmp     lab16
    COD32   ENDS
  • .TYPE Operator:
    Extensions to the .TYPE operator provide additional information about an operand. The .TYPE operator now returns the following bit settings as shown in the .TYPE Operator and Variable Attributes table:

    Bit Position  If Bit=0  If Bit=1
    0Not program relatedProgram related
    1Not data relatedData related
    2Not a constant valueConstant value
    3Addressing mode is not directAddressing mode is direct
    4Not a registerExpression is a register
    5Not definedDefined
    7Local or public scopeExternal scope

    It bits 2 and 3 are both zero, the expression involves a register-indirect expression. Bit 6 is reserved. The use of bits 2,3, and 4 is new with this version of the Macro Assembler.
  • COMM Extension:
    The COMM directive now accepts structure names for the size argument. This enhancement lets you declare communal variables of any size, rather than being limited to 1-,2-,4-,6-,8-, or 10-byte items.
  • Line Continuation:
    Version 5.1 lets you use the line-continuation character (\) to continue program lines. Using the line-continuation character, you may have program lines up to 512 characters. Physical lines are still limited to 128 characters. The backslash must be the last character in the line.
  • Performance:
    Version 5.1 is significantly faster than Version 5.0 because it uses dynamically allocated memory to perform file caching. File caching stores significant parts of the source and include files to be stored in memory.

    In addition, Version 5.1 allows significantly more structure definitions because it now uses far memory to store these definitions.
  • Command Line Options:
    Version 5.1 of the Macro Assembler includes a new command line-option that shows all code generated by MASM. The /LA option displays the results of the simplified segment directives and the code generated by the high-level-language support features.

    [bytepointer.com edit] Doc bug. /LA was new in 5.0 too, but it didn't make it into the manual, just the README.

    The following command line option was removed that was present in version 5.0:

    /B<number> - Set I/O buffer size, 1-63 (in 1K blocks)

    The /B option is now ignored, because its effect is irrelevant, given the new file buffering mechanism. However, the option is still accepted for the purposes of compatibility.
  • Command-Line Changes to CodeView:
    If you have an IBM Personal System/2, then you can use the /50 command-line option to start the CodeView debugger in 50-line mode. Note that you must be in 25-line mode to effectively use either the /43 or /50 command-line option.
  • CodeView and Microsoft Pascal:
    In this release, Microsoft Pascal programs cannot be debugged with the CodeView debugger.
  • LIB Utility Changes:
    There is a new option for LIB: /NOIGNORECASE (abbreviated as /N). This option tells LIB to not ignore case when comparing symbols. names. By default, LIB ignores case. Multiple symbols that are the same except for case can be put in the same library. An example of this is: "_Open" and "_open". Normally you could not add both these symbols to the same library.

    Note that if a library is built with /NOI, the library is internally "marked" to indicate /NOI. All libraries built with earlier versions of LIB are not marked.

    If you combine multiple libraries, and any one of them is marked /NOI, then /NOI is assumed for the output library.

    In addition, LIB also supports the option /IGNORECASE (/I), which is completely analogous to /NOIGNORECASE. /I is the default. The only reason to use it would be if you have an existing library marked /NOI that you wanted to combine with other libraries which were not marked, and have the output library be not marked. If you don't use /IGNORECASE, the output is marked /NOI (see above).
  • "The idea is simple: you define a local label with two at signs (@@) followed by a colon. To reference the nearest preceding local label, use @B (back); to reference the next local label, use @F (forward). When writing assembly language routines for use in HLL programs, a much more structured feature is enabled. The manual describes it as a local variable scope when you use the extended form of the .MODEL directive. Labels ending with a single colon (and procedure arguments passed on the stack and local stack variables) are considered local to the procedure where they are defined. To make a label available from another procedure, it must be defined with two colons."

    REFERENCE: Dr. Dobbs: MS-DOS Assemblers Compared

  • "Perhaps the greatest (though most overlooked) feature added to version 5.10 was the @@ local label; we no longer had to come up with a unique label for each conditional test. Note that Microsoft's @@ labels are not the same as TASM's. Microsoft included a text editor simply named M, which a few programmers loved, but many never figured it out at all. Version 5.10 also added OS/2 1.x support."
  • REFERENCE: r_harvey

  • "New with 5.1 is the Microsoft Editor, a programmer's editor that allows compiling (or assembling) from the editor. One major feature of MASM is a BIND utility, which allows the creation of a program that runs under DOS or OS/2."
  • REFERENCE: Dr. Dobb's

  • According to a BYTE magazine "Programmer's Paradise" advertisement from June of 1990, Microsoft Macro Assembler (presumably version 5.1) had a list price was $150, although sold for $105; much less than the C compilers. The competition between Microsoft and Borland was evident as the list and sale prices between MASM and Turbo Assembler were identical. In an ad in the November 1990 BYTE magazine, Turbo Assembler 2.0 was bundled with Borland's Turbo C++ Professional, implying the Turbo Assembler at the time was 2.xx; this is further verified by the command line copyright dates of Turbo Assembler 2.xx.
MASM 5.1 3-Hole "Technical Highlights"
Card / Brochure

MASM 5.1 Technical Highlights Card Brochure / Front MASM 5.1 Technical Highlights Card Brochure / Back

MASM 5.10A © 1981, 1989 (a.k.a. 5.1A)
MASM.EXE110,937 bytes (108k)md5=03671c1240696672ef413817c62a8e6edate=1/16/1989 11:10am(file date from EXE offset 1A50B / DOS)[Command Line]
MASM.EXE110,675 bytes (108k)md5=331bbd30a4da6068884c19b89921c6d9date=7/22/1988 2:28pm(file date from EXE offset 1A419 / DOS)[Command Line]
MASM.EXE124,448 bytes (122k)md5=20ca57a959cd487ddb1eeeafd3f99964date=11/19/1991 10:55am(From Win3.1 DDK / Dual Mode)[Command Line]
MASM.EXE124,448 bytes (122k)md5=910b3486b43acf67452fa1e186e95529date=3/18/2002 5:54pm(From WS03 SP1 DDK / DOS)[Command Line]
@Version reports: 510

The directory listing (and README.DOC) from the 360k distribution disk is as follows (courtesy of pcjs.org):
 Volume in drive A is MASM-5-10A 

Directory of A:\

MASM     EXE    110937 01-16-89  11:16a
BINB         <DIR>     03-19-90  12:15p
README   DOC      3951 03-10-90   4:06p
        3 file(s)     114888 bytes

Directory of A:\BINB

.            <DIR>     03-19-90  12:15p
..           <DIR>     03-19-90  12:15p
MASM     EXE    124448 01-16-89  11:11a
        3 file(s)     124448 bytes

Total files listed:
        6 file(s)     239336 bytes
                      120832 bytes free
It is interesting to note that while the timestamp in the DOS version of MASM.EXE in the listing above (not the one in BINB) has a date of 11:16am, the internal timestamp is 6 minutes prior, containing 11:10am; at least in the version I have to compare it to.

This version of MASM, known as an "incremental update", was released at least as early as the Windows 3.1 DDK (located in "286\tools") but has variations that date back to 1988.

Since the Windows 3.1 DDK, this version was again released nearly 11 years later in 2002 with the Windows Server 2003 SP1 DDK 3790.18030 located in "WINDDK\3790.1830\bin\bin16". This was primarily a bugfix release including the fix described in MASM KB Article Q32811. It is puzzling that a 5.1 series assembler shipped with the WS03 DDK rather than one of the 6.x versions as the "16-bit assembler". Also interesting is the fact that 5.10A was chosen over 5.10B which may indicate version 5.10B was a special hack just for Windows 3.1.

The changelist below was derived from the README.DOC.

  • Modified alignment constraints for variables allocated with the LOCAL directive. Padding bytes are used to enforce the following constraints:

    Type Specifier  Align Type

    Offset for local variables whose size is greater than WORD is now correctly calculated.
  • With /Zi, Codeview information is now generated for all symbols defined with the LOCAL directive.
  • The text macros for parameters and locals with the PROC directive are generated with surrounding parentheses. This aids in their correct evaluation in expressions.
  • USES clauses in PROC directives no longer generates internal assembler errors.
  • Open procedures no longer cause listing file errors.
  • SUBSTR can now be used with the same label as both source and destination.
  • EXTRN ABS when C language is specified prepends name with an underscore.
  • Parameter alignment in 32 bit mode has been adjusted. 6 bytes were previously allocated for the return address, but 8 bytes are pushed by the calling program.
  • 32 bit fixup records are now being output in 16 bit code segments.
  • Unintentionally redefining a code label in a PROC no longer causes the assembler to hang.
  • MASM will now run in a VIO window under Presentation Manager.
  • .CONST now generates a 'CONST' class segment as documented. Previously, it was generating class 'DATA'.
  • /Z switch is no longer ignored after an include file is processed.
  • Can now mix / and \ in the command line source file path specification, i.e.:
    masm -t \masm/src/file.asm;
  • Fixed GP fault on command line longer than 127 characters.
  • Fixed bug which caused errors to be reported with the wrong line numbers.
  • Fixed a phase-error problem with:
     MOV BX, forward-reference expression
  • Fixed improper behavior when type missing on LABEL directive.
  • Real number initialization now works when .RADIX 16. Previously, a false "non-digit in number" error was generated.
  • Can now initialize a structure field to a segment address. Previously, initializing a DD to a segmentName generated an invalid object file.
  • % operator no longer inconsistently causes "symbol not defined" errors when used with text equates.
  • Text macro expansions no longer cause GP faults.

MASM 5.10B © 1981, 1989 (a.k.a. 5.1B) [Command Line]
MASM5.EXE111,396 bytes (109k)md5=562f09d9136f12bf9eb15d5cde2e15d1date=1/4/1992 12:52pm(file date from EXE offset 1A6CB is 4/7/1989 11:50)
@Version reports: 510

This version came with the Windows 3.1 DDK, located in the "386\tools" directory. According to Microsoft KB 110405, version 5.10B was designed for the Windows 3.1 DDK. The DDK's DRIVERS.TXT file explains that MASM5.EXE (5.10B) is for 386 virtual devices.

  • "The best traditional MASM was 5.10B, which has been around since 1989. While reliable, fast and small, it didn't have high-level structures (.IF / .ENDIF), and a few 386 instructions were encoded a bit oddly. It was the last version that would run in less than 640K and fit on a low-density floppy disk. Version 5.10B was available on the first pre-release Microsoft Developer's Network CD-ROM (dig around, it's buried in there somewhere)."

MASM386 5.NT.02 © 1981, 1989 (a.k.a. 5.10.NT)
MASM386.EXE211,556 bytes (207k)md5=1e673dbfa68e9d1431869c57f2f8c48cdate=11/1/1993 6:28ambuild 3.10.508.1(from Win32 SDK for NT 3.1 - \MSTOOLS\BIN\i386)[Command Line]
MASM386.EXE153,360 bytes (150k)md5=3ebda9cebf3aec0626816e89f3cfa012date=9/4/1994 1:07ambuild 3.50.794.1(from Win32 SDK for NT 3.5, Final, Sep 1994 - \MSTOOLS\BIN\I386)[Command Line]
MASM386.EXE258,560 bytes (252k)md5=661bee6835e90f66c1585504ac250907date=12/3/1991 1:54am(from MSDN Win32 DDK CD for NT 3.1 Build 1.239.1 / untested)
@Version reports: 510

MASM386 was a special 32-bit version of MASM that did not run under DOS. It first shipped with the Windows NT 3.1 Win32 SDK for use with the DDK (Driver Development Kit). Based on MASM 5.1, MASM386 was likely a fork of the latest 5.1 code, modified to run and assemble under the 32-bit NT 3.1 and 3.5 operating systems (a 32-bit kernel with the UI of Windows 3.1), but before Microsoft had stabilized the MASM 6.x code branch.

The oldest version listed here is from December 1991 and is the only 32-bit MASM I've encountered that won't run on Windows XP and up (MessageBox "not a valid Win32 application" followed by console message "Access is denied."). The executable module has some invalid fields (virtualsize for the sections are zero), relocation table in an unknown format, and a host of other problems indicative of the fact that the program was built before the PE/COFF specification was finalized. I did not bother to install an NT 3.1 to see if I could get it to work, so I've got it listed as "untested".

Although the file timestamps range between 1991 and 1993, the copyright year is 1989. Although the 2 in the last portion of the version indicates there may have been a 5.NT.01 release, I don't know if there were any other publicly available releases of MASM386.

This hybrid version of MASM was a pretty strange animal because it is the only version of MASM I'm aware of that supports 32-bit targets without supporting the flat model. I'm sure there are other oddities too.

The \DDK\DOC\README.DDK file mentions only supporting this version of MASM as version 6.x had not been tested enough for use with the DDK:
*  Intel x86 assembler code

If the Win32 SDK is not installed or in the path, it is necessary to
copy the masm386 binary from the Win32 SDK if assembly code is used in
a driver targeted for the Intel x86 platform.  This is required to
build some of the video drivers for x86 such as the VGA display
driver.  The masm386.exe binary should be copied from the
\mstools\bin\i386 directory of the SDK to the \<ddkroot>\bin directory
where the DDK is installed.

It may also be possible to use other 32bit Intel x86 assemblers (such
as Microsoft MASM 6.x) but the DDK is not tested with other assemblers
and code changes may be required.
The version resource within MASM386.EXE contains (note the funny mixed-case with the Internal Name):
File version: 3.10.508.1
Description: Microsoft Assembler
Copyright © Microsoft Corp. 1981-1993
Company: Microsoft Corporation
Internal Name/Original File name: MAsm386.Exe
Language: Language Neutral
Product Name: Microsoft® Windows NT(TM) Operating System
Product Version: 3.10
The only other piece of documentation from the DDK was the MASM.TXT file, mostly explaining differences between this version of MASM and the 6.x series.

  • 5.1 as a 32-bit assembler:
    [bytepointer.com edit] MASM 5.1 turned into a 32-bit hybrid assembler for NT 3.x
  • Introduction of the .FPO directive:
    .FPO controls the emission of debug records to the .debug$F segment or section.

    The README.TXT from version 6.11, the README.TXT from version 6.11a and the README.TXT found in version 6.11d all document the .FPO directive as being present in MASM386 and initially for the 6.x series in version 6.11a. The .FPO directive was not supported in any other 6.x release. The .FPO directive would be re-introduced in version 8.0 for reasons that are unclear.
  • "Microsoft's early 32-bit development tools often included a descendent of the 5.10 series, usually called MASM386.EXE. The latest was labeled "5.NT.02" and responds as @Version=510. It's really primitive when compared to MASM 6.x."

    REFERENCE: r_harvey

MASM 6.0 © 1981-1991 [Command Line]
ML.EXE244,690 bytes (239k)md5=6b9ac50cd937732fdbd328d7f4f1431edate=4/3/1991 2:59pm
ML.EXE225,863 bytes (221k)md5=ac746c41188ab43aaf3a5a5097909e68date=4/3/1991 2:58pm(OS/2 version / untested)
@Version reports: 600
Retail Price: $150.00 / Upgrade Price: $75.00

This version of MASM introduced support for the 80486 (i486) processor released by Intel in April of 1989.

Intel 80486 Processor

Version 6.0 shipped the week of April 29th 1991 (see InfoWorld magazine article below). The 4-floppy distribution (on 1.2 MB 5¼ inch disks) included a PACKING.LST file on the first disk along with a README.DOC file.

On July 1, 1991, Dr. Dobbs published a good primer article for version 6.0, called Masm's Changing Face.

Most of the information below was derived from the 6.0 programmer's guide and other official sources (unless otherwise noted):

  • A personal computer running DOS version 3.0 or later or OS/2 version 1.1 or later.
  • 640K (kilobytes) of available memory (RAM) for operating under DOS (1 megabyte of RAM recommended)
  • 3 megabytes of RAM for operating under OS/2 (4 megabytes are recommended)
  • At least 384K of extended memory if you want to debug large DOS programs.
  • A hard-disk drive with at least 4 megabytes of free space. (The actual space required depends on the options you select.)
  • A floppy-disk drive.
  • Programs assembled with MASM version 6.0 run under DOS versions 2.1 and later.
  • Support for the Intel 486 (80486) processor instruction set:
    • The .NO87 directive disables all coprocessor instructions
    • MASM can assemble instructions specific to the 80486, enabled with the .486 directive. The .486P directive enables 80486 instructions at the highest privilege level (recommended for systems-level programs only).
    • New 486 processor instructions supported:
      BSWAP- Byte swap
      CMPXCHG- Compare and exchange
      INVD- Invalidate data cache
      INVLPG- Invalidate Translation Lookaside Buffer entry
      WBINVD- Write back and invalidate data cache
      XADD- Exchange and add
  • Support for the 32-bit flat memory model:
    In the flat memory model (available only in version 2.0 of OS/2), segments may be as large as four gigabytes because offsets contain 32 bits instead of 16. Segments are limited to 64K in all other memory models supported by DOS and earlier versions of OS/2. Version 2.0 of OS/2 runs only on 80386/486 processors.

    [bytepointer.com edit] Although this was the first official version supporting the flat memory model, it was only available for OS/2 version 2.0. Flat Model support for Windows NT was not yet available.
  • Operating Systems Support:
    Specifying the new OS_OS2 or OS_DOS keywords in the .MODEL statement allows the new .STARTUP directive to generate start-up code appropriate for the language and operating system. The new .EXIT directive generates the appropriate exit code.
  • New OS/2 Features:
    Create OS/2 applications with increased support for dynamic-link libraries (DLLs), multiple threads, and improved debugging options.
    [bytepointer.com edit] Added support for the SYSCALL calling convention (for all OS/2 version 2.0 functions).
  • Direct support for .COM files:
    [bytepointer.com edit] Jump to the 5.0 COM sample on this page to see just how tedious creating a COM file used to be. This was for two reasons: 1. the source code for a COM file didn't support simplified segment directives; 2. you had to assemble, link (creating an unusable EXE file) and then use EXE2BIN from your DOS distribution to generate the final COM file; 3. after all of this, debugging a COM file wasn't possible either because you couldn't embed symbolic debugging information in them.

    Microsoft KB24954: Producing .com Files With MASM explains the new and better way to create COM files, new for version 6.0:

    The Microsoft Macro Assembler packages prior to version 6.0 cannot produce .com files without an additional utility. One such utility is EXE2BIN, which is included with MS-DOS. It can convert .EXE files which have only one segment and an origin of 100h to .COM files. For more information on this utility, refer to your DOS manuals or contact the company which supplied your version of MS-DOS.

    MASM version 6.0 is the first version of the assembler to support the tiny model. Use the following steps the produce a .com file in MASM 6.0.

    1. Use .model tiny. Declare logical segments using the simplified segment directives or full segment declarations.


      Do not use the .model directive and assemble with /AT. Use full segment declarations.
    2. Make sure that the first statement in the the code segment is ORG 100h.
    3. Build the .com file.

      Compiling and linking in one step: If .model tiny was used, no options are needed. The linker will automatically receive the /TINY switch, the file extension on the file produced will be .com, and the executable is indeed a .com file.


      Performing a separate link: Specify the /TINY option on the link command line. The linker will issue the following harmless warning
      L4045: name of output file is 'filename'
      where 'filename' will have a .com extension.

    [bytepointer.com edit] The COM file sample from the 5.0 manual now looks like the following after modifying the source code to take advantage of the 6.0 COM file enhancements (and removing the comments):
    .MODEL  tiny
    message     DB      "Hello, world.",13,10
    lmessage    EQU     $ - message
    ORG 100h
    start:      mov     bx,1
                mov     cx,lmessage
                mov     dx,OFFSET message
                mov     ah,40h
                int     21h
                mov     ax,4C00h
                int     21h
                END     start
    The source code is much more elegant. Now, to build it with version 6.0, run the following commands:
        ml /AT /c example.asm
        link /tiny example.obj,example.com;
    The linker then produces a 33-byte COM file. This is 3 bytes less than the 5.0 version sample that resulted in a 36-byte COM file.
  • Specifying 16-Bit and 32-Bit Instructions:
    MASM supports all instructions that work with the extended 32-bit registers of the 80386/486. For certain instructions, you can override the default operand size with the W (word) and the D (doubleword) suffixes.
  • Introduction of the HIGHWORD and LOWWORD Operators:
    These new operators return the high and low words for a given 32-bit operand. They are similar to the HIGH and LOW operators of MASM 5.1 except that HIGHWORD and LOWWORD can take only constants as operands, not relocatables (labels).
  • MASM.EXE replaced by ML.EXE (MASM.EXE now just a compatibility driver for version 5.1 sources):
    MASM.EXE is now ML.exe: prior to version 6.0, the Microsoft Macro Assembler was MASM.EXE. Since version 6.0, it has been replaced by the more powerful and flexible ML.EXE using different command line options, such as allowing an assembly and link with a single command. MASM.EXE does remain, recognizing the old MASM driver command syntax to support existing batch files and makefiles prior to version 6.0. Internally, MASM.EXE translates command-line options to those accepted by ML.EXE, and then calls ML.EXE. The ML command-line options are now case-sensitive and must be separated by spaces.
  • Multiple Source Assembly:
    Although this was not mentioned in the manual's changelist, version 6.0 was the first version of MASM that could assemble more than one file in a single invocation from the command line while prior versions only supported assembly of a single file at a time. According to the InfoWorld article [see below] on April 29, 1991 (MASM 6.0 Changes), MASM's command line additionally supported wildcards.
  • Search order for include files:
    The search order for includes is different than simply looking in the current directory. MASM now searches for include files in the directory of the main source file. Similarly, MASM searches for nested include files in the directory containing the include file. Additional paths can be specified with the /I command-line option.
  • n-pass Assembler:
    When possible, MASM now performs assembly in a single pass, caching the source file in RAM and avoiding reading the file twice from disk. MASM 5.1 always assembled in two source passes. Because MASM now assembles in one pass, the directives referring to two passes are no longer supported. These include .ERR1, .ERR2, IF1, IF2, ELSEIF1, and ELSEIF2. If you use IF2 or .ERR2, the assembler now generates error A2061: "[ELSE]IF2/.ERR2 not allowed : single-pass assembler". The .ERR1 directive is treated as though it were .ERR and the IF1 directive is treated as though it were IF. MASM 5.1 directives that refer to the first pass are always true. Directives that refer to the second pass are flagged as errors. This change requires you rewrite the affected code, since OPTION M510 does not enable this behavior. Pass-sensitivity was normally used in version 5.1 in the following situations, and are no longer necessary in version 6.0:

    • Declaring an external variable only if it is not defined in the current module
    • Including a file of definitions only once to speed assembly
    • Generating an %OUT or .ERR message only once
    • Generating an error if a symbol is not defined but may be forward referenced
  • Support for the LROffset operator:
    For compatibility with applications for Windows, the LROFFSET operator can calculate a relocatable offset, which is resolved by the loader at run time. This allows the Windows memory manager to relocate code segments as neeeded.
  • Expanded high-level functionality and support for structures, unions and data types including pointer, signed and floating point types:

    • Type Initializers:
      You can now use the same type specifiers in initializations as in other contexts such as to define/initialize variables using BYTE, SBYTE, SWORD, and SDWORD, rather than simply DB.
    • Support for Signed Types:
      You can now use the SBYTE, SWORD, and SDWORD directives to declare signed data.
    • Support for Floating-Point Types:
      You can now use the REAL4, REAL8, and REAL10 directives to declare floating-point variables.
    • Type definitions can now include distance and language type attributes:
      Procedures, procedure prototypes, and external declarations now let you specify the type as a qualified type.
    • The syntax for defining and using structures and records has been enhanced:

      • Structures can be nested.
      • The names of structure fields need not be unique. As a result, you must qualify references to field names.
      • Initialization of structure variables can continue over multiple lines provided the last character in the line before the comment field is a comma.
      • Curly braces and angle brackets are equivalent. For example, this following code works:
        SCORE       STRUCT
            team1   BYTE       10 DUP (?)
            score1  BYTE       ?
            team2   BYTE       10 DUP (?)
            score2  BYTE       ?
        SCORE       ENDS
          first     SCORE      {"BEARS", 20,   ; This comment is allowed.
                                "CUBS", 10 }
          mov       al, [bx].score.team1       ; Field name must be qualified
                                               ;    with structure name.
    • Support for the definition of unions with the UNION directive.
    • Support for types (defining your own types), including pointer types, with the new TYPEDEF directive for later use in the program
    • Introduction of the SIZEOF operator:

      • When applied to a type, SIZEOF returns the size attribute of the type expression.
      • When applied to a data label, SIZEOF returns the number of bytes used by the initializer in the label's definition. In this case, SIZEOF for a variable equals the number of bytes in the type multiplied by LENGTHOF for the variable. The LENGTHOF operator returns the number of data items allocated for a data label.
  • Support for identifier names of up to 247 characters:
    All characters are significant, whereas under version 5.1, names are significant to 31 characters only.
  • Support for multiple-line initializers:
    A comma at the end of a line (except in the comment field) implies that the line continues. E.g.:
    longstring      BYTE       "This string ",
    bitmasks        BYTE       80h, 40h, 20h, 10h,
                               08h, 04h, 02h, 01h
  • Support for comments in extended-lines:
    Earlier versions allow a backslash ( \ ) as the line-continuation character if it is the last nonspace character in the line. MASM now permits a comment to follow the backslash.
  • New Predefined Symbols:
    The following new predefined symbols (also called predefined equates) provide information about simplified segments:
    Predefined Symbol  Value
    @stackDGROUP for near stacks, STACK for far stacks
    @InterfaceInformation about language parameters
    @ModelInformation about the current memory model
    @LineThe source line in the current file
    @DateThe current date
    @FileCurThe current file
    @TimeThe current time
    @EnvironThe current environment variables
  • Renamed Directives:
    Although MASM still supports the old names in MASM 5.1, the following directives have been renamed for language consistency:
    %OUT-> ECHO
    IRP-> FOR

    [bytepointer.com edit] %OUT was not only changed to ECHO, but ECHO could expand predefined text macros such as @Version as in the example below making it more handy for debugging. %OUT was not capable of this this expansion.
    ;works on MASM 6.0 and up
    %ECHO MASM reports its version as: @Version
  • New OPTION directive:
    The OPTION directive allows you to selectively define the assembler's behavior, including its compatibility with MASM 5.1.

    • 5.1 Compatibility Mode:
      MASM provides a "compatibility mode," making it easy for you to transfer existing MASM 5.1 code to the new version. You invoke the compatibility mode through the OPTION M510 directive or the /Zm command-line switch. In some cases, OPTION M510 does not support MASM 5.1 behavior. In several cases, this is because bugs in MASM 5.1 were corrected. If you have conflicts between identifier names and new reserved words use the "OPTION NOKEYWORD" to resolve errors generated from the use of reserved words as identifiers.
    • User-Defined Prologue/Epilogue:
      Support for user-defined stack frame setup (prologue) and cleanup (epilogue) code VIA macros and the OPTION directive. The prologue code generated immediately after a PROC statement sets up the stack for parameters and local variables. The epilogue code handles stack cleanup.
  • Enhancements to the ASSUME directive:
    MASM now automatically generates ASSUME values for the code segment register (CS) when a segment is opened. It is no longer necessary to include lines such as
    ASSUME CS:MyCodeSegment
    in your programs. In addition, the ASSUME directive can now include ERROR, FLAT or register:type. Generating ASSUME values for the code segment register CS to be other than the current segment or group is no longer valid.
  • The .STARTUP and .EXIT directives:
    These directives automatically generate appropriate startup and exit code for your assembly-language programs.
  • The PUSHCONTEXT and POPCONTEXT directives:
    PUSHCONTEXT saves the assembly environment, and POPCONTEXT restores it. The environment includes the segment register assumes, the radix, the listing and CREF flags, and the current processor and coprocessor. Note that .NOCREF (the MASM equivalent to .XCREF) still determines whether information for a given symbol will be added to Browser information and to the symbol table in the listing file.
  • MASM now generates complete CodeView information for all types:

    • PTR and CodeView:
      Under MASM 5.1, applying the PTR operator to a data initializer determines the size of the data displayed by CodeView. You can still use PTR in this manner, but it does not affect CodeView typing. Defining pointers with the TYPEDEF directive allows CodeView to generate correct information.
  • More powerful features for declaring and calling procedures:

    • The extended PROC syntax for generating stack frames has been enhanced since version 5.1.
    • Introduction of the PROTO directive:
      PROTO lets you prototype procedures in the same way as high-level languages. PROTO enables type-checking and type conversion of arguments when calling the procedure with INVOKE.
    • Introduction of the INVOKE directive:
      INVOKE automatically generates code to pass arguments (converting them to a related type, if appropriate) and call a procedure according to the prototype and specified calling convention. MASM also provides the VARARG keyword to pass a variable number of arguments to a procedure with INVOKE.
    • Introduction of the ADDR keyword:
      When used with INVOKE, it changes an expression to an address expression for passing by reference instead of value, in the same way as the address-of operator (&) in C.
  • Simplified methods for applying public attributes to variables and routines in multiple-module programs making it easier than in version 5.1. The EXTERNDEF and PROTO directives make it easy to maintain all global definitions in include files shared by all the source modules of a project.

    • Introduction of the EXTERNDEF directive:
      MASM 5.1 requires that you declare public and external all data and routines used in more than one module. A single EXTERNDEF directive now accomplishes the same task. EXTERNDEF lets you put global data declarations within an include file, making the data visible to all source files that include the file.
    • Specify Alternate Symbol Names for the Linker:
      The syntax for EXTERN allows you to specify an alternate symbol name, which the linker can use to resolve an external reference to an unused symbol preventing linkage with unneeded library code.
    • Case Sensitivity adherence to Langtype:
      In MASM 5.1, sensitivity to case is influenced only by command-line options such as /MX, not the language type given with the .MODEL directive (langtype). Now langtype takes precedence over the command-line options that specify case sensitivity.
  • New directives for generating loops and decision statements:

    • Introduction of High-Level (C-like) Flow-Control Constructions:
      Several new directives that generate code for loops and decisions depending on the status of a conditional statement (tested at run time rather than at assembly time) include: .IF, .ELSE, .ELSEIF, .REPEAT, .UNTIL, .UNTILCXZ, .WHILE, and .ENDW. The associated .BREAK and .CONTINUE directives for loops and IF statements are also provided.
    • Support for automatic Jump Encoding Optimization:
      MASM now automatically generates the smallest encoding for direct unconditional jumps. If a conditional jump requires a distance other than SHORT, MASM generates the necessary comparison and unconditional jump to the destination.
    • Better Jump Handling:
      Better handling of the "Jump Out of Range" errors present in version 5.1 and earlier due to jump offsets greater than 128 bytes.
      REFERENCE: r_harvey
  • Enhancements for writing and using macros:

    • Required and Default Macro Arguments:
      You can now specify default values for arguments or mark them as required using the := operator or REQ respectively.
    • Introduction of the VARARG keyword:
      MASM 5.1 ignores extra arguments passed to macros. Now you can pass a variable number of arguments to a macro by appending the VARARG keyword to the last macro parameter in the macro definition. The macro can then reference additional arguments relative to the last declared parameter.
    • New Directives for Macro Loops:
      You can implement loops inside of macros in various ways. For example, within a macro definition, the new WHILE directive expands the statements in a macro body while a condition remains true. The other macro loop directives IRP, IRPC, and REPT, have been renamed FOR, FORC, and REPEAT.
    • The GOTO Directive for Macros:
      Within a macro definition, GOTO transfers assembly to a line labeled with a leading colon(:).
    • Macro Functions:
      You can define macro functions, which return text macros. Several predefined text macros are also provided for processing strings. Macro operators and other features related to processing text macros and macro arguments have been enhanced.

      • Introduction of the EXITM directive:
        At assembly time, macro functions can determine and return a text value using EXITM.
      • Introduction of the TEXTEQU directive for text macros:
        Text macros allow greater flexibility than EQU. For example TEXTEQU can assign to a label the value calculated by a macro function.
      • Introduction of the following predefined text macro functions:
        Predefined macro string functions concatenate strings, return the size of a string, and return the position of a substring within a string.

        @CatStr- A concatenated string
        @InStr- The position of one string within another
        @SizeStr- The size of a string
        @SubStr- A substring
  • CodeView Debugger 3.12:
    Track down program bugs and logic errors more quickly with the new Microsoft CodeView® debugger version 3.12. With an 80286 or 80386 processor and 1 megabytes or more of RAM, you can debug a program up to 640K in size in real mode.
  • New Tools Added:

    • Introduction of the Programmer's WorkBench (PWB):
      The Programmer's Workbench offers an integrated development envieronment (IDE) from which you can write, edit, debug, and execute code. The PWB could be configured to edit, build and debug in many languages and also offers project capabilities. Edit source code with PWB's mouse- and window-oriented editor. Cross-reference program procedures with the PWB Source Browser.

      [bytepointer.com edit] This was a DOS predecessor to the Visual C/C++ Editor "Visual Workbench" that would be released about 2 years later, and then later renamed to "Visual Studio".
    • Introduction of the H2INC utility:
      The program H2INC.EXE converts C include files to MASM include files. It translates data structures and declarations but does not translate executable code.
    • The MAKE utility is replaced by NMAKE:
      NMAKE provides new functions for evaluating target files and more flexibility with macros and command-line options.
  • Introduction of the Microsoft Advisor System:
    Access MASM language, assembler, linker, and utility documentation with the Microsoft Advisor and QuickHelp online reference systems.
  • Removed Utilities:

    • CREF was removed, but will be included once again in version 6.1 and finally in 6.11.
    • EXEMOD
  • Command Line Changes:
    [bytepointer.com edit] The command line options for version 6.0 and up were completely different than the previous versions of MASM. This is one reason why Microsoft included the MASM.EXE compatibility driver to invoke ML.EXE with the equivalent 5.1 options. One notable change is that you now have to issue the /? switch to get a list of the available command line options. In previous versions of MASM this was done with the /help (or simply /h) option. /h no longer works and /help will display the command line options or bring up the QuickHelp utility (QH.EXE, if installed and set up properly).
  • According to Windows Assembly Language & Systems Programming by Barry Kauler, Masm 6.0 was not technically “Windows-aware” until at least version 6.1, but standalone Windows applications could be built as long as the SDK was installed.
Article: MASM 6.0 Changes
InfoWorld - April 29, 1991
Article on MASM 6.0 Changes

MASM 6.0 Box Images
MASM 6.0 Box Front MASM 6.0 Box Back MASM 6.0 Box Right Side MASM 6.0 Box Left Side MASM 6.0 Box Bottom MASM 6.0 3.5 Disk/Manual set

MASM 6.00A

Although apparently not publicly released, there were changes to this version that showed up in 6.00B.

  • "This version was not released (didn't even escape). It fixed some macro and structure alignment problems, and made @FileName always return an upper case string (it had been returning whatever it found on the command line unless you used wild cards)."
  • REFERENCE: r_harvey

MASM 6.00B © 1981-1992 [Command Line]
ML.EXE250,074 bytes (244k)md5=62d24aaca0b1373cf9e374703b3dc6abdate=3/18/1992 5:31pm(file date from ML.EX$ on setup disk)
ML.EXE230,850 bytes (225k)md5=f882dc9968c1cfd4219173994ad0ca6fdate=3/18/1992 4:40pm(file date from ML.EX$ on setup disk / OS/2 version / untested)
@Version reports: 600

Version 6.00B was the last version of MASM to be a pure 16-bit DOS application (and likely the last to support OS/2), released just less than a year after 6.0. This didn't mean future versions wouldn't run under DOS, but MASM would be a Windows hybrid executable allowing it to be run under DOS and NT simultaneously. This benefit did not come without a cost however, as MASM's file size had to grow over 100k to accommodate addition of the DOS Extender (see section MASM 6.1 below).

It is not known if this version was ever distributed as a patch, but for some, it was integrated directly into the disk set "sold as" the retail 6.0 version.

The changelist below where unspecified was derived from the README.DOC.

  • The high-level CALL directive INVOKE can now be used as the first statement of a procedure.
  • MASM.EXE can now invoke MLX.EXE by using the /Q command-line option. MASM.EXE still invokes ML.EXE when the /Q option is not used.
  • Code and data alignment problems are corrected.
    • If the ALIGN directive was used with a value greater than 2, the bytes representing the instructions that were generated for the padding (mov ax, ax) were reversed.
    • If an ALIGN directive immediately followed any composite data declaration (i.e. DUP, STRUCT, etc.) the results of the ALIGN directive would be incorrect.
  • Structure padding is now correct.
  • Improvements were made to the MLX.EXE DOS Extender.
  • Increased CodeView(R) information capacity is now available.
  • COMM directive syntax corrections were made.
  • ORG $ + X, where X is a constant, no longer effects ORG directives found later in the source file.
  • Miscellaneous problems in listing files are corrected.
  • Added Stdcall calling convention switch (NOT from README.DOC). The /G command line option present in 6.0:
    /G<c|d> Generate Pascal or C calls
    Was changed to [add Stdcall] :
    /G<c|d|z> Use Pascal, C, or Stdcall calls
    NOTE: The Stdcall ("z" option) for the /G switch was not officially documented until version 6.1.

    According to MSDN article Q94314 (below), the Stdcall feature was technically added in 6.00a, but since 6.00a wasn't publicly released, that information is being included here:

    The Microsoft Macro Assembler (MASM) versions 6.0a and later support generating 32-bit flat memory model code through the .MODEL flat directive. When combined with the CVTOMF and LINK32 utilities and the KERNEL32.LIB library distributed with the Windows NT software development kit (SDK) or the LINK utility and the KERNEL32.LIB library distributed with Microsoft Visual C++ for Windows NT, MASM can generate a 32-bit flat memory model application for the Windows NT environment.

    Because MASM version 6.0 does not properly support the _stdcall convention, it cannot be used to generate applications for the Windows NT environment.
  • Calling Convention Changes:

    Changes were made to the STDCALL calling convention after MASM 6.0 was shipped. These changes are reflected in MASM 6.0b. To maintain the previous use of STDCALL, use the new OPTION directive:
    Below is a chart describing all of the calling conventions found in MASM 6.0b.

    For the procedure func(a1,a2, ... an), the following chart describes the results when used with the calling convention found on the left side.
                                  for Stack        Argument     VARARG
        Convention     Name        Cleanup        Push Order    Allowed
        ----------     -----     -----------    -------------   -------
        C              _func     caller         right-to-left     Yes
        BASIC          FUNC      callee         left-to-right     No
        SYSCALL        func      callee         right-to-left     Yes
        STDCALL (16)   _func@N   callee         left-to-right     No
        STDCALL (32)   _func@N   callee         right-to-left     No
        OLDSTDCALL     _func     caller/callee* right-to-left     Yes
    STDCALL Naming Note
    In addition to the prefixed underscore, STDCALL also adds the suffix, @N, where N is the total number of bytes that will be pushed onto the stack.

    Also, note that argument push order differs between 16-bit and 32-bit procedures. *OLDSTDCALL
    The responsibility for cleaning the stack is always on the callee, unless the procedure uses VARARG's, in which case the caller is responsible for cleaning the stack.
  • "MASM 6.00B fixed a few minor bugs missed in 6.00A. It was a fast, versatile program. It was the last version that would run on any Intel-compatible processor. I believe that it was also the last version that officially supported OS/2. Microsoft sent copies of 6.00B free of charge to all registered owners without saying a word about it. (Really! In fact, I bought Windows 1.0, and later they sent me a free upgrade to 1.03; I haven't seen them do that sort recently, though.) If you're running an older machine but want the benefits of new-fangled Assemblers, this is your MASM."

    REFERENCE: r_harvey

  • Vernon from pcdosretro (lead developer for IBM PC DOS 7) had the following comment in response to this page previously reporting details from the Phoenix BIOS Developer's Blog that early versions of MASM 6.x were "buggy":

    "By the way the comment about the MASM 6.x series being pretty buggy until 6.14 is just not true. As an assembly language programmer I have used MASM extensively since 4.0 and found that 6.00B (I never used the original 6.0) was a MAJOR step up from previous versions in terms of stability and consistency and it had very few bugs. The only bugs I can think of in 6.00B were an occasional extra tab in listings and INVOKE/PROTO not always working as expected which was fixed in the 6.1x series."

MASM 6.1 © 1981-1992 [Command Line]
ML.EXE360,480 bytes (352k)md5=49790131ea2e38e1c14dc90111d3de33date=11/16/1992 4:00pm
@Version reports: 610
Retail Price: $199.00

MASM 6.1 shipped in January 1993. It was the first version to build Windows NT binaries (see InfoWorld article below) and the first DOS/Windows hybrid version of MASM (importing KERNEL32.DLL and NTDLL.DLL). This was made possible by the 3rd-party DOS Extender DOSXNT by Phar Lap Software, Inc. DOSXNT was required for MASM until the last DOS version (6.11d), but is still required by Microsoft's last official 16-bit linker (5.60.339): Lnk563.exe.

This was also the last version with printed manuals, although these manuals were shipped with the later 6.11 version (the last retail box set). For this reason, even to this day, the manuals are sought-after as they strill contain relevant information about the assembler. They are available in PDF and DOC form on the internet as well as on MSDN. After these manuals, Microsoft began distributing MASM documentation exclusively by electronic means either with the MASM binaries themselves or alongside the Visual C++ documentation on MSDN after version 6.15. Some of the relevant documentation files included with this distribution include: README.TXT (although the document is titled README.DOC), ERRMSG.TXT, CREF.DOC, CV.TXT, SMARTDRV.DOC, and SAMPLES.TXT.

The following information unless otherwise noted was derived from the printed manuals:

SYSTEM REQUIREMENTS (from retail box shown below):
  • Personal computer with a 386 or higher processor running MS-DOS operating system version 3.3 or later
  • 4 MB of memory
  • One high-density disk drive and a hard disk with 10 MB available (3.5" low-density disks available on request
  • Flat memory model support for the new 32-bit Microsoft® Windows NT™ operating system:
    Version 6.0 added the initial flat model support, but only for OS/2. Now MASM can build 32-bit binaries for Windows NT. The flat model allows segments as large as 4 gigabytes and offsets are 32 bits instead of 16 bits. All other memory models limit segment size to 64K for MS-DOS and Windows.

    When you are creating a 32-bit application, you must link separately with a 32-bit linker. To prepare your object files for 32-bit linking, assemble using the following switches:
    - /c (assembles without linking)
    - /coff (causes object files to be created in Windows NT-compatible common object file format)
    After assembling, link with your 32-bit linker.

    To build NT binaries, a specialized linker available in the WinNT 3.5 SDK was needed

    Wikipedia's Entry for Phar Lap mentioned the following about the NT compatibility of ML.EXE:

    "Unfortunately, MASM 6.1 and the 16-bit version of the Visual C++ 1.0 compiler were Win32 applications written for a beta version of Windows NT that was bound with the TNT DOS Extender, which means it could not run on the final version of Windows NT until Beta2Fix.exe was run, which replaced all references to NTDLL.DLL with BETA2.DLL. This was fixed in MASM 6.11 and Visual C++ 1.5."

  • Support for OS/2 Silently Removed:
    [bytepointer.com edit] Although no official announcement was made, almost all references to OS/2 were removed from the 6.1 documentation (OS/2 was only mentioned on the copyright page, MS-DOS handling of the Critical Error flag, minimum Intel processor types required for DOS and OS/2 operating systems, and some assembler and linker errors). Likewise, the OS/2 BIND utility was also removed. IMPLIB, a formerly OS/2-only utility now worked with Windows and NT DLLs, adding 2 new command line options (/ntdll and /nowep).

    Gordon Letwin's OS/2 usenet post titled: What's happening to OS/2 is an interesting read; an opinion from a Microsoft programmer posted 8/17/1995 about why OS/2 was "doomed".
  • Support for PE/COFF formats:
    MASM now supports producing object modules in the Portable Executable (PE/COFF) format, as required by Windows NT.
  • Introduction of MLX.EXE, the DOS-Extended Assembler:
    MLX allows the assembler to run in protected mode using one of the following drivers: DPMI, VCPI and XMS. It is meant as a replacement for ML.EXE only if running ML with the /VM virtual-memory option fails due to an out of memory error as ML.EXE with the /VM option runs significantly faster than MLX due to its use of real mode. Also, MLX can only assemble one file at a time.
  • ML.EXE now a 32-bits:
    ML now runs in 32-bit protected mode under MS-DOS, giving it direct access to extended memory for assembling very large source files.
  • Windows Aware:
    A collection of tools lets you write a dynamic-link library (DLL) for the Microsoft® Windows™ operating system without the Windows Software Development Kit. The LIBW.LIB library provides access to all functions in the Windows application programming interface (API), so your DLL can display menus, dialog boxes, and scroll bars. DLLs are compatible with the Visual Basic programming system.
  • Support for Instruction Timings:
    Program listings now support displaying instruction timings. The number of required processor cycles appears adjacent to each instruction in the listing, based on the selected processor.
  • CodeView Debugging:
    Version 6.1 generates debugging information for CodeView version 4.0 and later.
  • Greater compatibility with version 5.1 than MASM 6.0:
    Many programs written with version 5.1 will assemble unchanged under MASM 6.1. The OPTION M510 directive (or the /Zm command-line switch) assures nearly complete compatibility between MASM 6.1 and MASM 5.1.
  • CMP byte-register Encoding Change:
    MASM 6.1 uses a different encoding for the CMP <reg8>,<reg8> instruction than MASM 6.0 did. There is no difference in length or processor timing.
  • Command Line Options Added:

    /G - New "z" option for Stdcall (this was fully or partially supported in 6.00B, but not documented until now)
    /coff - Generate COFF format object file
    /Sc - Generate timings in listing
    @<file> -  Response Files:
    Information on response files is not included in the MASM 6.1 manuals; however, this information can be found in "ML Command Line Options" in Online help.

    [bytepointer.com edit] What this means is that this useful feature is not documented anywhere but the now obscure QuickHelp utility. To get this running, navigate to the BIN directory containing ML.EXE. Ensure your PATH environment variable is set to the HELP directory installed with the distribution. Run "ml /help". QuickHelp will pop up with a "ML Command-Line Syntax" page. About midway through the page, select "ML Options". The first item in the next page is the "@<file>" switch for response files. Select this option to display the details.

    Command Line Options Removed:

    /Fb- Generate bound executable
    /VM- Enable virtual memory
  • New WIN.INC Include File:
    Rather than have people attempt to convert WINDOWS.H to a MASM include file with the H2INC utility, Microsoft provided one named WIN.INC. The reason was that WINDOWS.H had to be tweaked a bit prior to running through H2INC. The nice thing is that all of the tweaks are explained in detail at the top of the file should you want to create your own or use the same techniques for other header files.
  • CREF:
    The CREF utility, missing since version 5.1 is back and is updated for the MASM 6.x series. CREF will be distributed once more as part of MASM's last retail release in version 6.11. This CREF details can be read in the CREF.DOC.
Article: MASM 6.1 Update
InfoWorld - December 14, 1992
Article on MASM 6.1 Update

MASM 6.1 Box Images
MASM 6.1 Box Front MASM 6.1 Box Back MASM 6.1 Box Side

MASM 6.1 3.5 Disk Set and Manuals (with 6.11 disks)
MASM 6.1 3.5 Disk Set and Manuals (with 6.11 disks)

MASM 6.1a © 1981-1992 (a.k.a. 6.10a) [Command Line]
ML.EXE360,992 bytes (353k)md5=dd344d3f0162badea58ae801ca287b63date=3/12/1993 1:59pm(Date from patch README, but unconfirmed if correct)
@Version reports: 610

This was oddly the only version of MASM in the 6.x series that did not have a dependency on the ML.ERR file (error message strings). For this reason, I suspect it evolved internally from a 5.1 series code fork. The README.TXT distributed with the patch is the source of changelist information shown below.

  • DISTRIBUTED AS PATCH (61PTCH.ZIP) for version 6.1 (reportedly posted on the Microsoft BBS).
    AFFECTED FILES: 10 (7 changed, 3 added)

  • Compatibility problems with Microsoft Visual C++:

    • MASM 6.10 cannot be installed in the same directory as Microsoft Visual C++, because of DOS extender conflicts. MASM 6.1a uses the same version of the DOS extender as Visual C++, eliminating this problem.

      NOTE: Microsoft Visual C++ contains newer versions of some utilities. To use the newer utilities, ensure that Visual C++ comes before MASM on the path.
    • The MASM 6.10 PWB extensions use /NOF as an abbreviation for the "Translate Intrasegment Far Calls" linker option. /NOF is not a legal option for the Visual C++ linker. To make PWB change /NOF to /NOFA:

      1. Open the desired project.
      2. From the Options menu, choose Link Options.
      3. Select Additional Debug Options or Additional Release Options.
      4. Choose OK to close the Additional Options dialog box.
      5. Choose OK to close the Link Options dialog box.
  • Inability to run MASM from a read-only network drive:
    MASM now correctly uses the TMP environment variable to create swap files for virtual memory. If you are running MASM from a read-only network drive, ensure the TMP variable is set to a drive and directory for which you have write permission.
  • Bugs Fixed:
    Errors when assembling a very large number of files using ML *.ASM have been fixed.
  • Added compact memory model Windows DLL library (CNOCRTDW.LIB):
    CNOCRTDW.LIB is the compact memory model version of the Windows DLL startup code. Because Windows DLLs rarely use the compact model, this file is not typically needed. To use CNOCRTDW.LIB, make sure it is in the MASM libraries directory (for example, C:\MASM61\LIB).
  • Added virtual memory browser database utility (BSCMAKEV.EXE):
    BSCMAKEV is a version of the BSCMAKE browser database utility which uses virtual memory. BSCMAKEV is slower than BSCMAKE, but it can handle larger databases. To use BSCMAKEV, make sure BSCMAKEV.EXE and BSCMAKE.EXE are in the same directory. BSCMAKE will automatically invoke BSCMAKEV when required.
  • Added PWB 2.1 extension for Microsoft Profiler (PWBPROF.XXT):
    PWBPROF.XXT enables the use of the Microsoft Source Profiler version 1.0 with PWB. The PWB extension originally supplied with version 1.0 of the Profiler is not compatible with the current version of PWB. To use the Profiler with PWB, rename this file to PWBPROF.MXT and make sure it is in the same directory as PWB (for example, C:\MASM61\BIN). The extension will automatically be loaded when PWB is run.
  • "MASM 6.10A began shipping at the end of 1992. The A-release updated the memory manager for compatibility with Microsoft's Visual C++ 1.0, and corrected some memory management problems. Complaints from fuddy-duddies forced Microsoft to revert to the old-style lea encoding. Unfortunately, 6.10A's wild card support no longer worked reliably if you had more than about 180 files."
  • "While memory requirements zoomed, MASM 6.10A was actually slower than 6.00B. If you had limitless memory, you could assemble limitlessly-large files--though even version 5.10B could handle 300K files. In keeping with Visual C++ 1.0, which could slurp-up over 50MB of disk space, everything about MASM 6.10A grew--even the linker was over 300K. "
  • "Version 6.10A shipped with the final update of the Programmer's WorkBench (PWB) editor, which was like M with a user interface. If PWB's keyboard repeat rate goes crazy, remove the Fastfunc lines from TOOLS.INI, or try the Microsoft C/C++ 7.00 version (early 1992). The Visual WorkBench (VWB), a Microsoft Windows editor in Visual C++ 1.0 (early 1993), replaced PWB. As of this writing (March 2002), VWB and its make files are indifferent, if not hostile, to MASM. Now, Microsoft's Visual Studio allows you to add any files to projects, even MASM, if you manually set compile switches, and you have to set those switches again for each additional file added to projects. If you use a lot of Assembly files in a C/C++ project, expect a lot of fussing with dialog boxes to get it all working together."
  • "If you use complex, multi-line high-level directives in very large files, you may experience "Line too long" errors that have nothing to do with the line they reference. Shorten lines, even comment lines, within the high-level structures until the errors go away. Running MASM from the DOS command line instead of Microsoft Windows fixes many mysterious problems. The real fix will appear seven years later."
  • REFERENCE: r_harvey

MASM 6.11 © 1981-1993 [Command Line]
ML.EXE388,608 bytes (380k)md5=0a05c3eae7888a2f01330862eeea7efddate=9/24/1993 8:25am(Date from Setup File ML.EX$)
@Version reports: 611
Retail Price: $249.00

This version of MASM introduced support for the Pentium (i586) processor released by Intel on 3/22/1993. pcjs.org has a directory listing of this version's setup file (ML.EX$) with an alternative date of almost 1 day earlier than that shown above at 9/23/1993 11:25pm.

Intel Pentium i586 Processor

This was the last retail version of MASM, and thus the last stand-alone product complete version (i.e. full set of disks, not a patch). This version shipped with manuals from version 6.1.

This version's list price increased to a whopping $249.00 (the highest price for MASM to date). According to Microsoft's MASM KB Article Q228454, "MASM 6.11 is no longer available as a retail product." and further indicating it could be ordered with a registered copy of Visual C++ or through some levels of MSDN. The updated documentation files included with this distribution include: README.TXT, PENTIUM.TXT, ERRMSG.TXT, CV.TXT, and SAMPLES.TXT.

MASM no longer had a dependency on NTDLL.DLL (as version 6.1 and 6.1a did), just KERNEL32.DLL (when running under NT).

  • Personal computer using a 386 or higher processor running MS-DOS version 3.3 or later, Windows version 3.1 or later, or Windows NT version 3.1 or later.
  • 4 MB of available memory.
  • Hard disk with 10 MB available space.
  • One 3.5" high-density (1.44 MB) disk drive (3.5" low-density (720K) or 5.25" high-density (1.2 MB) disks available separately with coupon enclosed).
  • To target Windows 3.1, you need one of the following:
    • Microsoft Windows Software Development Kit (SDK) 3.1.
    • Microsoft Visual C++ Development System, Standard or Professional Edition.
  • To target Windows NT, you need one of the following:
    • Microsoft Windows NT Software Development Kit (SDK).
    • Microsoft Visual C++ Development System, 32-Bit Edition.
  • New Pentium Directives:
    • .586 - enables assembly of non-privileged instructions
    • .586P - enables privileged instructions in addition to the non-privileged instructions
  • New Pentium Instructions:
    The new instructions are extensions to the Intel486 instruction set:

    CMPXCHG8B - Compare and Exchange 8 Bytes
    CPUID - CPU Identification
    MOV - Move to/from Control Registers (CR0, CR2, CR3, CR4) to or from a general purpose register
    RDMSR - Read from Model-Specific Register
    RDTSC - Read from Time Stamp Counter
    RSM - Resume from System Management Mode
    WRMSR - Write to Model-Specific Register
  • LEA instruction changes:
    [bytepointer.com edit] This change made it into the previous version (6.1a) according to r_harvey, but officially documented in this version.

    The MASM 6.1 Reference indicates that the LEA instruction is encoded as a MOV when the source operand is a direct memory address. In response to programmer requests, MASM 6.1x no longer performs this optimization automatically. The optimization can be performed by using the OPATTR operator, as shown in the following macro:
        MOVLEA MACRO Dest, Symbol
        IF (OPATTR(Symbol)) AND 08h
             MOV Dest, OFFSET Symbol
             LEA Dest, Symbol
  • .FPO Directive:
    The .FPO directive controls the emission of debug records to the .debug$F segment or section. This directive was originally included with MASM386 and is not supported by MASM 6.11. If you are using both MASM 6.11 and MASM386, the following allows you to continue to implement the .FPO directive:
    IF @version LT 600
  • Linker Changes:
    [bytepointer.com edit] The ALIAS directive is documented in the README.TXT:

    The ALIAS directive is not included in the printed documentation for MASM 6.11. The ALIAS directive can be used for creating libraries that allow the linker (LINK) to map an old function to a new function.
    Syntax:    ALIAS  <alias> = <actual-name>
    where alias is the alternate or alias name, and actual-name is the actual name of the function or procedure. The angle brackets are required. The ALIAS directive should be used with LINK 5.3 or later and LIB 3.2 or later. At this time, ALIAS functions only with the 16-bit linker.
  • New /WIN32 switch to H2INC:
    Use the /WIN32 switch with H2INC to convert C header files to NT-compatible MASM include files. When you use the /WIN32 switch, C int data types are converted to the 4-byte assembler equivalent DWORD (signed int data types are converted to SDWORD). Without the /WIN32 switch, H2INC converts int data types to 2-byte WORD (and signed int data types to SWORD).

    [bytepointer.com edit] This version of H2INC crashes with the simplest of C header files (such as a single #define, a single structure with two members, or even a file with nothing in it!) with or without the new argument. It can however display its version header and command line help without crashing. The version of H2INC that is released with the next version (MASM 6.12) does not crash in this way. I have verified the crash on XP and DOSBox, although the crash under DOSBox results in a more meaningful error:
    DOSXNT : fatal error DX1020: unhandled exception: Page fault;
    contact Microsoft Support Services
    ProcessId=485 ThreadId=486
    User Registers:
    EAX=00000000h EBX=00000001h ECX=00000000h EDX=00000000h
    ESI=00079963h EDI=00186F00h EBP=00186F5Ch ErrorCode = 00000004h
    DS=0017h ES=0017h FS=005Fh GS=0017h FLG=00003246h
    CS:EIP=000Fh:00068473h SS:ESP=0017h:00186ED4h
  • Filename Wildcard Problem Fixed

  • REFERENCE: r_harvey
MASM 6.11 Complete Disk Set
MASM 6.1 Disk Set

MASM 6.11a © 1981-1994 [Command Line]
ML.EXE382,976 bytes (374k)md5=58ab843e26f5b75197b4aab519c23ddfdate=3/21/1994 12:22pm(Date from Patch Files)
@Version reports: 611

Microsoft has documented this version as being a "maintenance release". The patch was previously available on the Microsoft FTP site but it was taken down quite some time ago. Interesting they left all other 6.1x patches except this one. Without jumping to conspiracy theories as to why, it is possible they removed this version because it made use of "experimental" NT features that had since been solidified or removed in later versions (such as the mysterious .FPO directive which disappears after this version only to be reimplemented in version 8.0 approximately 11 years later).

Regardless, EMS Professional still offers a shareware CD collection (named ASM UTIL) containing this patch and it is reported as being on the September 1995 Technet Supplemental CD, provided you can dig up an old copy somewhere. Or, you can download the patch package below. Although not the original self-extracting EXE, it contains all the files within the original patch package for patching version 6.11. The file details for the original package were reportedly: ML611A.EXE 330,893 bytes (323k) md5=38C1C740C8FBFB459699902388154192 according to processlist.com, blog entries on Computer Programming Forum and MASMForum.

The 6.11a README.TXT explains the changes, although it seems the primary purpose for this version was the backwards-compatible support for the .FPO directive only previously available under MASM386 5.10.NT (a 32-bit version for MASM for NT based on MASM 5.1). Due to the MASM386 compatibility, I suspect this version was intended as the next upgrade from MASM386, bringing along the bugfixes and new features of the MASM 6.x series to code that was most-likely stuck in version 5.1-land.

Microsoft KB article Q120920 (9/21/1994) "Visual C++ Vers 2.0 README.WRI, Part 4 Integrated Debugger" is available on the "MSDN 97" help library, but does not seem to be available on the web. This article references MASM 6.11a:

The Visual C++ version 2.0 debugger's Disassembly window may not display lines correctly if you are assembling some modules of your Visual C++ application with Microsoft Macro Assembler (MASM) version 6.11 and using linker version 2.50. To correct this problem, you should upgrade to the MASM version 6.11a maintenance release and use the /COFF option on the ML command line.

The MASM version 6.11a maintenance release is available on the Microsoft Download Service (MSDL), phone 206-936-6735.

  • DISTRIBUTED AS PATCH (ML611A.EXE) for version 6.11 / available here as ML611A.ZIP / 307k
    LAST OFFICIAL DOWNLOAD LOCATION: ftp://ftp.microsoft.com/Softlib/MSLFILES/Ml611a.exe
  • MASM now supports structure packing on 8 byte boundaries as well as 16 byte boundaries using the /Zp8 or /Zp16 switches. Older versions of Masm only allowed up to /Zp4 structure packing.
  • New .FPO Directive:
    FPO stands for Frame Pointer Omission. The .FPO directive is a feature added to MASM386 5.10.NT that controls the emission of debug records to the .debug$F segment or section of the object file. These records are the same records that the Microsoft Visual C++ 1.10 or Microsoft Fortran PowerStation compilers emit when they perform frame pointer elimination under /Oy and /Ox optimization control, respectively. Unlike the compiler, MASM never performs any such optimization. it simply passes on the information supplied by the programmer within this directive to the object file.

    The .FPO directive does not have to be used in order to debug assembly programs under the Microsoft Visual C++ 1.10 or Microsoft Fortran PowerStation debuggers whether they are stand alone Windows NT applications or mixed language C\Assembly or Fortran\Assembly Windows NT applications. This directive has been implemented to provide better backward compatibility with assembly code written for MASM386 5.10.NT, which is provided with the Windows NT DDK.

    The FPO directive should only be used on naked procedures or those procedures not declared with proto and called with invoke. Also you do not need to use the .FPO directive to debug naked procedures or on procedures that use proto and invoke.

    The following 6 parameters are used within the directive as follows.
    .FPO (  number of bytes in a procedures local variables divided by 4, 
        number of bytes in a procedures parameters divided by 4,
        number of bytes in a procedure prologue,
        number of registers saved by a procedures prologue,
        If EBP is allocated,
        Frame Type )
    Parameters                                      Range 
    ----------                                      -----
    number of bytes in local variables / 4          >= 0
    number of bytes in parameters / 4               0 - 65535
    number of bytes in the procedure prologue       0 - 255
    number of registers saved                       0 - 7
    If EBP is allocated                             0 = false, 1 = true
    Frame Type                                      0 - 2
    The valid values for the Frame Type parameter above are
    FRAME_FPO   0
    FRAME_TSS   2
    The C compiler only generates entries with FRAME_FPO. The other two types are used inside the NT kernel to all stack traces across trap and tss frames that can appear in ring 0 code.

    Example Usages:

    aproc proc
        .FPO ( 0, 0, 0, 0, 0, 0 )       ; all params are zero. 
    aproc endp
        push    +000000001h             
        call    aproc
        add     esp, 04h
    aproc proc
        push    ebp
        mov     ebp, esp
        .FPO ( 0, 1, 3, 1, 1, 0 )       ; 0 = no locals
                        ; 1 = 4 byte param \ 4
                        ; 3 = bytes in procedure prologue
                        ; 1 = one register saved in prologue
                        ; 1 = if EBP was allocated
                        ; 0 = frame type of FPO
        mov     eax, dword ptr [ebp+8]  ; move the passed param to EAX.
        ret     00h
    aproc endp
  • IMPLIED FIXES? (Removed from Known Assembler Bugs present in README.TXT for version 6.11):

    • Intersegment near jumps do not work across files (externs) in flat model. When programming in flat mode, make sure that all intersegment near jumps occur within the same file.
    • The /link command line option for ML causes all following parameters to be passed to the linker. If the /nologo command line option is passed to the linker, the linker may parse other parameters incorrectly.

MASM 6.11c © 1981-1994 [Command Line]
ML.EXE381,952 bytes (373k)md5=5312c5bc214e2049d727fef15ad41ab5date=8/25/1994 6:30pm(from Win95 DDK)
@Version reports: 611

This version was shipped with the Windows 95 and NT 3.5 DDK's for building drivers. The short README.TXT included said:
This directory contains upgraded MASM files.  They are upgrades of  
MASM 6.11, you will need to add these files to your MASM 6.11 directory.
These files are necessary for building VxDs for Windows 95.
Although there was no changelist, the official information available implied they added the bare-bones necessary features (and bugfixes) that allowed drivers written for Windows 95. What was said about MASM in the READVXD.TXT file from the Win95 DDK (see below) implied this version was a pre-release/hotfix (or a downright hack). Supporting that theory, this version could NOT be patched by any of the later 6.X patches that did patch the earlier 6.11 and 6.11a.

There does not seem to have ever been a 6.11b version mentioned or available to the public.

  • DISTRIBUTED AS UPGRADE: exclusively with the Windows 95 DDK and Windows NT 3.5 DDK
    AFFECTED FILES: ML.EXE, ML.ERR (to copy over previous versions in MASM 6.11 directory)
  • According to the Win95 DDK README.TXT, "These files are necessary for building VxDs for Windows 95."
  • V2CONV.TXT in the Win95 DDK said: "[MASM 6.11c] which fully supports COFF..." implying better COFF support
  • READVXD.TXT in the Win95 DDK said: "Copy the contents of the MASM611C directory into your MASM6x\BIN directory. These fixes will be included in the next release of MASM 6.X."
  • "The 6.11C patch (er, upgrade) slipped-out in 1994. It added Windows 95 VxD support, but it was still 6.11 underneath. MASM's tendency to add extra records to object files was corrected, which tamed object files to TASM and WASM sizes. Borland's TASM was noticeably faster with large files."

    REFERENCE: r_harvey

MASM 6.11d © 1981-1995 [Command Line]
ML.EXE388,096 bytes (379k)md5=cf70b409267a8f2085f00a4138b4628ddate=9/19/1995 1:18pm(Date from Patch File)
@Version reports: 611

This version was available as patch to be downloaded from Microsoft. It was also bundled directly with the Windows NT 3.51, Windows NT 4.0 and Windows 98 DDK's. The ML.EXE found on the Windows NT 3.51 DDK had a date of 5/25/1995 6:57pm, about 4 months earlier than the patch date.

This was the last version that ran under DOS (via DOSXNT) and Windows 3.x, however DOS and Windows 3.x targets could still be built with future versions (actually, you can use any version of MASM prior to 10, where DOS support was removed).

Quoting the README from the patch directory of an MSDN VC6 SP5/MASM 6.11 bundle CD released in 2001,

Due to changes in the MS-DOS extender used in earlier versions of MASM, MASM 6.14 does not run on Windows 3.1x or MS-DOS. Either Windows NT or Windows 95 is required to run MASM 6.14. If you are working in MS-DOS or Windows 3.1x, you need to continue using version 6.11d.

Note that you can use MASM 6.14 to develop applications that run under MS-DOS or Windows 3.1x.

According to Microsoft's MASM KB Article Q228454, "If you need to use MASM on an MS-DOS or Windows 3.1x machine, version 6.11d is the latest version capable of running under these operating systems."

Updated documentation files were the README.TXT and ERRMSG.TXT.

  • DISTRIBUTED AS PATCH (ML611D.EXE / 488k) for versions 6.11 or 6.11a
    OFFICIAL DOWNLOAD LOCATION: ftp://ftp.microsoft.com/softlib/mslfiles/
  • now supports structure packing on 8 byte boundaries as well as 16 byte boundaries using the /Zp8 or /Zp16 switches. Older versions of Masm only allowed up to /Zp4 structure packing.
  • FIXES:
    • The opcode generated for the FSETPM instruction has been corrected.
    • Errors when using the ALIAS directive and creating COFF object files have been fixed.
    • Errors when specifying an entry point with the END directive and creating COFF object files have been fixed.
    • Errors when using the ORG directive to back patch the code being generated in a COFF object file have been fixed.
    • The extra byte in the listing file for instructions using 32-bit addressing modes has been removed.
    • Unresolved externals that could occur when a symbol appeared more than once in EXTERNDEF directives have been fixed.
    • You can now step through code in include files when building COFF object files.
    • Various Access Violations when generating COFF object files have been fixed.
  • Latest Free DOS Linker:
    If you use this version or any future version up to MASM 9.0 to assemble 16-bit/DOS code, you can't use any of the 32-bit linkers released with Visual Studio. Your choices are to use the 16-bit linker that came with the last full distribution of MASM in version 6.11 (LINK.EXE 5.31.009 dated 7/13/1992) or the last 16-bit linker released by Microsoft with many fixes (ver=5.60.339 size=364544 date=12/5/1994 file_date=1/13/1995 md5=ed1ff59f1415af8d64daee5cdbd6c12b) which Microsoft provided as a free download: The self-extracting Lnk563.exe file provides the following 3 files: CVPACK.EXE, LINK.EXE and README.TXT.

    The original download URL was: http://download.microsoft.com/download/vc15/Update/1/WIN98/EN-US/Lnk563.exe
  • Latest Free DOS Debugger:
    If you want to debug 16-bit programs, you might also want the last release version of CodeView (version 4.10.1, dated 9/16/1994) to replace the one that came with MASM 6.11. CodeView 4.10 fixed some bugs debugging .COM files, stepping through code using 32-bit registers, etc. The self-extracting cv41patch.exe file provides 20 files to be copied into your MASM 6.11 BIN directory (or you may simply run the included CV.EXE standalone).

    The original download URL was: http://www.nuvisionmiami.com/books/asm/cv/cv41patch.exe

MASM 6.12 © 1981-1997 (build 6.12.7164) [Command Line]
ML.EXE366,080 bytes (358k)md5=fdc7bc15286109f773e6895c7a2f8e96date=8/27/1997 3:49pm(Date from Patch File)
@Version reports: 612

This version of MASM added MMX and Pentium Pro (i686) support and no longer ran under DOS or Windows 3.1. This was the first version of MASM to require Windows 95. The MMX line of Pentium processors and the Pentium Pro processors were released by Intel on 10/22/1996 and 11/1/1995 respectively.

Intel Pentium MMX Processor Intel Pentium Pro (i686) Processor

Running under Windows 95 or NT 3.1 was now required as this was the first version of MASM to run exclusively under Win32. As a direct consequence, Phar Lap's DOS extender no longer needed, thus ML.EXE shrank. The only changed documentation from prior versions was the README.TXT.

  • Personal computer using a 386 or higher processor running Windows 95, or Windows NT version 3.1 or later.
  • 4 MB of available memory.
  • Hard disk with 10 MB available space.
  • One 3.5" high-density (1.44 MB) disk drive (3.5" low-density (720K) or 5.25" high-density (1.2 MB) disks available separately with coupon enclosed).
  • To target Windows 3.1, you need one of the following:
    • Microsoft Windows Software Development Kit (SDK) 3.1.
    • Microsoft Visual C++ Development System, Standard or Professional Edition.
  • To target Windows NT, you need one of the following:
    • Microsoft Windows NT Software Development Kit (SDK).
    • Microsoft Visual C++ Development System, 32-Bit Edition.
  • DISTRIBUTED AS PATCH (ML612.EXE / 670k) for versions 6.11, 6.11a, or 6.11d.
    OFFICIAL DOWNLOAD LOCATION: ftp://ftp.microsoft.com/softlib/mslfiles/
  • New Pentium Pro Directives:
    • .686 - enables assembly of non-privileged instructions
    • .686P - enables privileged instructions in addition to the non-privileged instructions
  • MMX Support:
    The .MMX directive enables assembly of MMX instructions. Users can check to see that @Version is 612 or higher to tell if the version of MASM being used supports the .MMX directive and MMX instructions.
  • FIXES:
    • Various Access Violations when generating CodeView debug information (/Zi) have been fixed.
    • Errors when specifying an entry point with the END directive and creating COFF object files have been fixed.
    • Various structure packing inconsistencies when compared to the Microsoft C/C++ compilers have been corrected. MASM 6.12 should now pack structures the same as the Microsoft C/C++ compiler when using the same packing options.
  • IMPLIED FIXES? (Removed from Known Assembler Bugs present in README.TXT for version 6.11d):
    • Exiting from MS-DOS Critical Errors - MS-DOS critical errors, such as attempting to assemble a file on a drive which does not exist or is empty, produce the "Abort, Retry or Fail?" error message. Selecting "Abort" when running MASM in MS-DOS may cause memory to be corrupted. This problem does not occur when running MASM in Windows. To avoid this problem, select "Retry" or "Fail", as appropriate.
  • Intel added Streaming SIMD support to this version in the form of macros (which also supported MMX)

    REFERENCE: r_harvey

MASM 6.13 © 1981-1997 (build 6.13.7299) [Command Line]
ML.EXE351,744 bytes (344k)md5=2c6183857c6b692fa75d3967b875e4f9date=12/5/1997 1:43pm(Date from Patch File)
@Version reports: 613

The only official change in this version of MASM was the addition of the 3DNow! Technology support, a SIMD extension to the x86 instruction set released by AMD (Advanced Micro Devices) on 4/28/1998 (initially in the AMD K6-2 processor). However, there were some unofficial changes too.

AMD Logo AMD 3DNow! Logo

The only changed documentation from prior versions was the README.TXT.

  • DISTRIBUTED AS PATCH (ML613.EXE / 815k) for versions 6.11, 6.11a, or 6.11d.
    OFFICIAL DOWNLOAD LOCATION: ftp://ftp.microsoft.com/softlib/mslfiles/
  • AMD 3DNow! Technology Support:
    The .K3D directive enables assembly of K3D instructions. Users can check to see that @Version is 613 or higher to tell if the version of MASM being used supports the .K3D directive and K3D instructions.
  • WIN.INC Updated:
    The WIN.INC has changed for the first (and last) time since the initial version in 6.1. This version makes a change (fix) to line #2405 which is to prefix the SWORD symbol mm so it now reads _mm. I suspect they made this change to avoid name clashing with the new MMX register set MM0 thru MM7.
  • Addition of @comp.id symbol to resulting OBJ files:
    For consistency with new Visual C++ compiler features at the time, the @comp.id (compiler id) COFF symbol was added to MASM-created OBJ files starting with this version. This symbol embeds the MASM build number. The Microsoft linker then picks this value up to encode the undocumented "Rich" header in the final executable module.

MASM 6.14 © 1981-1997 (build 6.14.8444) [Command Line]
ML.EXE372,736 bytes (364k)md5=b54b173761ac671cea635672e214a8dedate=4/12/1999 3:05pm(Date from Patch File)
@Version reports: 614

This version of MASM no longer ran under Windows NT 3.1, but now required Windows NT 3.51, Windows 95, Windows 98 or Windows ME. This version additionally included SSE support (released by Intel on 2/26/1999) for the Pentium III and had one fix, as can be read in the README.TXT.

Pentium III (3) Processor / SSE

This was the officially supported version of MASM for Windows ME as it was bundled with both the XP (2600) and XP SP1 (2600.1106) DDK's; installed to the "bin\win_me\bin" directory.

  • Personal computer using a 386 or higher processor running Windows 95, Windows 98, or Windows NT version 3.51 or later.
  • 4 MB of available memory.
  • Hard disk with 10 MB available space.
  • One 3.5" high-density (1.44 MB) disk drive (3.5" low-density (720K) or 5.25" high-density (1.2 MB) disks available separately with coupon enclosed).
  • To target Windows 3.1, you need one of the following:
    • Microsoft Windows Software Development Kit (SDK) 3.1.
    • Microsoft Visual C++ Development System, Standard or Professional Edition.
  • To target Windows NT, you need one of the following:
    • Microsoft Windows NT Software Development Kit (SDK).
    • Microsoft Visual C++ Development System, 32-Bit Edition.
  • DISTRIBUTED AS PATCH (Ml614.exe / 858k) for versions 6.11, 6.11a, or 6.11d. (see MASM KB Article Q228454)
    OFFICIAL DOWNLOAD LOCATION: ftp://ftp.microsoft.com/softlib/mslfiles/
  • Support for Streaming SIMD Extension instructions (SSE):
    • Built-in support for Streaming SIMD (Single Instruction, Multiple Data) formerly known as KNI (Katmai New Instructions), available on the Pentium III and later processors
    • The new .XMM directive enables assembly of SSE instructions. Users can check to see that @Version is 614 or higher to tell if the version of MASM being used supports the .XMM directive and SSE instructions.
  • FIXES:
    • Incorrect A2039 errors indicating 'line too long' have been fixed.
  • The OWORD (Octal Word) keyword was introduced replacing MMWORD used in Intel's macros; "This 16-byte data type is required for SIMD instructions, and should be useful for ad hoc structures."

    REFERENCE: r_harvey
  • Trial and error shows partial SSE2 support, however MASM provides no access to the XMM registers

MASM 6.15 © 1981-2000 / bundled w/ Visual C++ 6.0 Processor Packs 4, 5 (build 6.15.8803) [Command Line / Help]
ml.exe385,072 bytes (376k)md5=3d52f47ad3a190294323eb80449c9ff6date=3/16/2000 3:20pm
@Version reports: 615

This version was bundled with the Visual C++ SP4 and SP5 Processor Packs for Visual C++ 6.0 (an add-on to Visual C++). Microsoft no longer considered MASM a separate product. Oddly enough, SP6, the last service pack for Visual C++ 6.0, actually removes the SP5 the Processor Pack, so you had to hang on to SP5 to keep MASM. Future versions of MASM would ship directly with the Visual C++ compiler and tools VIA Visual Studio. Microsoft had this to say for Visual C++ 6.0 SP6:

In addition, the Visual C++ Processor Pack (VCPP) was removed from Service Pack 6. If you have the VCPP installed, installing SP6 will remove it from your machine. If you wish to continue using the VCPP, you will need to stay with SP5 or migrate to Visual Studio 2002 or 2003 (recommended).

Processor Pack 5 can be downloaded here: vcpp5.exe
Other documentation files installed by Processor Pack 5: PPreadme.htm (Dec 7, 2000) procpack.chm (Aug 22, 2000) MasmRef.Doc (Aug 9, 2000)
Instructions on how to extract MASM from Processor Pack 5 can be found at The Starman's Realm.
NOTE: I think it is a bug that the word "Beta" is present in the <title> element of the PPReadme.htm file (see link above). Microsoft removed "Beta" from the title at the top of the page, but they missed the title that displays in the browser's title bar.

This was the only version of MASM to date with no official changelist but there WERE changes. The Visual C++ 6.0 Processor Pack documentation listed the C/C++ Compiler changes but no official word on the MASM changes. The Processor Pack did contain the handy MasmRef.Doc (see above) you could open in WordPad (write.exe), but no section explaining the fixes, new features or other changes between versions 6.14 and 6.15.

The word on the street was that this version added support for the SSE2 instruction set, released by Intel on 1/3/2001. In practice, SSE2 instructions seemed to assemble on 6.14 (you didn't get errors) however you could not use the XMM registers (for SSE) until 6.15. So it is generally recommended to use a minimum of 6.15 to assemble SSE or SSE2 instructions. Diffing the command line output shows that /omf was added. Was that it? Its hard to know for sure.

Oh, yes; the MASM executable is now a lowercase filename (ml.exe) and will likely be into the foreseeable future. The all UPPERCASE filenames of the DOS-days appear to be over :).

  • Added command line option: /omf "generate OMF format object file" as the COFF object file format became the new default for the 32-bit world
  • MASM now allows the use of the XMM registers (for SSE)
  • The new .XMM directive enables SSE2 instruction set support (complete?)

  • REFERENCES: OSDEV MASM, German Wikipedia: MASM, OpenSSL bug list, MASM32 Blog

MASM 7.0 / bundled w/ Visual C++ .NET 2002 7.0 (any*) & XP 5.1.2600 DDK
ml.exe413,696 bytes (404k)md5=b2165bcdd8754d2827ba850f4fbfb93fdate=1/5/2002 3:36ambuild 7.00.9466 / VS.NET 2002 7.0 (any*)[Command Line]
ml.exe413,696 bytes (404k)md5=78aac4b5784393fbb4a4b51d1a02d231date=7/21/2001 7:31pmbuild 7.00.9210 / XP 5.1.2600 DDK[Command Line]
@Version reports: 615

*The version of MASM shipped with Visual C++ .NET 2002 7.0 does not change after SP1 is applied.

This version shipped with the new Visual C++ .NET 2002 7.0 and the Windows XP 5.1.2600 DDK (located at WINDDK\2600\bin\x86\ml.exe). Another release of the XP DDK (5.1.2600.1106) bundled an identical ml.exe as the first DDK but was dated 3/25/2002 7:22pm. Besides cosmetic differences, it appears there were no significant changes. @Version still reports the previous version of MASM.

  • Copyright Year(s) on Command Line:
    Starting with version 7 and into the future, Microsoft stopped displaying the copyright years that used to display on the command line.
  • ML.ERR Dependency Removed:
    The ML.ERR companion file required for MASM to run was present in almost the entire 6.x line (except version 6.1a), but starting with version 7 and into the future, the error message display strings ml.exe read from this file were moved into ml.exe itself. Additionally, the newly embedded error message strings are now UNICODE for localization purposes.

    NOTE: the ml.exe version released with the XP 5.1.2600 DDK did come with an ml.err file that was identical to the ml.err released with version 6.15 (different date though). This was a bug as it was confirmed the ml.exe assembles without it. Version 6.15 will NOT even attempt assemble without this file present.
  • MASM retrofitted with a version resource block:
    Although MASM has been 32-bit for 4 years, its never had a version resource block until now (view it by clicking the build-version link above). There is one exception: MASM386 had a version resource block, but it would be considered non-standard and obsolete compared to the rest of Microsoft's Win32 binaries. All future versions of MASM will contain a version resource block as well.
  • Buffer and stack overflow checking, warnings

  • REFERENCE: r_harvey

MASM 7.1 / bundled w/ Visual C++ .NET 2003 7.1 [Command Line Help]
ml.exe413,696 bytes (404k)md5=cae874c25467b4566a56b8c9cdc00446date=7/11/2006 6:15pmbuild 7.10.6030 / VS.NET 2003 PRO 7.1[Command Line]
ml.exe413,696 bytes (404k)md5=63ab5c7120e7b3582eaac18cf0bdcf0fdate=3/24/2005 4:25pmbuild 7.10.4035 / WS03 SP1 DDK[Command Line]
@Version reports: 710

In addition to being primarily released with Visual Studio .NET 2003 7.1, this version of MASM was also bundled with the Windows Server 2003 SP1 DDK 3790.18030 located in "WINDDK\3790.1830\bin\x86".

  • SAFESEH Support:
    The .SAFESEH directive and /safeseh option were added.
    .SAFESEH identifier
    Registers a function as a structured exception handler. identifier must be the ID for a locally defined PROC or EXTRN PROC. A LABEL is not allowed. The .SAFESEH directive requires the /safeseh ml.exe command-line option. The command-line option is described on the command line as:
    Marks the object as either containing no exception handlers or containing exception handlers that are all declared with .SAFESEH.

    Page 345 of the book Practical Malware Analysis sheds some light on SafeSEH:

    The ExceptionHandler function will be called first whenever an exception occurs. This action will be subject to the constraints imposed by Microsoft's Software Data Execution Prevention (Software DEP, also known as SafeSEH). Software DEP is a security feature that prevents the addition of third-party exception handlers at runtime. For purposes of handwritten assembly code, there are several ways to work around this technology, such as using an assembler that has support for SafeSEH directives. Using Microsoft's C compilers, an author can add /SAFESEH:NO to the linker command line to disable this.

  • Unlike MASM 7.0, @Version correctly reports a version matching the build number; in this case, 710

MASM 8.0 / bundled w/ Visual C++ 2005 8.0 [Command Line Help]
ml.exe350,208 bytes (342k)md5=4bd78317f0f9e4897d3569dbbc8fad39date=4/21/2006 6:11pmbuild 8.00.50727.104 / VS 2005 8.0 Express[Command Line]
ml.exe344,576 bytes (336k)md5=735e3ee3de15a3d96dce84b5242cef33date=9/5/2004 12:15ambuild 8.0.40904.0 / VS 2005 8.0 BETA REFRESH / Win32[Command Line]
ml64.exe557,056 bytes (544k)md5=ee2bb5d50d50152bcbf588a8c7441474date=9/5/2004 2:06ambuild 8.00.40904 / VS 2005 8.0 BETA REFRESH / Win64[Command Line]
ml64.exe369,664 bytes (361k)md5=82b8948213657dc7e221ed472772e4a9date=9/5/2004 1:46ambuild 8.00.40904 / VS 2005 8.0 BETA REFRESH / Win64 PE32[Command Line]
@Version reports: 800

Visual Studio 2005 offered something that had never been available before: the Express Edition. This edition contained a fully functional although limited integrated development environment with compilers and tools for educational/trial purposes, available for download, completely free (with licensing restrictions of course). These tools included the Win32 version of MASM 8, although it had to be downloaded separately (MASMsetup.EXE released June 7th, 2006) from Microsoft's website exclusively for the Express Edition. This version was the first version of MASM that was offered by Microsoft completely for free.

The Express Edition also marked the first time Microsoft's C# compiler was offered for free. The C/C++ compiler was first offered for free in the stand-alone download bundle: “Visual C++ Toolkit 2003” (VCToolkitSetup.exe) in the previous release of Visual C++ (i.e. 7.1). This included only a C/C++ compiler, linker and some libs/includes, but nothing else. That Toolkit was superseded by the Express and Community Editions that would follow, providing access to a full blown IDE and tools.

This version also marked the debut public release of the Win64 MASM (ml64.exe) for the amd64 architecture (a.k.a. x64, x86-64, EM64T, Intel 64), although only the Win32 version would be offered for free in the MASMsetup.EXE package. As an alternative, the feature-complete BETA 64-bit tools (including the 64-bit assemblers and compilers) are still freely available from Microsoft's Visual Studio 2005 BETA REFRESH package. As with MASMsetup.EXE, you can extract the files contained within these setup files (as well as the nested setup files) using a typical archive extractor program such as WinRAR and 7Zip. With the advent of the new 64-bit MASM, Microsoft includes both 64 and 32 bit variations (PE32+, and PE32 respectively) allowing 64-bit assembly to be performed on 32-bit or 64-bit versions of Microsoft Windows. Note that Microsoft also began releasing an additional 64-bit MASM along with compilers and other tools targetting the Intel Itanium architecture (IA-64) which is primarily used for enterprise hardware. The Intel Itanium architecture is not currently covered on this page, so whenever the MASM 64-Bit assembler is referenced, the amd64 architecture version should be assumed.

As a side-note, the versions of MASM offered in the free editions (Express/Community) are identical to the versions present in the retail editions. The only difference are the licensing restrictions and file timestamps.

This was the first version of 32-bit MASM to have a dependency on anything other than kernel32.dll (with exception of NTDLL.DLL in versions 6.1 and 6.1a about 13 years prior)! MASM was now dependent on the Visual C runtime library MSVCR80.DLL and ADVAPI32.DLL. In credit to Microsoft, they did trim the executable size from 404k in version 7 to 342k in version 8 freeing up 62k. The executable actually became smaller than every version of MASM released after 6.00B (14 years prior) which was 244k! Until version 8, Microsoft must have been statically linking to the C runtime library and possibly others. Problem now is, MSVCR80.DLL is 621k, so you have to haul this thing around with MASM 8 unless you also want to have the whole Visual Studio 2005 8.0 installed. This isn't considered to be a problem by most because not only is disk space cheap nowadays, but if you want to link your object code, you are going to need the linker (link.exe). And, the linker has been dependent on various runtime DLLs since version 6.15 so we might as well get used to the bloat. :)

  • MASM expressions are now 64-bit values. In previous versions MASM expressions were 32-bit values.
  • The instruction __asm int 3 now causes a function to be compiled to native. For more information, see __asm.
  • the following are now documented: ALIAS (MASM) and .FPO
  • operators added: IMAGEREL, HIGH32, LOW32, and SECTIONREL
  • added .686 (Intel and AMD variant) call-gate instructions:
    • SYSEXIT (requires .686P)
    • SYSRET (requires .686P)
  • directives added:
    • MMWORD (64-bit data type for MMX)
    • XMMWORD (128-bit data type for SSE)
    • SQWORD (signed QWORD / 8 signed-bytes / version undocumented)
  • The SEGMENT directive now supports additional attributes.
  • Changes to Command Line Options:
    • /omf now implies /c
    • ml.exe does not support linking OMF format objects
    • /errorReport "Report internal assembler errors to Microsoft" option added to ml.exe and ml64.exe
    • /Sc "Generate timings in listing" no longer supported. Microsoft either must no longer think people are or should be concerned with the clock-ticks of each instruction, or it may be too difficult to maintain the timings of each instruction on the various different types of processors. It may also not be possible to get exact timings with the newer processors.
    The official documentation between 7.1 and 8.0 no longer list this option:
    • /Sg (asm code in listing) (the option still works, but appears to be synonymous with /Sa)
    This docs also say:
    • /w now implies /W0 and /WX instead of just /W0
    This option has been added to the docs (although was present in 7.1 command line):
    • /X (ignore INCLUDE environment variable)
  • H2INC.exe will not ship in Visual C++ 2005. If you still need it, use from a previous version.
  • Introduction of the 64-bit Assembler (ml64.exe):
    ml64 is a version of MASM for the x64 architecture. It assembles x64 .asm files into x64 object files. Inline assembly language is not supported in the x64 compiler. Additionally, the following command line arguments available for the 16/32 bit version are not available for ml64:

    • /AT (tiny model)
    • /coff (common object file format)
    • /omf (object module file format)
    • /Cu (uppercase identifiers)
    • /FPi (floating-point emulator fixups)
    • /Gc (FORTRAN or Pascal calling convention)
    • /Gd (C-style calling convention)
    • /GZ (stdcall calling convention)
    • /H (external name significant characters)
    • /safeseh (no exception handlers or all handlers .SAFESEH.)
    • /Zm (M510 compatibility)

    The following MASM directives have been added for ml64 (x64):
    • .PUSHREG
    • .SAVEREG
    • .SAVEXMM128
    • PROC (updated with x64-only syntax)
  • Support for the SSE3 (Streaming SIMD Extensions 3) Instruction Set released by Intel on 2/1/2004:

    REFERENCE: Intel article: Streaming Simd Extensions 3 / VS.NET 2003
    REFERENCE: pcdosretro

  • Fast compile times, stricter type checking, separate 32-bit and 64-bit assemblers, the 64-bit lacking many of the features:

    "One of the great things about MASM 8.0 (other than faster compile times) is the stricter type checking."
    "Probably the most disappointing part of MASM 8 is that Microsoft decided to split the assembler: one for 32-bit and one for 64-bit. And the 64-bit version is missing a lot of the polish of its older brother. It doesn't support many of the higher level constructs or calling conventions. So no .IF, .WHILE or automatic declaration of function parameters. Minor nits include no support for C++ function name decoration and no support for register-based calling conventions (such as __fastcall). These just make it trickier when you have to integrate 32-bit and 64-bit assembly code with C & C++."

    REFERENCE: Phoenix Technologies 2006 Blogs
  • Various opinions are that MASM 8 broke code that used to work with previous versions:

    "I tried ML.exe & Link.exe from latest VisualStudio 2005, but it sucks Linker 8.0 do not support some command line switches, assembler fails sometimes with good (assembled ok by all prev. version) code"
    "I agree ML.EXE 8.00 from Visual Studio 2005 is not so good."

    REFERENCE: Winasm Forums

  • BUGS FIXED in v8: REFERENCE: JWasm Manual
    • "TYPE xmm0" will return 10 in Masm v6 and v7 - the correct value is 16.
    • for Masm v6 and v7, if an array > 64 kB is defined and output format OMF is selected, the array's size will be mod 0x10000 only.
    • silent truncation of immediate constants: Masm v6 and v7 will accept line "mov [word_variable],12345h" without error.
    • If a section contains more than 0xffff relocations in COFF, the number of relocations that is stored in the object module is just the value of the lower 16-bit half of the relocation count.

MASM 9.0 / bundled w/ Visual C++ 2008 9.0 [Command Line Help]
ml.exe361,968 bytes (353k)md5=16ca0bd9537b96e91efdd234007999cbdate=7/30/2008 12:05pmbuild 9.00.30729.01 / VS 2008 9.0 (any*) / Win32[Command Line]
ml64.exe387,064 bytes (378k)md5=009923b2441a8bb3e6686db8aa15e5f6date=7/30/2008 1:58pmbuild 9.00.30729.01 / VS 2008 9.0 (any*) / Win64[Command Line]
ml64.exe308,216 bytes (301k)md5=aa9d358c6f5f20772aaaff4455326dd7date=7/30/2008 2:11pmbuild 9.00.30729.01 / VS 2008 9.0 (any*) / Win64 PE32[Command Line]
ml.exe352,768 bytes (344k)md5=2a2b8d75e359e6311de1195e65dbf252date=2/8/2010 7:18pmbuild 9.00.30729.207 / WDK 7.1 7600.16385.1 / Win32[Command Line]
ml64.exe299,008 bytes (292k)md5=69fa9f19d8a7ac3ea85f867415016a02date=2/8/2010 7:18pmbuild 9.00.30729.207 / WDK 7.1 7600.16385.1 / Win64 PE32[Command Line]
@Version reports: 900

*The version of MASM shipped with the Express Edition is identical to that in the retail editions; the Express Edition required Service Pack 1 to obtain MASM. It was also distributed with the Windows Driver Kit (WDK) 7.1.0.

This was the last full-featured version of MASM to support legacy 16-bit DOS code and processors in the 80x86 family prior to the 386. MASM 10 has removed this support. This was the first version of MASM to require Windows 2000 as opposed to Windows 95 which has been required by all prior versions since 6.12.

The changelist below is based on MSDN information found from VS2008 Compiler Intrinsics. The C/C++ compiler documented support for the new intrinsics reflected in MASM's newly supported instruction sets, but not a word on MASM's changes.

  • New Instruction Set Support:

    • SSSE3 (Supplemental Streaming SIMD Extensions 3) released by Intel on 6/26/2006
    • SSE4.1, SSE4.2, SSE4A (Streaming SIMD Extensions 4, a.k.a. “HD Boost”) released by Intel on 9/27/2006
    • AES (Advanced Encryption Standard New Instructions or AES-NI) proposed by Intel in March of 2008
  • JWasm Manual: Bugs FIXED in v9:

    • the infamous "invoke" bug: if an argument for invoke has to be expanded (from BYTE or WORD to DWORD, for example ), bad code was generated.
    • REFERENCE: JWasm Manual
  • Outstanding Bugs:

    • Wildcard support (*.asm) broken since 8.0

      REFERENCE: MASM Forums
    • You can pass more arguments to a macro than needed:
          include \masm32\include\masm32rt.inc
          MBox MACRO text:REQ, title:REQ, style:REQ ; 3 arguments received
            invoke MessageBox, 0, text, title, style
          MyTitle db "Ciao", 0
          MBox 0, chr$("Message text, not title!"), addr MyTitle, MB_OK ; 4 arguments passed
          end start
      REFERENCE: MASM Forums
    • Assembly gets slow, and ML may eventually freeze, for large buffers in the .data? section:
          MySlowBuffer db 600000 dup(?) ; 0.6 mega: about 5 seconds
      The workaround is a macro using the ORG directive (I owe this idea to drizz and MichaelW):
          include \masm32\include\masm32rt.inc
          mkbuf MACRO var, BufLen
          LOCAL lbl
          align 4
            lbl LABEL byte
            ORG $+BufLen-1
            db ?
          var dd lbl ;; define it in the data section
          ; MySlowBuffer db 600000 dup(?) ; 0.6 mega: about 5 seconds
          start: mkbuf MyBuffer, 100000000 ; one-hundred mega
          invoke MessageBox, 0, chr$("Done!"), chr$("Fat buffer:"), MB_OK
          end start
      REFERENCE: MASM Forums
    • The offset problem: Both versions of this code work for ml 6.14 and JWasm but ml 9.0 says "error A2070:invalid instruction operands"
          MyAccels ACCEL <FCONTROL or FVIRTKEY, VK_S, IdMenuSave>
          LastAccel ACCEL <FVIRTKEY, VK_ESCAPE, IdEscape>
          invoke CreateAcceleratorTable, addr MyAccels,
          1+(offset LastAccel-MyAccels)/SIZEOF ACCEL
          invoke CreateAcceleratorTable, addr MyAccels,
          1+(dword ptr LastAccel-dword ptr MyAccels)/(SIZEOF ACCEL)
      No workaround found yet, except sacrificing a register...

      REFERENCE: MASM Forums
  • JWasm Manual: Bugs STILL PRESENT as of v9 (possibly fixed in future versions):

    Many of these bugs are old enough that they have likely become “features”, courtesy of Microsoft. It is not know which exact version of MASM introduced each bug, but many were present from MASM's “gold standard” versions 6.14 and 6.15, likely contributing to the reasons not to fix them. Although possible some or all might never be fixed, it is possible some may have been fixed in v10 and/or greater. The bug list below was copied from JWAsm's documentation (the closest clone to MASM available, and free), but JWAsm has fixed them all as of v2.11a (Released Nov 16th, 2013)!

    • PROTOs contained twice in the source caused an EXTDEF entry to be generated in the object module.
    • a nested structure might cause a GPF in Masm if the embedded STRUCT's starting offset has to be adjusted due to alignment.
    • defining huge arrays in Masm is very slow and might even cause a deadlock if COFF has been selected as output format.
    • Masm doesn't flag invalid numbers in struct/array initializer strings.
    • if an ALIAS is defined somewhere in the source and the symbol table is listed, a 'General Failure' error occurs in Masm if output format is OMF.
    • Type "coerces" for DWORD data items defined in a 32bit segment are ignored by Masm, i.e., "dd far16 ptr <symbol>" will generate a near32 fixup instead of a far16 one.
    • if the ALIGN directive has to add 5 bytes in 32bit code segments, Masm includes an "add eax,0" opcode, which isn't a no-op because flags are modified.
    • preprocessed output with option -EP may erroneously contain text macros and macro function calls if the macros are located in the initialization string of a structured variable.
    • Masm generates wrong code if a conditional jump is coupled with a type coercion which modifies offset magnitude. Examples: "jz near32 ptr ..." in 16bit code or "jz near16 ptr ..." in 32bit code).
    • if the arguments given to Masm end with an option which expects a parameter (i.e. "ml -c -Fo"), a 'General Failure' may occur.
    • floating-point data items in Masm can be followed by any suffix (example: REAL4 1.0foo, 2.0bar). JWasm won't accept this.
    • If a local is defined inside a macro, Masm will create a unique name for it. The name is constructed by using '??' as prefix, followed by a hexadecimal number with 4 digits. There is no check for overflow, however, so if the total of locals in all macros exceeds 65536, strange errors will occur.
    • If a weak external is defined for -coff with the ALIAS directive, an invalid fixup - and also a strange entry in the module's symbol table - is created.
    • If a symbolic constant (=equate) is made public in OMF format, Masm will store the symbol's value in a 16-bit record if it is in the range -32768 ... 65535. If the symbol is referenced in another module as a 32-bit number, it is always zero-extended, never sign-extended; hence values -1 ... -32768 will become 65535 ... 32768.
    • if data labels become public by the -Zf option ( and not by the PUBLIC directive ), their names are not decorated. Also, if format is COFF, they won't become true publics, they're just included in the symbol table with class "static".

    REFERENCE: JWasm Manual

MASM 10.0 / bundled w/ Visual C++ 2010 10.0 from VS 2010 10.0 (any*) [Command Line Help]
ml.exe397,120 bytes (388k)md5=c60f9e0657e639019388c6c3f223aa98date=3/19/2010 2:02pmbuild 10.00.30319.01 / Win32[Command Line]
ml64.exe452,424 bytes (442k)md5=3c024c12974359fab262afe9789a7b5ddate=3/19/2010 2:02pmbuild 10.00.30319.01 / Win64 / Retail Only[Command Line]
ml64.exe349,000 bytes (341k)md5=660f05d6f2c7016b2cf72964a16ed0e4date=3/19/2010 2:02pmbuild 10.00.30319.01 / Win64 PE32[Command Line]
ml.exe411,456 bytes (402k)md5=2d0869f6bb8725501c4d476606044f19date=2/21/2011 6:03pmbuild 10.00.40219.01 SP1 / Win32[Command Line]
ml64.exe474,952 bytes (464k)md5=f1f1958ac367e5c31c9d25588c95af44date=2/21/2011 7:53pmbuild 10.00.40219.01 SP1 / Win64 / Retail Only[Command Line]
ml64.exe363,336 bytes (355k)md5=39f9d0d63e99d255e745faf4050ca83cdate=2/21/2011 7:53pmbuild 10.00.40219.01 SP1 / Win64 PE32[Command Line]
@Version reports: 1000

Visual Studio 10.0 Express released 32-bit executable versions (PE32) of both ml.exe and ml64.exe assemblers, the same that were released in the retail editions except with different timestamps. The Express Edition did not release the 64-bit ml64.exe. There were slight differences in the binary executable between the initial release version and SP1. These differences are most likely the build number changes in the version resource block, but no functionality changes.

Version 10.0, appearing 29 years after its initial version in 1981, has made one of the most significant changes in MASM history. All support for 16-bit/DOS assembly and any processor support prior to the 386's 32-bit modes is now gone. This was also the first version of MASM to require a minimum of Windows XP.

  • Support for the AVX Instruction Set (Advanced Vector Extensions) (proposed by Intel in March of 2008)
  • The addition of the YMMWORD data type supports the 256-bit multimedia operands that are included in the Intel Advanced Vector Extensions (AVX) instructions.
  • Several directives were removed from the Microsoft Macro Assembler Reference compiler. The removed directives are .186, .286, .286P, .287, .8086, .8087, and .NO87.
  • ML.exe has removed the following command line options (although Microsoft did not update their help):
    • /AT "Enable tiny model (.COM file)"
    • /FPi "Generate 80x87 emulator encoding"
    • /H "Set max external name length"

MASM 11.0 / bundled w/ Visual Studio Express 11.0 (2012)
ml.exe434,608 bytes (424k)md5=1e94f1e7fdea87a5e0cc22463f298c14date=7/26/2012 7:08pmbuild 11.00.50727.1 / Win32[Command Line]
ml64.exe388,536 bytes (379k)md5=a333d57ee9d988c11584fca2114f28d1date=7/26/2012 7:08pmbuild 11.00.50727.1 / Win64 PE32[Command Line]
@Version reports: 1100

This was the first version of MASM (and all of the Visual Studio toolset) to require a minimum OS of Windows Vista. This change was made to the PE header.

Aside from that, no official changelist was released and a diff of the MSDN documentation also revealed no changes.

MASM 12.0 / bundled w/ Visual Studio 12.0 (2013)
ml.exe438,920 bytes (429k)md5=248f463dc5dbb770bc695c7fdc647d24date=10/5/2013 2:38ambuild 12.00.21005.1 / From VS 2013 Express for Desktop / Win32[Command Line]
ml64.exe393,360 bytes (384k)md5=0fc4a6cc54cc41e62ddc20a58580d61cdate=10/5/2013 2:38ambuild 12.00.21005.1 / From VS 2013 Express for Desktop / Win64 PE32[Command Line]
ml.exe439,416 bytes (429k)md5=ab9bb772f3e2c40dea3942ee3b960eb3date=11/1/2014 12:46ambuild 12.00.31101.0 / From VS 2013 Community UPDATE 4 / Win32[Command Line]
ml64.exe517,744 bytes (506k)md5=6dff37bc4dbc74121fd6b01d9c987e2adate=10/31/2014 8:44pmbuild 12.00.31101.0 / From VS 2013 Community UPDATE 4 / Win64[Command Line]
ml64.exe393,344 bytes (384k)md5=918bf14035f6a5859941f7e8f81f1d19date=11/1/2014 12:46ambuild 12.00.31101.0 / From VS 2013 Community UPDATE 4 / Win64 PE32[Command Line]
@Version reports: 1200

The Visual Studio 12.0 (2013) toolset (including this version of MASM) was marked with the debut release of the Community Edition: a free version of Visual Studio for individuals, academia, open source projects and small businesses that is functionally equivalent to the professional edition minus CodeLens and Team Foundation Server features. Microsoft oddly continued to release the free and crippled Express Edition. Both the Community and Express editions of Visual Studio included MASM.

Unfortunately, no official changelist was released and a diff of the MSDN documentation also revealed no changes.

MASM 14.0 / bundled w/ Visual Studio 14.0 (2015)
ml.exe446,600 bytes (436k)md5=977a2329c414f9f83d08a2806a370857date=6/25/2015 11:34pmbuild 14.00.23026.0 / From VS 2015 Community 14.0.23107.0 D14REL / Win32[Command Line]
ml64.exe525,968 bytes (514k)md5=43149845421ecf4e7c4636c512ec1c8adate=6/25/2015 11:15pmbuild 14.00.23026.0 / From VS 2015 Community 14.0.23107.0 D14REL / Win64[Command Line]
ml64.exe401,040 bytes (392k)md5=0d7c443b13fa36f7aa7b6cdf58967e96date=6/25/2015 11:34pmbuild 14.00.23026.0 / From VS 2015 Community 14.0.23107.0 D14REL / Win64 PE32[Command Line]
@Version reports: 1400

This should have been MASM 13.0, but the entire Visual Studio toolset skipped the "unlucky" number in favor of 14.0. If Microsoft got flack from the superstitious for shipping Visual Studio 2013 two years prior, they certainly didn't make the same mistake twice!

The Visual Studio 14.0 (2015) C Runtime dependency DLL was restructured in this version, affecting most of the tools including MASM. What would have been MSVCR140.DLL is now broken into VCRUNTIME140.DLL and various "api-ms-win-crt-CCC-VVV" DLLs, where CCC is the category and VVV is the version. Note that the MSVCP (C++) DLL dependency was kept (MSVCP140.DLL).

As with the prior two major versions of MASM, no official changelist was released for this version and a diff of the MSDN documentation revealed no changes.