You have a Visual Basic executable and you need to see something inside it. Two families of tools are available, and they do not do the same job: one shows you instructions, the other tries to reconstruct intent. Picking the wrong one costs hours.
What a disassembler does
A disassembler translates the file's bytes into readable instructions. The mapping is direct: each sequence of bytes corresponds to exactly one instruction. The operation is therefore faithful and lossless — disassembling a valid binary always succeeds.
What it does not do is guess. It gives you machine instructions, not variable names, not control structures, not the author's business logic. Reading it remains entirely your job.
What a decompiler does
A decompiler goes further: it attempts to reconstitute source code from those same instructions. That means recognising patterns, inferring types, and finding loops where there are only jumps.
So it is a partial and fallible operation. What the compiler removed — local variable names, comments, folded constants — does not come back. In exchange, what does come back is directly readable.
Disassembler
Output: instructions. Always complete, never wrong.
You read what the machine executes. Working out the meaning is up to you.
Decompiler
Output: reconstructed source. Partial, sometimes approximate.
You read an intent. Checking that it is accurate is up to you.
On a Visual Basic binary the question arises twice
Visual Basic 5 and 6 produce two kinds of executable, and the gap between disassembly and decompilation is not the same in each case.
In P-Code, the bytecode is high level: its instructions correspond to typed language operations. The disassembly is already almost readable, and decompilation is a largely mechanical extension of it.
In native code, the binary is x86 produced by the Visual C++ optimising compiler. Disassembly gives you machine instructions; going from there to Visual Basic is work of a different order. The detail is covered in P-Code or native code: what your binary gives back.
Concretely, here is the difference on a single-line assignment. A native binary does not contain the assignment: it contains the runtime calls that carry it out.
push offset aHello ; literal preserved
mov eax, [ebp-18h]
push eax
call __vbaObjSet ; MSVBVM60.DLL export
mov edx, eax
lea ecx, [ebp-4]
call __vbaStrCopy
...
call __vbaFreeStr
Private Sub Command1_Click()
Text1.Text = "Hello"
End Sub
Both outputs describe the same code. The first is exact and costly to read; the second is reconstructed and takes one glance. Note that the procedure name and the control name came back: those are things the format preserves, whatever the compilation mode.
Which one do you need?
It depends entirely on what you want to obtain, and the answer is not always "a decompiler".
And in practice, tools often do both
The distinction is clean in theory, less so in products. Most Visual Basic tools embed a disassembler and lay a reconstruction layer on top: you get both views in the same window and switch between them whenever the reconstruction becomes doubtful.
That is the right way to work: read the reconstructed code to move fast, go back to the disassembly when a passage does not stand up. The available tools, their approach and their status are listed in a history of Visual Basic decompilers.
VBReFormer publishes the actual coverage of its reconstruction, function by function and instruction by instruction, with the denominators: 1,153 documented correspondences. And the free edition will tell you within seconds which format your binary belongs to and what it holds — the first question to settle before choosing a tool.