Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>Assembly ExplorerNew to Visual Studio Code? Get it now.
Assembly Explorer

Assembly Explorer

kuchingneko

|
1 install
| (0) | Free
Compile C/C++ to assembly with Compiler Explorer and inspect it side by side with your source.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Assembly Explorer

Compiles the C or C++ file you are editing with Compiler Explorer and shows the assembly next to it.

There is no local toolchain to install. The source is sent to the public Compiler Explorer API and the assembly comes back over the network.

What it does

  • Compile. Run Assembly Explorer: Compile to Assembly on a .c or .cpp file (Ctrl+Alt+A, or right-click and pick Compile to Assembly). The assembly opens in a read-only panel beside your code.
  • Compile locally. Assembly Explorer: Compile to Assembly can also run a compiler from your own PATH instead of Compiler Explorer, which needs no network.
  • Hover an instruction. The tooltip shows the source line the compiler attributed it to, its file:line:column, and a link to jump there.
  • Hover your own code. The tooltip shows the instructions that line produced. If it produced none, it says so.
  • Select lines. The matching lines on the other side light up, and the panel scrolls them into view.
  • Click a line. The other pane's cursor moves to the linked line, so both panes show one highlight in the same place.
  • Jump both ways. Assembly Explorer: Go to Source from the panel, Assembly Explorer: Go to Assembly from the source.
  • Follow a label. Ctrl+click or F12 on a label jumps to its definition, and back again. The cursor on a label highlights every place it is used.
  • Stays current. Once a file has been compiled, the panel follows your edits on save.
  • Warnings are shown. A build that succeeds with warnings puts a warning icon in the status bar and lists them in its tooltip.
  • Remembers what it built. Closing a file keeps its assembly, so reopening it is instant. Saving a new file keeps the build it had as an unsaved buffer.
  • Skips work it does not need. Asking for the assembly again when the source and the flags have not changed shows the panel from memory.

Usage

Open a C or C++ file and press Ctrl+Alt+A (macOS: Cmd+Alt+A).

An Assembly Explorer output channel records each compilation and any compiler diagnostics.

Commands

Command Description
Assembly Explorer: Compile to Assembly Compile the active file and open the assembly panel
Assembly Explorer: Optimization Level Pick -O0…-O3, -Os, -Og, or type your own flags
Assembly Explorer: Edit Compiler Flags Type the flags directly, like the flags box on the web
Assembly Explorer: Toggle Optimization (-O0 / -O2) Flip between the two, keeping your other flags
Assembly Explorer: Auto Compile Mode Choose on save or off
Assembly Explorer: Select Compiler Choose the compiler to build with
Assembly Explorer: Toggle Intel / AT&T Syntax Switch assembly syntax and recompile
Assembly Explorer: Go to Source From the assembly panel, jump to the producing source line
Assembly Explorer: Go to Assembly From source, jump to the generated instructions

The everyday commands are also in an Assembly Explorer submenu in the editor context menu.

Where things open

Your code and its assembly each keep their own column.

  • Compiling opens the panel beside your code and does not steal focus. The cursor stays where you were typing.
  • A hover link or Assembly Explorer: Go to Source returns to the column your code is in, never into the panel.
  • The panel is placed once and then left alone. Switching files does not swap it, and opening a file over it does not move that file, so your layout stays put. To see another file's assembly, compile it or click its panel tab. To stop files opening in the panel's column at all, use VS Code's own View: Lock Editor Group on that column.

This matters because VS Code resolves both ViewColumn.Beside and an unset column against whichever group has focus. Leaving the column out gives a different answer depending on where you last clicked, so the extension always names the column.

What happens as files come and go

  • Closing a file closes its panel too. The build itself is kept, in memory and in the saved workspace state, so reopening the file and pressing Ctrl+Alt+A shows the assembly again without a round trip. Closing the panel never closes your code. Results are dropped only once the store passes its cap, oldest first, and never for a file whose code or panel is on screen.
  • Asking again does not necessarily compile. Ctrl+Alt+A reuses the build in memory when the source text and the flags both match it, and compiles only when the answer would differ.
  • Saving a new file carries its build onto the file. Compile an unsaved buffer and it gets a panel named after it, such as Untitled-1.asm. Save it as main.c and the result and the auto-compile tracking move to the real file, the panel becomes main.asm and its old tab is closed. Renaming a file on disk works the same way.

Optimization level

The level is a dial, not a decision. The status bar shows the flags in use next to the compiler. Click it to open a picker with -O0, -O1, -O2, -O3, -Os, -Og, or Other flags… to type your own. Ctrl+Alt+O (macOS: Cmd+Alt+O) flips between -O0 and -O2. Assembly Explorer: Edit Compiler Flags skips the picker and opens the flags box straight away, the way you would type them on the website.

Changing the level rebuilds immediately, with no edit needed. Your other flags are kept: switching with -Wall -O2 gives -Wall -O0.

The default is -O2. That is where the assembly stops being a direct translation of your source: calls get folded away, variables stop existing, and some lines produce nothing at all. Use -O0 when you want the opposite, a listing where every statement maps to real instructions.

Auto compile

Once a file has been compiled, the extension keeps its panel up to date on its own, the way godbolt.org does. Choose a mode with Assembly Explorer: Auto Compile Mode or the godbolt.autoCompile setting.

Mode Behaviour
onSave Rebuild when you save the file (default)
off Only rebuild when you ask

Only files that have already been compiled once are watched, so saving an unrelated C file never contacts the API. Background rebuilds never open a panel or steal focus; the assembly is simply up to date the next time you look at it. A background build that fails stays quiet: the reason goes to the assembly panel and the output channel instead of a popup, and the status bar shows an error icon.

Compiling locally

By default the source goes to Compiler Explorer. A compiler on your machine can do it instead, which needs no network: run Assembly Explorer: Select Compiler and pick Compile locally at the top of the list. The choice is remembered, and the godbolt.compilerMode setting decides the mode until you first switch.

In local mode the compiler setting names the binary, for example gcc or /usr/bin/clang++, and the compiler picker lists the ones found on your PATH, family-appropriately: gcc, clang or cc for C, g++, clang++ or c++ for C++.

Everything else behaves the same, including the optimization dial, the flags and the filters. The source mapping works the same way too: the listing is asked for with -g -S, and each instruction's line and column come from the .loc directives the compiler emits, so the panel, hover, linked highlighting and labels all apply as they do in remote mode.

Labels

The listing is full of names: function labels like main: and square(int):, string and constant labels like .LC0:, and the instructions that refer to them.

Ctrl+click a label, or press F12, to jump to its definition; on the definition itself, F12 jumps back to the places that use it. Put the cursor on a label and every occurrence is highlighted, with Shift+F12 listing them all in the usual way. Hovering a label says whether it is a definition or a use, and shows the other side.

A plain click is left alone: it moves the cursor, which is what keeps the two panes linked.

Hovering your own code

Hover a line of C or C++ and the tooltip shows the instructions that line produced, with a link that jumps to them in the panel. This is the same relationship the assembly hover describes, read from the other end.

The case worth knowing about is the empty one. When a line produces no instructions, the tooltip says the compiler removed it instead of staying silent. Silence would be ambiguous, since it looks the same as a file that has not been compiled. Optimization is the usual reason, so the tooltip also offers a comparison against -O0.

Hovering is turned off once you have edited the file without rebuilding it. The mapping describes the text that was compiled, so after an edit the line numbers mean something different. Save the file, or press Ctrl+Alt+A, and the hovers come back. A hover never appears for a file with no build, or for a build that failed.

Settings

All under godbolt.* in Settings.

Setting Default Description
compiler g162 Compiler Explorer compiler id (x86-64 gcc 16.2)
compilerMode remote Starting mode; the picker switches and remembers it
userArguments -O2 Flags passed to the compiler; the picker edits this
intelSyntax true Intel syntax instead of AT&T
filterDirectives true Hide directives and debug sections, keep only instns
filterLabels true Hide compiler-generated labels such as .LFB0
filterComments true Hide the source lines the compiler echoes back
trim false Trim unused code
autoCompile onSave onSave or off; see above
linkPanes true Highlight linked lines between the source and its assembly

The three filter* settings mirror Compiler Explorer's own "Filter directives / labels / comments" checkboxes. They remove the selected items, so turning one off shows more of what the compiler emitted.

The godbolt.org website defaults to no optimization flags, while this extension defaults to -O2. To match the website, set userArguments to empty. For learning, -O0 is often more useful: the compiler stops rearranging your code and the mapping becomes close to one line per statement.

Any compiler in the Compiler Explorer catalogue can be used. The Select Compiler command searches the live list, fetched once per session, with a built-in fallback list when offline. The picker is split by architecture, with x86-64 first, since the catalogue also holds hundreds of cross-compilers (ARM, AVR, 6502, RISC-V and others) that cannot produce x86 assembly at all.

Development

npm install
npm run compile      # or: npm run watch

Press F5 to launch an Extension Development Host with the extension loaded, then open examples/example.cpp or examples/hello.c. That window starts with no folder open, so open the folder first. Development extensions do not appear in the Extensions sidebar; the extension activates when you open a C or C++ file.

Tests

npm test          # compile + unit tests + smoke test (all offline)
npm run typecheck # tsc --noEmit
npm run lint      # eslint
npm run format    # prettier --write
npm run unit      # pure-logic tests
npm run smoke     # activates the real extension against recorded responses
npm run smoke:live # same, but against the live Compiler Explorer API
npm run record    # re-record test/fixtures/ce.json from the live API
npm run perf      # micro-benchmarks for the store lookups

test/unit.js covers the pure helpers directly, notably the assembly-to-source mapping.

test/smoke.js stubs the VS Code API, activates the real extension and asserts on the mapping, hover contents, selection sync, auto-compile behaviour and state restoration across a simulated window reload.

Compiler Explorer is replayed from test/fixtures/ce.json, so the suite needs no network and cannot fail because someone else's server is down. The fixtures are real recorded responses: the C and C++ compiler lists plus every compilation the suite performs. Three modes, set by GODBOLT_CE or as the first argument to the script:

Mode What it does
replay (default) Serves every request from the fixtures. A miss fails with the request that was not recorded.
live Ignores the fixtures and calls the real API (npm run smoke:live).
record Calls the real API and merges the responses back into the fixtures (npm run record), so a partial run only ever adds to them.

Re-record when the suite grows a new request, or when you want to move to a newer compiler. Expect a diff: Compiler Explorer's compiler lists change as it adds and retires compilers, and the listing itself is part of what is recorded.

test/perf.js measures the two lookups that run the most, the per-file result lookup and the assembly-document lookup, and also times the scan-and-sort they replaced, so a regression back to scanning the whole store is obvious.

Building a VSIX

npm run package       # writes assembly-explorer-<version>.vsix
npm run install:local # installs that file, and trashes older installed copies

Then reload the VS Code window.

Installing does not replace the previous version, it sits beside it, so install:local clears the older copies out. A window that can see two of them may read its settings from one and run the code from the other, which is how a setting can be declared and still be rejected as unregistered.

How it works

  • src/core/: shared foundations, used by every other module.
    • services.ts: the process-wide singletons, populated once at activation.
    • config.ts: reads the godbolt.* settings and resolves the workspace/global target for writing them.
    • constants.ts: shared constants: language ids, known x86 instruction sets, the default compiler and flags.
    • types.ts: the shared types the modules pass around.
    • documents.ts: which documents can be compiled, their language, and names.
    • text.ts: text helpers: ANSI stripping, statement detection, snapshot checks.
    • warnings.ts: once-per-key user warnings, so background builds stay quiet.
  • src/compiler/: talking to Compiler Explorer and turning a document into a build.
    • client.ts: HTTP client for godbolt.org/api.
    • compilers.ts: the built-in fallback list used when the catalogue cannot be fetched.
    • compilerRegistry.ts: picks the compiler id that handles the file's language.
    • compilerSelection.ts: compiler choice: language detection, resolving the configured id, and the compiler picker.
    • compile.ts: the compile path: building a document and opening its panel.
    • compilerMode.ts: the one branch between Compiler Explorer and a local compiler.
    • localCompiler.ts: running a compiler from PATH and reading the .loc directives it emits back into a source mapping.
    • optimization.ts: the optimization dial: rewriting flags and the level picker.
  • src/asm/: the assembly side: the store, the godbolt-asm: documents and the asm↔source mapping.
    • resultStore.ts: holds compilation results and the asm↔source index.
    • serialize.ts: indexes, restores and serialises the lines and mapping a result holds.
    • asmUri.ts: the godbolt-asm: URI scheme and the keys that identify a document.
    • mapping.ts: resolves an assembly line (including labels) to its source.
    • documentProvider.ts: serves the read-only godbolt-asm: documents.
  • src/panel/: everything about the panel beside your code.
    • panelLayout.ts: which column holds the code and which holds the assembly.
    • panelFiles.ts: closing, renaming and adopting panels as files come and go.
    • syncHighlight.ts: keeps selection highlighting in step on both sides.
    • navigation.ts: jumping between source and assembly.
    • statusBar.ts: the one-line summary, its warnings and its failure state.
  • src/link/: the label index and everything you can hover or click in the listing.
    • hoverProvider.ts: both hover tooltips: the panel's, which names the producing source line, and the source's, which names what the line produced.
    • labels.ts: the label index, and the definition and reference answers built on it.
    • labelClicks.ts: the Ctrl+click and F12 jumps between a label and its uses.
  • src/state/: what runs in the background and what survives a window reload.
    • workspaceState.ts: what survives a window reload, and when it is written.
    • autoCompile.ts: rebuilds already-compiled files when they are saved.
  • src/extension.ts: activation and wiring only; the composition root.

Staying cheap

Two paths run the most: the per-file result lookup, since the auto-compiler asks "has this file been compiled?" whenever a file is saved, and the selection re-highlight. Both are cheap on purpose.

  • The store indexes results per source file, so a lookup costs one map hit instead of scanning and sorting every result it holds.
  • Highlights are rebuilt only when something they depend on changed. VS Code fires selection events even for a cursor that has not moved, and each rebuild costs a round trip per decorated editor.
  • Workspace state is written at most once per change, as a single already-encoded string, so saving does not re-encode every result it holds.

npm run perf prints the numbers. getBySource is more than an order of magnitude faster than the scan it replaced.

Compiler Explorer returns the assembly as a list of lines, each optionally tagged with the source line and column it came from. That mapping is what makes all of the above possible. Without it the assembly is just text.

Compilation results are kept in the workspace state, so assembly panels that VS Code restores after a reload come back with their contents instead of an empty placeholder. Files that changed while the window was closed are rebuilt quietly; the rest are not touched.

Two grammar files are contributed: syntaxes/x86asm.tmLanguage.json for x86-64, and a deliberately architecture-neutral syntaxes/asm-generic.tmLanguage.json used when the compiler targets anything else, since applying x86 rules to ARM or 6502 output colours the wrong things.

Compiler ids and languages

Compiler Explorer keeps a separate compiler id per language: g162 is the C++ build of gcc 16.2 and cg162 is the C build (vcpp_v19_latest_x64 pairs with vc_v19_latest_x64). The compile endpoint's lang field does not switch language. Handing a C++-only id a C file makes it compile the file as C++, which mangles names and rejects C that is not valid C++.

The extension therefore stores one compiler id and translates it to whichever variant matches the file you are compiling, matching the two on their display name. The status bar shows the id actually used, and the picker is filtered to the language of the current file.

Notes and limitations

  • Only C and C++ are wired up so far, although the API supports many more.
  • Compilation needs network access, or a compiler of your own. By default the work is done by Compiler Explorer; set godbolt.compilerMode to local to run a compiler from your PATH instead, which needs no network at all.
  • The source sent is the current editor buffer, including unsaved edits. That is what lets the panel keep up as you type.
  • Assembly is attributed by the compiler's own debug information, so under aggressive optimization a line may map to a surprising place, or nowhere.
  • Labels, .string data and directives carry no source information of their own. Selecting or hovering one resolves to the nearest instruction's source line, which is what makes clicking a function label in the assembly useful. The hover says when it is showing an approximation.
  • A compiler built for a different CPU (ARM, 6502, AVR and so on) returns assembly that is not x86. The picker separates those out, the extension warns once if you compile with one, and the listing gets the architecture-neutral grammar instead of the x86 one.
  • A build that a newer one replaces is cancelled, and the newer result wins. A very large file on a slow connection still holds a request open until it is replaced or times out after 30 seconds.
  • Panel names drop the source extension, so tes.c and tes.cpp in the same folder both want a tab called tes.asm. They stay separate documents and nothing is lost, but the tabs are hard to tell apart by name.
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft