Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>LMC — teaching assembly languageNew to Visual Studio Code? Get it now.
LMC — teaching assembly language

LMC — teaching assembly language

mmarchand

|
8 installs
| (0) | Free
The LMC assembly language: diagnostics, completion, formatting and a step-through emulator. A teaching tool, in French, English, Spanish, Japanese or Korean.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

LMC — teaching assembly language

The LMC assembly language in VS Code: everything you need to write, understand and run programs for a machine with a hundred memory cells, in class.

Available in French, English, Spanish, Japanese and Korean. Diagnostics, hover, completion and the emulator panel all follow one setting, lmc.locale (fr, en, es, ja, ko, or auto). It is auto by default, which follows VS Code's display language. Set it explicitly if you teach in a language other than the one your editor is in, which is the common case: a display language stays English for most people whatever their country, because nobody changes it. A language this extension does not speak falls back to English rather than to blanks.

The Spanish, Japanese and Korean have not been read by anyone who speaks them. Corrections are very welcome — an awkward turn of phrase in a teaching tool costs more than in most software.

This is not the original LMC. The machine word is four digits, there are five registers (ACC, SI, LR, SP, PC) and seventeen mnemonics, including MOV, subroutines (JSR/RET), a stack (PSH/POP) and a screen (PLT).

Bringing a program in from a stock LMC emulator usually costs one edit: a colon after each label, FIRST DAT becoming FIRST: DAT. Checked by running the classic two-input adder and a classic countdown loop, which both work with nothing else changed. Two things still bite: textbooks that spell the mnemonics STO, BR or COB (here they are STA, BRA and HLT), and a label named after a register, since ACC, SI, LR, SP and PC are reserved words. Going the other way is another matter: anything using MOV, JSR, PSH or PLT has nowhere to run but here.

The instruction set

Seventeen mnemonics. Hovering over any of them in the editor gives this same text, in your language, with the details this table leaves out.

INP read a value from the input into the accumulator
OUT write the accumulator to the output
HLT stop the program
ADD addr add the value at the address to the accumulator
SUB addr subtract the value at the address from the accumulator
LDA addr load the value at the address into the accumulator
STA addr store the accumulator at the address
MOV dst, src the general form of both: LDA n is MOV ACC, n, STA n is MOV n, ACC
BRA addr unconditional jump
BRZ addr jump if accumulator = 0
BRP addr jump if accumulator >= 0
JSR sub call a subroutine, recording the return address in LR
RET return to the last caller: jumps to LR, also written MOV PC, LR
PSH reg push a register onto the stack; with none written, ACC
POP reg pop the top of the stack into a register; with none written, ACC
PLT addr light a pixel, reading x, y and the colour from three cells at addr
DAT n, ... reserve one or more memory cells

A label ends with a colon (total: DAT 0), and lst[SI] addresses the cell lst + SI, which is what lets one instruction walk an array. Branches and PLT cannot be indexed.

What the extension gives you

  • Diagnostics that explain rather than merely report: an undefined label, a missing HLT, a program that outgrows the hundred cells, an address outside 0-99 — that last one because, written as is, it would overflow into the mode digit and assemble into another perfectly valid instruction, silently.
  • Hover, go to definition, find references, completion on labels and mnemonics.
  • Formatting of the whole document, to one canonical shape.
  • A step-through emulator, command "LMC: Open Emulator". This is the centrepiece.

The emulator

A grid of a hundred cells, the five registers, the input and output trays, and the Fetch / Decode / Execute cycle unfolded at every step — including the program counter being incremented during the read, which is what explains why a stopped machine shows a PC one past the instruction that stopped it.

At every step, the cells the instruction touched light up: teal for a cell that was read, pink for one that was written. Reading changes nothing, writing changes the machine, and the grid says which just happened. The colour stays until the next instruction runs, so there is time to look. The registers carry the same two colours — a step does two things, one to memory and one to the processor — and one both read and written in the same step is pink, the warm colour going to the act that changes the machine.

The panel and the editor are synced both ways: moving the cursor outlines the matching cell, clicking a cell reveals its source line. That is the reason for a panel here rather than one of the many standalone LMC simulators on the web.

The grid marks four things: the stack above SP, the cells a DAT reserved, the unused middle, and the code. Those marks say what the author wrote, not what the machine does: nothing distinguishes a code cell from a data cell, and a STA writing into code does not change a colour. That gap is the lesson, not a defect.

Assemble, Load and Run are three separate acts, with three buttons. "Assemble" writes a .lmcobj next to the source: four digits per line, one line per cell, no mnemonics and no labels, because that is all the processor ever receives. "Load" reads that file back off the disk. Loading before assembling fails, and editing the source without reassembling loads the old program: that is how a real toolchain behaves.

What the model simplifies, on purpose

  • There is no MAR, MBR or IR. On a real processor, the fetch goes through three internal registers: MAR <- (PC), then MBR <- (memory), then IR <- (MBR) (W. Stallings, Computer Organization and Architecture, ch. "Control Unit Operation"). Here the first two are folded into a single cell read, and the fetched word is decoded without being shown in an instruction register. The panel still says where the address comes from: read PC → 0, then read mem[0] → 5003, then PC 0 → 1. Adding those three registers would make the machine harder to follow without teaching more about it.
  • "Read" means something different for a register than for a cell. Memory is read on command: an address goes out, a READ signal is sent, the word comes back. A register does not work that way: its value is always present on its outputs, and "reading" it means that value is passed on to the part that needs it, at the moment it is needed (onto a bus, into an adder, into another register). When the panel says read ACC → 5 or turns a register teal, it means the step used that register's value, not that a separate read operation took place.

A screen

PLT lights a pixel on a 32 × 32 screen in eight colours. Colour 0 is the background, so lighting a pixel in 0 erases it. A pixel outside the screen or outside the palette is not drawn, and the cycle panel says so instead of leaving an unexplained blank.

The code

Written for teaching Numérique et Sciences Informatiques, the French high-school computer science curriculum. The extension is open source, MIT, at lmc-vscode; issues and corrections are welcome there, including on the translations. The language server it drives is a separate, private repository, kept apart so that it stays editor-independent rather than tied to VS Code; it ships inside this extension, so nothing else is needed to install and use it.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft