MBASIC
MBASIC
Main page

MBASIC

logo
Community Hub0 subscribers
Read side by side
from Wikipedia
MBASIC
Paradigmimperative
Designed byMicrosoft
DeveloperMicrosoft
OSCP/M
Websitewww.microsoft.com
Influenced by
BASIC

MBASIC is the Microsoft BASIC implementation of BASIC for the CP/M operating system. MBASIC is a descendant of the original Altair BASIC interpreters that were among Microsoft's first products. MBASIC was one of the two versions of BASIC bundled with the Osborne 1 computer. The name "MBASIC" is derived from the disk file name MBASIC.COM of the BASIC interpreter. MBASIC, like its predecessor family of 8-bit interpreters Microsoft BASIC, were heavily inspired by Digital Equipment Corporation PDP-10's BASIC-PLUS.

Environment

[edit]
MBasic 5.21 running on a Z80 CP/M system displayed on a monochrome monitor typical for that time

MBASIC version 5 required a CP/M system with at least 28 KB of random-access memory (RAM) and at least one diskette drive.

Unlike versions of Microsoft BASIC-80 that were customized by home computer manufacturers to use the particular hardware features of the computer, MBASIC relied only on the CP/M operating system calls for all input and output. Only the CP/M console (screen and keyboard), line printer, and disk devices were available.

MBASIC in the uncustomized form had no functions for graphics, color, joysticks, mice, serial communications, networking, sound, or even a real-time clock function. MBASIC did not fully support the features of the host CP/M operating system, for example, it did not support CP/M's user areas for organizing files on a diskette. Since CP/M systems were typically single-user and stand alone, there was no provision for file or record locking, or any form of multitasking. Apart from these limitations, MBASIC was considered at the time to be a powerful and useful implementation of BASIC.

Features

[edit]

Language system

[edit]

MBASIC is an interpreter. Program source text was stored in memory in tokenized form, with BASIC keywords replaced by one-byte tokens which saved memory space and speeded execution. Any line prefixed with a line number was stored as program text; BASIC statements not prefixed with a line number were executed immediately as commands. Programs could be listed on the screen for editing, or saved to disk in either a compressed binary format or as plain ASCII text. Every source line was identified with a number, which could be used as the target of a GOTO or GOSUB transfer. Only line editing commands were provided.[1] It was often beneficial to save a program as plain text and edit it with a full featured editor.

Program text, variables, disk buffers and the CP/M operating system itself all had to share the 64 kilobyte address space of the 8080 processor. Typically when first starting MBASIC there would be less than 32 kB memory available for programs and data, even on a machine equipped with a full 64 kilobytes of RAM. Comment lines, prefixed with the REM keyword or an apostrophe, could be placed in the program text but took up valuable memory space, which discouraged BASIC users from fully documenting their code. To allow larger and more complex programs to be run, later versions of MBASIC supported functions that allowed portions of program text to be read in and executed under program control (the " CHAIN " and MERGE statements). No support for "shell" command execution was provided, though this functionality could be duplicated by a determined programmer.

A particular advantage of MBASIC was the full-text error messages provided for syntax and run-time errors. MBASIC also had a "trace" function that displayed line numbers as they were executed. While this occupied the same screen space as normal program output, it was useful for detecting conditions such as endless loops.

Files and input/output

[edit]

Data could be read and stored to disk as either sequential files (delimited by the CP/M convention of CR/LF at the end of each line) or else as fixed-record-length random access files, which, given a sufficiently determined programmer, could be used to perform database-type record manipulation. The Microsoft Binary Format for floating point numbers was proprietary to the implementation, which meant that data could only be interchanged with other programs using ASCII text representation or else with extensive programming to convert the binary format.

Variables and data types

[edit]

MBASIC supported the following data types:

  • 8-bit character data, in strings of length 0 to 255 characters;
  • 16-bit integers;
  • 32-bit floating point (single precision), equivalent to six decimal digits, with a two-digit exponent;
  • 64-bit floating point (double precision), equivalent to sixteen decimal digits, with a two-digit exponent.

String operators included substring selection, concatenation, assignment, and testing for equality.

Arrays of the above types were allowed with up to 7 dimensions, but no functions or operators worked on arrays; for example, there was no assignment of arrays. Unlike some other BASIC implementations of the time, MBASIC did not provide support for matrix operations, complex numbers, or a decimal (BCD) data type for financial calculations. All floating point operations were carried out in software since typical CP/M systems did not have floating point hardware. The built-in mathematics functions (sine, cosine, tangent, natural log, exponential, square root) only gave single precision results. A software pseudorandom number generator was provided; this relied on the user to key in a seed number to obtain a sequence of numbers useful for games and some simulations. MBASIC permitted but did not require the LET keyword for assignment statements.

Early versions of BASIC on microcomputers were infamous for one- or two-character variable names, which made the meanings of variables difficult to recall in complex programs. MBASIC version 5 allowed identifiers up to 40 characters long, which permitted programmers to give variables readable names.

Program flow control

[edit]

Program flow control in MBASIC was controlled by IF...THEN...ELSE... conditional tests, WHILE...WEND loops, and GOTO and GOSUB instructions. No CASE statement was available, although an ON...GOTO... (computed GOTO) provided multi-way branches. Subroutines had no parameters and all variables were global. MBASIC did not make structured programming mandatory for programmers and it was easy to write spaghetti code.

PEEKs, POKEs, and user functions

[edit]

As with other 8-bit computers of the late 1970s and early 1980s, PEEK and POKE functions were used for directly reading and writing to memory. Since these systems typically had no memory protection, this allowed a programmer to access portions of the operating system, or functions that would not otherwise be available. This also provided opportunities for user programs to hang the system, usually by accident. For example, a CP/M programmer might use a POKE function to allow BASIC to switch the console device to the serial port, if the system BIOS supported this. For machines with real-time clocks, a set of PEEK instructions might have been used to access the time.

For more complex operations, MBASIC allowed user-defined functions that could be called from a BASIC program. These were typically placed in a reserved area of memory, or POKEd into string constants, as a series of machine codes (opcodes). MBASIC also provided hardware INP and OUT instructions that read and wrote directly to the 8080 hardware input/output ports. This could be used to control peripheral devices from a BASIC program if the system hardware permitted.

Any MBASIC programs that made use of PEEK and POKE, and of machine code user functions, were not portable between machines without modifications.

Successors to MBASIC

[edit]

Besides Microsoft's BASIC-80 for CP/M, a variant of MBASIC was also available as for the ISIS-II operating system.

MSX-BASIC is also a well known successor of MBASIC, featuring several extensions specific to the MSX machines.

All the functions of CP/M MBASIC were available in the IBM PC disk-based BASICA or GWBASIC which made migration of programs from CP/M systems to PC-compatibles possible. The tokens used to represent keywords were different, so CP/M programs had to be saved in ASCII source form. Typically screen formatting escape sequences put into the CP/M version would be replaced with the cursor positioning commands found in the PC versions of BASIC, otherwise little rewriting would be needed.

BASCOM

[edit]

Microsoft sold a CP/M BASIC compiler (known as BASCOM) which used a similar source language to MBASIC. A program debugged under MBASIC could be compiled with BASCOM. Since program text was no longer in memory and the run-time elements of the compiler were smaller than the interpreter, more memory was available for user data. Speed of real program execution increased about 3 fold.

Developers welcomed BASCOM as an alternative to the popular but slow and clumsy CBASIC. Unlike CBASIC, BASCOM did not need a preprocessor for MBASIC source code so could be debugged interactively.[2] While approving of its superior edit-compile-run-debug loop compared to CBASIC, and stating that binaries ran far faster, Jerry Pournelle in December 1980 denounced Microsoft's requirement of a 9% royalty for each binary copy[3] and $40 for hardware-software combinations. The company also reserved the right to audit developers' financial records. Because authors' typical royalty rates for software was 10-25%, InfoWorld in 1980 stated that BASCOM's additional 9% royalty rate "could make software development downright unprofitable", concluding that "Microsoft has the technical solution [to CBASIC's flaws], but not the economic one".[2]

Importance of MBASIC

[edit]

MBASIC was an important tool during the era of 8-bit CP/M computers. Skilled users could write routines in MBASIC to automate tasks that in modern-day systems would be performed by powerful application program commands or scripting languages. Exchange of useful MBASIC programs was a common function of computer users' groups. Keying in long BASIC listings from a magazine article was one way of "bootstrapping" software into a new CP/M system. At least one compiler for a high-level language was written in MBASIC, and many small games and utility programs ranging from a few lines to a few thousand lines of code were written.

Other uses

[edit]

MBASIC is also the name of a commercial BASIC compiler for the Microchip Technology PIC microcontroller family developed by Basic Micro, Inc., unrelated to the CP/M interpreter.

References

[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
MBASIC, also known as BASIC-80, is a disk-based interpreter for the BASIC programming language developed by Microsoft for 8080 and Z80 microprocessor-based systems running the CP/M operating system.[1] It originated as a descendant of Microsoft's Altair BASIC from 1975 and was first released around 1977-1978, becoming one of the most influential and widely adopted BASIC implementations for 8-bit microcomputers during the late 1970s and early 1980s.[2][3] Designed to meet the ANSI X3.60-1978 standard for minimal BASIC, MBASIC provided versions such as 8K, Extended, and Disk BASIC to accommodate different memory configurations and user needs, enabling efficient program development, editing, and execution on resource-constrained hardware.[1] Key features included support for integer, single-precision (7 digits), and double-precision (16 digits) arithmetic; file input/output operations for sequential and random access; error handling with ON ERROR GOTO; and debugging tools like TRON/TROFF for tracing execution.[1] It also offered advanced commands such as WHILE/WEND loops, user-defined functions, and machine-specific PEEK and POKE for direct hardware interaction, making it suitable for both hobbyist and professional programming on systems like the Altair 8800 successors and early portable computers.[4][1] MBASIC's popularity stemmed from its portability across CP/M-compatible machines, including the Kaypro and Osborne series, and its role in porting programs to later Microsoft BASIC variants like BASICA for the IBM PC.[5] By version 5.0 (copyright 1978), it included significant enhancements over earlier releases, such as improved editing capabilities and compatibility modes, solidifying its status as a cornerstone of early personal computing software ecosystems.[1] A compiler version, BASCOM, was later available for producing standalone executables, extending its utility beyond interpreted environments.[6]

Development History

Origins in Altair BASIC

MBASIC traces its origins to Altair BASIC, Microsoft's inaugural product developed in 1975 by co-founders Bill Gates and Paul Allen specifically for the MITS Altair 8800, the pioneering commercial microcomputer based on the Intel 8080 processor.[7] Motivated by a January 1975 article in Popular Electronics that announced the Altair 8800, Gates and Allen contacted MITS president Ed Roberts and proposed creating a BASIC interpreter, securing a contract despite lacking access to the hardware.[8] To overcome this, Allen developed an 8080 emulator on Harvard University's PDP-10 mainframe, enabling them to write and test the code in MACRO-10 assembly; mathematician Monte Davidoff contributed the floating-point routines.[9] The team completed the interpreter in a frantic effort, delivering a demo that impressed MITS and led to the formal founding of Microsoft on April 4, 1975.[8] Altair BASIC was released in three primary variants tailored to the era's severe memory limitations, reflecting the Altair 8800's modular RAM expansions. The 4K version, the most compact, required just 4 KB of RAM and provided core functionality like basic arithmetic, loops, and simple input/output, fitting into ROM for quick loading but omitting advanced features to conserve space.[10] The 8K edition expanded capabilities slightly while still operating within 8 KB constraints, supporting longer programs and more variables.[10] The Extended BASIC variant demanded at least 12 KB of RAM and introduced enhancements such as the PRINT USING statement for formatted output and support for multi-dimensional arrays, enabling more sophisticated applications like data processing on S-100 bus systems compatible with the Altair.[10] Under the licensing agreement with MITS, Microsoft adopted a per-copy royalty model—$30 for each 4K or 8K BASIC sold and $150 for Extended—marking an early innovation in software distribution economics.[11] This structure, which included an initial $3,000 advance, incentivized MITS to bundle BASIC with Altair kits but soon revealed challenges from unauthorized copying among hobbyists.[11] In response, Gates penned the seminal "An Open Letter to Hobbyists" in February 1976, published in the Homebrew Computer Club newsletter, decrying widespread piracy of Altair BASIC tapes that undermined royalties and equated to theft, a stance that sparked debate but solidified software as a paid commodity.[8] Initial distribution of Altair BASIC occurred primarily through physical media suited to the Altair's primitive interfaces, with the 4K and 8K versions shipped on paper tape for loading via front-panel bootstraps or teletypewriters like the ASR-33. Later releases, including Extended BASIC, utilized audio cassette tapes for higher-capacity storage, read through the Altair's serial interface connected to standard cassette recorders, while output relied on teletype printers or emerging video terminals for interactive sessions.[10] This method, though cumbersome—requiring manual toggling of switches for initial bootstraps—facilitated widespread adoption among early enthusiasts before evolving into more portable formats for subsequent Microsoft BASIC implementations.[12]

Adaptation for CP/M Systems

The adaptation to the Intel 8080 and Z80 processors for use with the CP/M operating system began in 1977, with Microsoft engineers porting Altair BASIC and renaming it MBASIC to denote Microsoft BASIC.[13] This adaptation retained the core syntax of its predecessor while optimizing for CP/M's environment, enabling broader compatibility with emerging microcomputers.[13] The initial key release, MBASIC-80 in 1978, required a minimum of 28 KB of RAM and introduced support for disk-based storage, marking a shift from tape-only systems to more persistent data handling.[14] Development occurred in close collaboration with Gary Kildall, CP/M's creator at Digital Research, including licensing agreements that facilitated integration; this partnership also incorporated features like the full-screen editor EDIT.COM for program modification and cassette tape support for data transfer on resource-limited setups.[13] By late 1979, MBASIC was released alongside CP/M 2.0, which enhanced file management capabilities, including random-access files up to 8 MB in size for systems specifying a 256-byte record length.[1] Later versions, such as 5.2 in the early 1980s, added refinements tailored for specific hardware, notably bundling with the Osborne 1 portable computer launched in April 1981, where it served as the primary programming environment alongside CP/M, WordStar, and SuperCalc.[13]

Runtime Environment

Hardware and Software Requirements

MBASIC, the CP/M variant of Microsoft BASIC-80, was designed for 8-bit microcomputers equipped with an Intel 8080 or Zilog Z80 processor.[15] It required a minimum of 28 KB of RAM for basic operation, with the core interpreter occupying approximately 16 KB and additional memory needed for program storage and execution.[15] Systems with 32 KB or more were recommended to accommodate larger programs and data structures effectively.[15] For storage, MBASIC relied on a single floppy disk drive—typically 8-inch or 5.25-inch formats compatible with CP/M—or cassette tape for loading and saving programs.[16] Program size was constrained by available RAM, but later versions supported source code up to around 30 KB, limited by the 255-character line length and overall memory allocation.[15] On the software side, MBASIC could not operate standalone and depended on CP/M version 1.4 or later as the host operating system, with version 2.0 preferred for enhanced features like larger random-access files.[15] It interfaced directly with CP/M's Basic Disk Operating System (BDOS) for essential system calls, including file I/O and console operations.[15] A variant of MBASIC for Intel's ISIS-II operating system targeted development systems like the Intellec series, requiring an 8080 processor, at least 48 KB of RAM, and a single disk drive for full functionality.[16] This version maintained compatibility with ISIS-II's file handling but adapted to the system's higher memory demands for debugging and assembly integration.[16]

Integration and Limitations

MBASIC integrates seamlessly with the CP/M operating system by leveraging the Basic Disk Operating System (BDOS) for all disk input/output operations, including file access through functions such as OPEN, CLOSE, GET, and PUT.[1] Console interactions, such as keyboard input and screen output via the CON: device, are managed through direct calls to the CP/M Basic Input/Output System (BIOS), enabling MBASIC to bypass standard BDOS behavior and prevent unintended termination from control-C interrupts during execution. This approach ensures reliable operation within CP/M's environment while adhering to its device conventions for peripherals like printers and auxiliary ports. Despite its tight integration, MBASIC exhibits several inherent limitations tied to the CP/M ecosystem. Output is strictly text-based, with no native support for graphics, sound, or color, confining applications to terminal-style displays typical of 1970s-1980s hardware.[1] The interpreter enforces single-tasking execution only, lacking features like user areas, networking capabilities, or multitasking, and it depends entirely on the host CP/M system for error handling and resource management, which can lead to abrupt halts without built-in recovery mechanisms.[1] Performance constraints further highlight MBASIC's environmental bounds, as its interpretive nature introduces execution overhead, making it slower than compiled alternatives for compute-intensive tasks. Memory management in extended sessions can result in fragmentation, necessitating garbage collection pauses that may last 1 to 1.5 minutes, potentially disrupting workflow.[1] Additionally, MBASIC's design precludes compatibility with subsequent standards like MS-DOS, rendering it obsolete for native modern use; contemporary access relies on emulators such as SIMH for accurate CP/M simulation or DOSBox-integrated tools like 22NICE for running legacy sessions.

Language Features

Interpreter Mechanics and Syntax

MBASIC functions as an interpreter that executes programs line by line in memory, supporting line-numbered BASIC code stored in a tokenized binary format that compresses keywords, operators, and functions into single-byte (0x80–0xFF) or two-byte tokens for efficient storage.[17][1] This format serves as the default for saved programs, with an optional ASCII mode available via the SAVE command's "A" parameter, though the tokenized representation remains the primary in-memory structure during editing and execution.[1] The interpreter operates in two modes: direct mode for immediate command execution without line numbers, prompting with "Ok" after each statement, and indirect mode for storing and running numbered programs via the RUN command, which begins execution at the lowest line number (ranging from 0 to 65529).[1] Basic syntax revolves around commands entered at the prompt or within numbered lines, with statements separated by colons and a maximum line length of 255 characters in the disk-based MBASIC implementation.[1] Keywords such as RUN (to execute a program), LIST (to display source code), and SAVE (to write to disk) are case-insensitive, permitting mixed-case input while treating it uniformly.[1] Upon encountering invalid syntax, the interpreter halts and issues full-text error messages like "Syntax error" or "Type mismatch" in extended versions, providing clear diagnostics unlike the numeric codes in smaller variants.[1] Program editing integrates directly into the interpreter via a built-in line editor, invoked by typing the line number followed by subcommands such as "I" for insert or "D" for delete, allowing precise modifications without external tools.[1] MBASIC eschews structured modules, depending on line numbers for sequencing and flow control through commands like GOTO and GOSUB.[1] For debugging, an optional trace mode enabled by TRON prints the executing line number before each statement, with TROFF disabling it to resume normal output.[1] A distinctive syntactic feature is the automatic initialization of variables to zero (for numerics) or null strings upon first use, reducing boilerplate code for setup.[1] This, combined with the tokenized input process—where the interpreter converts textual keywords to tokens during entry—ensures streamlined program handling within the constraints of CP/M environments.[17][1]

Variables and Data Types

MBASIC supports four primary data types: integers, single-precision floating-point numbers, double-precision floating-point numbers (in extended versions), and strings. Integers are 16-bit signed values ranging from -32768 to 32767, occupying 2 bytes of storage.[1] Single-precision floating-point numbers use 32 bits to represent real numbers with approximately 6 to 7 decimal digits of precision and occupy 4 bytes.[1] Double-precision floating-point, available only in the Extended and Disk BASIC versions of MBASIC, employs 64 bits for up to 16 decimal digits of precision and requires 8 bytes.[1] Strings consist of 8-bit characters with a maximum length of 255 characters, plus 3 bytes of overhead for length and descriptor information.[1] MBASIC does not support user-defined types or complex numbers, limiting numerical operations to these basic forms.[1] Variables in MBASIC are named using alphanumeric identifiers that begin with a letter, followed by letters or digits, with the first two characters being significant in the 8K version and up to 40 characters in Extended and Disk versions.[1] The data type is indicated by an optional suffix: no suffix or "!" for single-precision, "%" for integer, "#" for double-precision, and ""for[string](/page/String)(e.g.,A" for [string](/page/String) (e.g., `A%` for an [integer](/page/Integer) variable or `NAMEfor a [string](/page/String)).[](https://ia800609.us.archive.org/11/items/BASIC-80_MBASIC_Reference_Manual/BASIC-80_MBASIC_Reference_Manual_text.pdf) Variables are implicitly declared upon first assignment, with a default type of single-precision numeric unless specified otherwise via type suffixes or global type statements likeDEFINT, DEFSNG, DEFDBL, or DEFSTR, which set defaults for ranges of variable names (e.g., DEFINT A-Zmakes all unspecified numeric variables [integer](/page/Integer)s).[](https://ia800609.us.archive.org/11/items/BASIC-80_MBASIC_Reference_Manual/BASIC-80_MBASIC_Reference_Manual_text.pdf) Arrays are declared explicitly using theDIMstatement, specifying dimensions up to 255 with a maximum of 32767 elements per dimension (e.g.,DIM SALES(12, 4)` for a two-dimensional array), and follow the same naming and typing rules as scalar variables.[1] Variable names cannot be reserved words, though Extended and Disk versions permit embedded reserved words within longer names.[1] Type handling in MBASIC includes automatic conversions during expressions and assignments to promote compatibility. For instance, assigning a floating-point value to an integer variable truncates the fractional part after rounding (e.g., A% = 23.7 sets A% to 24), while arithmetic operations use the type of the most precise operand, converting others as needed (e.g., integer operands in a sum with a float become floats).[1] Explicit conversion functions such as CINT, CSNG, CDBL, STR$, and VAL allow programmers to control type changes (e.g., CINT(55.88) yields 56).[1] Strings are delimited by double quotes in literals (e.g., MESSAGE$ = "Hello, World!") and support concatenation with the + operator, but numeric-string mixing requires explicit conversion to avoid errors.[1] Precision limits apply strictly: integers overflow silently by wrapping around, and floating-point operations may lose accuracy beyond the supported digits.[1] Storage for variables is dynamically allocated from the available memory space, distinct from program code. Numeric variables and arrays use fixed sizes per element (2 bytes for integers, 4 for single-precision, 8 for double-precision), while strings are allocated from a separate string space managed by the interpreter's garbage collector, which reclaims unused space when needed and can be queried via FRE("").[1] In the 8K version, memory constraints limit variable usage more severely compared to Extended BASIC, which supports larger programs and more variables.[1] This dynamic approach allows flexible use of variables in expressions and control structures without manual memory management.[1]
10 DEFINT A-Z  ' Default all numerics to integer
20 A = 42      ' A is integer (42)
30 B! = 3.14   ' B is single-precision (overrides default)
40 C$ = "Data" ' C is string
50 DIM X(5)    ' Integer array X with 6 elements
60 PRINT A, B!, C$, X(1)
This example illustrates variable declaration, typing, and array usage, with output showing the respective values.[1]

Control Structures

MBASIC provides unstructured control flow primarily through unconditional jumps and basic conditional statements, relying on line numbers to specify targets for branching. Programs are organized into sequentially numbered lines, typically integers from 0 to 65529, which serve as unique identifiers for execution points; all GOTO, GOSUB, and similar statements must reference these line numbers rather than symbolic labels. This design, inherited from earlier BASIC interpreters, facilitates simple navigation but can lead to "spaghetti code" without careful structuring.[1] Unconditional branching is handled by the GOTO statement, which transfers execution immediately to the specified line number without preserving the call stack. For subroutines, GOSUB branches to a line number while pushing the return address onto an internal stack, allowing up to a memory-limited depth of nesting; execution resumes after the calling line upon encountering RETURN, which pops the stack and jumps back accordingly. These mechanisms enable modular code reuse but lack modern scoping or parameter passing. For example:
10 GOSUB 100
20 PRINT "Back from subroutine"
...
100 PRINT "In subroutine"
110 RETURN
[1] Conditional execution uses the IF statement in a single-line format: IF THEN or , with an optional ELSE clause available only in Extended and Disk versions of MBASIC. The expression evaluates to true if non-zero, executing the THEN branch or the ELSE if present; multi-line IF blocks, SWITCH/CASE statements, or relational chaining are not supported, limiting complex decision logic to multiple single-line IFs or computed GOTOs. An example illustrates a basic comparison:
10 IF X > 0 THEN 20 ELSE 30
20 PRINT "Positive": [GOTO](/page/Goto) 40
30 PRINT "Non-positive"
40 END
This restriction encourages reliance on GOTO for flow control within conditionals.[1] Looping constructs include FOR-NEXT for counted iterations and, in Extended and later versions, WHILE-WEND for condition-based repetition. The FOR statement initializes a numeric variable to a starting value, incrementing it by 1 (or a specified STEP value, positive or negative) until it reaches or passes the end value, at which point NEXT (optionally naming the variable) advances to the matching FOR or exits the loop; nested FOR loops match innermost-first. WHILE begins a loop that continues as long as the expression is non-zero, terminating at WEND, with support for arbitrary nesting but no DO-WHILE variant for post-condition checks. Advanced iterators like FOR-EACH are absent. A simple FOR loop example is:
10 FOR I = 1 TO 10 STEP 2
20 PRINT I
30 NEXT I
These loops provide essential repetition without built-in break or continue equivalents, often paired with IF-GOTO for early exits.[1] Error handling in MBASIC employs ON ERROR GOTO , available in Extended and Disk versions, which redirects execution to the specified line upon any runtime error, allowing custom recovery routines; the error can be queried via ERR and ERL functions, and RESUME restores normal flow. Without this, errors halt execution immediately, and no try-catch blocks or exception types exist, making robust programs dependent on anticipatory checks. For instance:
10 ON ERROR GOTO 1000
20 A = 1 / 0  REM [Division by zero](/page/Division_by_zero)
...
1000 PRINT "Error at line"; ERL
1010 RESUME NEXT
This basic trapping mechanism supports debugging in resource-constrained environments.[1]

Input/Output and File Handling

MBASIC provides straightforward mechanisms for input and output operations, primarily through console interactions, printer output, and disk file management, tailored to the constraints of CP/M environments. Console input is handled via the INPUT statement, which pauses program execution to accept data from the user, optionally preceded by a prompt string. For instance, INPUT "Enter name: "; A\$ displays the prompt and assigns the entered string to variable A$, with data items separated by commas for multiple variables. If no prompt is given, MBASIC prints a question mark; numeric variables expect numeric input, while strings accept any characters until Enter.[15] Output to the console uses the PRINT statement, which displays expressions, strings, or variables, with formatting options for alignment. Commas in PRINT advance to the next 14-space zone, semicolons place items immediately after the previous output without spacing, and a trailing semicolon suppresses the carriage return. Additional formatting includes TAB(n) to position the cursor at column n (where n ranges from 1 to the screen width) and SPC(n) to insert n spaces (n from 1 to 255), enabling tabular displays or spacing control; the screen serves as the default output device.[1][15] Printer output in MBASIC is directed through dedicated statements that interface with the CP/M printer device (typically LST:). The LPRINT statement functions analogously to PRINT but sends output to the printer, supporting up to 132 characters per line and the same formatting options like commas, semicolons, TAB, and SPC. For example, LPRINT "Report Header"; TAB(20); "Data Value" produces aligned printed text. The LLIST command lists program lines to the printer, mirroring the LIST command's syntax for specifying line ranges, such as LLIST 100-200, without advanced formatting beyond basic line numbering. These operations lack built-in support for printer-specific controls like font changes or margins, relying on CP/M's device handling.[15][1] File handling in MBASIC supports sequential and random-access operations on disk files, managed through statements that allocate file numbers (1 to 15) and interact with CP/M's file system. The OPEN statement establishes a file connection, specifying mode ("I" for input/sequential read, "O" for output/sequential write, or "R" for random access), file number, and filename, with an optional record length for random files (default 128 bytes). For example, OPEN "O", #1, "DATA.TXT" prepares a sequential output file. Sequential files are read or written line-by-line using INPUT# and PRINT# (or WRITE# for comma-quoted output), respectively; PRINT# mirrors console PRINT but appends a carriage return/line feed, while WRITE# adds delimiters for data portability. The CLOSE statement terminates access to specified files (or all if omitted), ensuring buffers are flushed for output files, and KILL deletes a file from disk, such as KILL "DATA.TXT". Random-access files use fixed-length records, with FIELD #n, length AS var$ defining substrings in a buffer (e.g., FIELD #1, 10 AS A\$, 20 AS B\$), and GET/PUT statements to read/write records by number via an implicit RECORD variable (set with RECORD #1, recnum). File status is queried using EOF(n), which returns -1 at the end of a sequential input file, and LOF(n), which provides the number of bytes (sequential) or records (random) in the file.[15][1] MBASIC employs the Microsoft Binary Format (MBF) for efficient storage of numeric data in files, particularly in random-access mode, where integers, singles, and doubles are packed into fixed bytes (e.g., 2 for integers, 4 for singles) to conserve space on limited CP/M disks. Sequential files default to ASCII text for readability, but binary output can be forced; conversion between formats uses functions like MKI$(value) to create MBF integer strings, CVS$(string) to unpack singles, and their inverse CVI and CVD equivalents for input. Utilities such as SAVE "filename",A explicitly save programs or data in ASCII, while standard SAVE uses compressed MBF; EOF and LOF assist in navigating these formats without manual byte counting. This design balances portability and efficiency, though MBF requires compatible Microsoft BASIC interpreters for direct reading.[15][1]

Advanced Capabilities

Memory Access Operations

MBASIC provides direct memory access through the PEEK function and POKE statement, enabling programmers to read from and write to specific memory locations for low-level data manipulation. These operations are essential for tasks requiring interaction with hardware-specific memory areas, such as inspecting status flags or modifying data structures not accessible via standard BASIC variables. However, their use demands caution due to the potential for system instability if critical memory regions are altered.[1] The PEEK function retrieves a single byte from a specified memory address, returning an integer value between 0 and 255. Its syntax is PEEK(I), where I is an integer expression representing the memory address. In extended and disk versions of MBASIC, typical for CP/M systems, addresses range from 0 to 65536, allowing access across the full 64 KB address space of 16-bit systems like those based on the Intel 8080 or Zilog Z80 processors. For instance, the statement X = PEEK(16384) would read the byte at address 16384 and store it in variable X, commonly used to inspect system variables or status flags in CP/M environments. This function complements higher-level data handling by providing granular inspection without altering memory contents.[1] In contrast, the POKE statement writes a byte to a memory address, with the syntax POKE I, J, where I is the target address and J is the byte value (0 to 255). Like PEEK, it operates within the 0 to 65536 address range in extended MBASIC implementations. An example is POKE 16384, 0, which sets the byte at address 16384 to 0, potentially used to clear flags or update data in video memory for custom display routines on CP/M terminals. Programmers often employed POKE to load small assembly routines or pass parameters to machine-code subroutines directly in memory. However, invalid addresses or writes to protected areas, such as the MBASIC interpreter itself or CP/M system regions, can cause program crashes or system hangs.[1] These operations are inherently non-portable across different hardware configurations, as memory maps vary between systems; for example, video memory locations differ on 8080-based versus Z80-based CP/M machines, and address calculations may require adjustments due to processor-specific memory layouts or BIOS implementations. In Z80 systems, additional registers might influence indirect addressing, but PEEK and POKE themselves remain byte-oriented and compatible with 8080 code. Users are advised to consult system-specific documentation, such as CP/M BIOS details, before employing these commands to avoid hardware-dependent errors. Overall, while powerful for advanced applications like real-time data inspection in embedded-like environments, PEEK and POKE underscore the trade-offs of direct hardware access in an interpreted language.[1]

Hardware Interaction and Extensions

MBASIC provided direct hardware interaction through the INP and OUT statements, enabling programs to read from and write to I/O ports on the host machine. The INP function, with syntax INP(I) where I is an integer expression between 0 and 255, returns an integer value (0 to 255) representing a byte read from the specified hardware input port.[1] For example, INP could be used to read status from a serial interface, such as the 8251 UART on CP/M systems.[1][18] Similarly, the OUT statement, formatted as OUT I, J where both I and J are integers from 0 to 255, transmits the byte value J to output port I, such as sending control signals to a parallel printer port.[1] These operations were limited to 8-bit values and were available in the 8K, Extended, and Disk versions of MBASIC, but their behavior was hardware-dependent, varying across CP/M implementations due to differences in port mappings for peripherals like serial interfaces (e.g., the 8251 UART).[1][18] To extend functionality beyond interpreted BASIC code, MBASIC supported the USR function for invoking machine code subroutines, allowing integration of assembly language routines for performance-critical tasks or hardware-specific operations. The USR syntax is USR[19], where (0-9) selects one of up to ten predefined routines and argument is a numeric value passed to the subroutine, typically via memory locations or CPU registers like the accumulator in Z80/8080 architectures. In 8K BASIC, USR supports a single routine without the digit selector.[1] The starting address for each USR routine is set using DEF USR[] = address, an integer expression specifying the memory location of the assembled code.[1] Programmers often assembled these subroutines using tools like the Z80 assembler and loaded them into memory before execution, enabling hybrid programs that combined BASIC's ease with assembly's speed—for instance, custom graphics drivers or device controllers.[1] This feature was available in 8K, Extended, and Disk BASIC versions, with the subroutine expected to return control to BASIC upon completion.[1] For simpler extensions without machine code, MBASIC included the DEF FN statement to define user-written functions directly in BASIC, facilitating reusable code snippets for calculations or logic. The syntax is DEF FN[(parameter list)] = expression, where follows variable naming rules (starting with FN), parameters are optional variables, and the expression is a single-line formula supporting arithmetic, variables, and other BASIC functions.[1] For example, DEF FNDIST(X1,Y1,X2,Y2) = SQR((X2-X1)^2 + (Y2-Y1)^2) creates a function for Euclidean distance, callable as A = FNDIST(0,0,3,4).[1] Available across all MBASIC variants, DEF FN supported numeric functions in the 8K version (with one argument limit) and both numeric and string types in Extended and Disk versions, though redefinition required re-execution and direct-mode use was prohibited.[1] These hardware interaction features carried risks of system instability, as INP and OUT lacked built-in validation for port access, potentially causing hardware malfunctions or crashes when targeting undefined or protected ports.[1] USR calls amplified this danger, with invalid addresses leading to memory corruption or interpreter crashes, especially in resource-constrained CP/M environments.[1] In modern emulation, such as MAME's drivers for CP/M hardware like the Sorcerer or NABU PC (updated post-2020), these operations are faithfully reproduced, allowing safe testing of legacy code on emulated ports without physical risks.[20][21]

BASCOM Compiler

BASCOM is a BASIC compiler developed by Microsoft and released in 1979 for the CP/M operating system, serving as a companion to the MBASIC interpreter. It compiles MBASIC source code into relocatable object modules (typically with a .REL extension) or absolute COM files, which can be linked using tools like the Microsoft LINK-80 to create standalone executables for 8080 or Z80 microprocessors. This process enables the generation of faster, more efficient programs without requiring an interpreter at runtime, with compiled code generally executing 5 to 10 times faster than interpreted MBASIC equivalents. In specific cases, such as integer variable loops, performance can reach up to 30 times the speed of the interpreter.[22] The compiler maintains strong compatibility with MBASIC by directly processing standard .BAS source files, eliminating the need for a preprocessor or source modifications in most scenarios. It supports linking with CP/M system libraries to preserve familiar input/output behaviors, including file handling and console interactions. While the majority of MBASIC statements are fully supported—such as DIM for array declaration, FOR/NEXT and WHILE/WEND loops, IF/THEN/ELSE conditionals, and double-precision mathematical functions—certain interactive editor commands like LIST, SAVE, and direct mode execution are excluded, as they pertain to the interpretive environment rather than compiled output. Limitations also apply to features like the COMMON statement in some configurations, though compatibility switches (e.g., /4 for BASIC-80 version 4.51 conventions) address variations in loop execution and other behaviors.[22] BASCOM incorporates several code optimizations to reduce execution time and memory usage, including constant folding (evaluating constant expressions at compile time), peephole optimization (replacing inefficient instruction sequences), and common subexpression elimination (avoiding redundant calculations). For instance, in a program with repeated constant-based assignments, the compiler precomputes values to streamline the resulting machine code. Additional command-line switches enhance flexibility, such as /Z for Z80-specific opcodes to leverage extended instructions, /E for enabling ON ERROR GOTO handling, /S for optimized string operations, and /D for debugging output that traces compilation steps. These features make BASCOM suitable for developing performance-critical applications on resource-constrained CP/M systems requiring at least 32 KB of memory (with a BASCOM32 variant for smaller setups).[22] Commercially, BASCOM was distributed as part of a development package that included the MACRO-80 macro assembler and LINK-80 utility, aimed at professional programmers building distributable CP/M software. The high upfront costs of the era's software tools contributed to its limited adoption.[22][23]

Successors and Derivatives

Following the success of MBASIC on CP/M systems, Microsoft ported its BASIC interpreter to the Apple II in 1977 as Applesoft BASIC, an enhanced version of its 6502 BASIC that added floating-point arithmetic and Apple-specific graphics commands.[24] This port marked an early adaptation of the core MBASIC syntax and features to non-CP/M platforms, though it diverged with hardware-tailored extensions.[25] The primary successor for personal computing arrived with the IBM PC in 1981, where Microsoft delivered BASICA (Advanced BASIC), an extension of MBASIC version 5.x integrated into the PC's ROM for immediate startup.[26] BASICA retained MBASIC's line-numbered syntax, control structures, and file handling while adding support for the PC's cassette interface and disk operations under PC-DOS, but required at least 40 KB of memory and was tied to IBM hardware.[27] In 1983, Microsoft introduced GW-BASIC as a disk-based enhancement for MS-DOS systems on non-IBM PCs, functionally identical to BASICA but without ROM dependency, allowing broader compatibility and minor optimizations like improved screen handling.[28][29] Derivatives extended the lineage further: MSX-BASIC, released in 1983 for the MSX home computer standard co-developed by Microsoft and ASCII, built on MBASIC 4.5 with additions for sprites, sound, and joystick input to support multimedia peripherals.[30] By 1991, QBasic emerged as a structured evolution bundled with MS-DOS 5.0, preserving MBASIC's foundational syntax like PRINT and INPUT statements while introducing optional line labels, better error handling, and IDE features, though it omitted some low-level operations.[31][32] Migration from CP/M-based MBASIC to PC environments was facilitated by high source code compatibility in BASICA and GW-BASIC, which supported most MBASIC programs directly after ASCII text file transfers, though CP/M-specific features like direct BDOS calls were lost in favor of DOS equivalents.[26] Tools such as simple file converters handled line-ending and encoding differences, enabling business applications to transition with minimal rewrites.[33] In modern contexts, emulations preserve these interpreters; GW-BASIC runs natively under FreeDOS for legacy hardware compatibility, while post-2020 projects like Microsoft's open-sourcing of GW-BASIC source code on GitHub enable recompilation and online interpreters for web-based execution. In September 2025, Microsoft open-sourced the source code for its 1978 Microsoft BASIC for 6502 Microprocessor Version 1.1 under the MIT License, facilitating further study and emulation of early variants like Applesoft BASIC.[34][35][36] BASCOM, a parallel compiling tool from the MBASIC era, offered binary output but remained distinct from these interpretive evolutions.[26]

Historical Significance

Role in Early Computing

MBASIC played a pivotal role in democratizing programming during the late 1970s and early 1980s by offering an interactive interpreter that lowered the barrier to entry for non-experts on resource-constrained 8-bit systems. As an extension of Microsoft's original Altair BASIC, MBASIC provided immediate feedback through its command-line interface, enabling users without deep technical knowledge to write, test, and debug simple programs on the fly. This accessibility was instrumental in expanding personal computing beyond hobbyists and engineers to business professionals and home users, who could leverage it for everyday tasks without needing to master low-level assembly language.[37][38] A key factor in MBASIC's adoption was its bundling with early portable computers, such as the Osborne 1 released in 1981, which included MBASIC alongside CP/M 2.2, WordStar, and SuperCalc. This software suite, valued nearly as much as the hardware itself at around $1,500, made CP/M-based systems affordable and practical for business and home applications, transforming the Osborne 1 into one of the first commercially successful luggable computers with over 10,000 units sold in its debut year. By integrating seamlessly with CP/M, MBASIC facilitated file handling and disk operations, rendering the platform viable for portable productivity in an era dominated by stationary minicomputers.[39][40] In practice, MBASIC powered a range of applications on 8-bit machines, including automation scripts for repetitive office tasks, simple text-based games like adventure simulations, and basic data processing for inventory or financial records. These uses exemplified its utility for rapid development, allowing users to create functional programs—such as sorting algorithms or report generators—with minimal overhead, often in under 64 KB of memory. Commercial examples included accounting software and inventory management tools, where MBASIC's string manipulation and file I/O features enabled efficient handling of unstructured data without requiring compiled languages.[41] MBASIC's market impact underscored Microsoft's strategic pivot to software distribution, building on the success of its BASIC interpreters to establish dominance in the emerging personal computer ecosystem. It enabled quick prototyping of applications before more sophisticated languages like C gained traction, fostering innovation in S-100 bus systems that formed the backbone of early microcomputer setups. By 1983, Microsoft BASIC variants like MBASIC had reached hundreds of thousands of users across CP/M installations, influencing the software portability and standardization that propelled the industry forward.[38][42]

Community Impact and Legacy

MBASIC fostered vibrant user communities in the late 1970s and early 1980s, particularly among hobbyists and early microcomputer enthusiasts who shared code listings through magazines and users' groups. Publications like Kilobaud Microcomputing frequently featured type-in programs written in MBASIC, including utilities for data management and simple games, which readers would manually enter into their systems to expand functionality. These shared resources, distributed via users' groups such as those affiliated with CP/M systems, democratized access to programming examples and encouraged collaborative learning among non-professional coders.[43][44] The legacy of MBASIC lies in its role as a foundational interpreter that propelled the widespread adoption of BASIC as an accessible entry point for programming, influencing the language's popularity in personal computing eras. By providing a structured yet simple environment for CP/M-based machines, it enabled rapid prototyping and experimentation, laying groundwork for BASIC's integration into subsequent Microsoft products like GW-BASIC and QBasic. In the 2020s, MBASIC's enduring appeal has inspired retro computing revivals, with hobbyists using emulators to recreate early experiences and preserve its syntax in modern contexts.[45][46] While MBASIC has no direct modern applications due to its obsolescence, its emphasis on straightforward syntax and immediate execution has indirectly shaped contemporary scripting languages such as Python and Ruby, which prioritize readability for beginners. Post-2020 efforts in digital preservation have focused on archiving MBASIC-related materials, with platforms like the Internet Archive hosting scanned magazines and code listings to safeguard these artifacts for educational and historical purposes. Notable examples include Microsoft's release of GW-BASIC source code in 2020 and the original 6502 BASIC source code in September 2025 under the MIT license, facilitating further study and emulation of early Microsoft BASIC interpreters.[47][48][49][2][50] It is important to disambiguate MBASIC from an unrelated product: a BASIC compiler for Microchip PIC microcontrollers developed by Basic Micro, Inc., introduced in the 2000s for embedded systems programming. This later MBASIC, detailed in resources like the book Programming the PIC Microcontroller with MBasic, targets low-level hardware control and shares no lineage with Microsoft's interpreter.

References

User Avatar
No comments yet.