This is ldis, a disassembler for lua binary files.  It works for
binaries compiled by the 5.4 and 5.5 branches of lua, discovering the
compiler used to compile into the opcodes, and delivers the assembly
opcodes and data in an easy to read form.  It is similar to the output
produced by luac -l -l, but of course, does not need the lua source
code around to be able to recover the opcodes, constants, upvals and
local variables.

In general, there is little lua consistency between major releases. 
Bytecodes are numbered differently, and so there is little
consistency, and compiled programs usually need to be recompiled. 
This disassembler tries to bridge that gap, by being able to
disassemble both 5.4 and 5.5-compiled binaries.


Examples:

A standard run of the disassembler on the "hello world" binary shows:

	% ./ldis hello.out

	main <hello.lua:0,0> (5 instructions)
	0+ params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
		1       [1]     VARARGPREP      0
		2       [1]     GETTABUP        0 0 0   ; _ENV "print"
		3       [1]     LOADK           1 1
		4       [1]     CALL            0 2 1
		5       [1]     RETURN          0 1 1
	Constants: 2
	1 4 "print"
	2 4 "hello world"
	Upvalues: 1
	1: instack 1, index 0, kind 0
	Closures: 0
	Lineinfos: 5
	[0]     01
	[1]     00
	[2]     00
	[3]     00
	[4]     00
	Abslineinfo: 0
	Local vars: 0
	Upvalues: 1
	Upval 1: '_ENV'

A verbose listing of the same binary, but compiled by lua 5.5, shows:

	% ./ldis -v hello55.out

	0.      1b 4c 75 61 55 00 19 93 0d 0a 1a 0a 04 88 a9 ff
	16.     ff 04 78 56 34 12 08 88 a9 ff ff ff ff ff ff 08
	32.     00 00 00 00 00 28 77 c0 01 00 00 00 01 02 05 00
	48.     53 00 00 00 0b 00 00 00 83 80 00 00 44 00 02 01
	64.     46 00 01 01 02 04 06 70 72 69 6e 74 00 04 0c 68
	80.     65 6c 6c 6f 20 77 6f 72 6c 64 00 01 01 00 00 00
	96.     0b 40 68 65 6c 6c 6f 2e 6c 75 61 00 05 01 00 00
	112.    00 00 00 00 01 05 5f 45 4e 56 00

	File header signature: 1b 4c 75 61
	Lua version: 55
	Lua format: 00
	Lua data: 19 93 0d 0a 1a 0a
	Instruction size: 04
	Integer size: 08
	Number size: 08
	Lua int: 88 a9 ff ff ff ff ff ff
	Lua num/float: 00 00 00 00 00 28 77 c0
	Upvalue size: 01

	=== func 0: Reading function info at offset 41
	=== func 0: Linefrom at offset 41
	=== func 0: Instructions at offset 48
	=== func 0: Constants at offset 68
	=== func 0: Upvalues at offset 91
	=== func 0: Closures at offset 95
	=== func 0: Filename at offset 96
	=== func 0: Lineinfo at offset 108
	=== func 0: Abslineinfo at offset 114
	=== func 0: Locals at offset 115
	=== func 0: Upval info at offset 116
	=== func 0: End of 5.5 function at offset 123

	Filename: 'hello.lua' (10 bytes)
	main <hello.lua:0,0> (5 instructions)
	0+ params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
		1       [1]     VARARGPREP      0
	[0] 48:         VARARGPREP      00 00 00 53
		2       [1]     GETTABUP        0 0 0   ; _ENV "print"
	[0] 52:         GETTABUP        00 00 00 0b
		3       [1]     LOADK           1 1
	[0] 56:         LOADK   00 00 80 03
		4       [1]     CALL            0 2 1
	[0] 60:         CALL    01 02 00 44
		5       [1]     RETURN          0 1 1
	[0] 64:         RETURN  01 01 00 46
	Constants: 2
	1 4 "print"
	2 4 "hello world"
	Upvalues: 1
	1: instack 1, index 0, kind 0
	Closures: 0
	Lineinfos: 5
	[0]     01
	[1]     00
	[2]     00
	[3]     00
	[4]     00
	Abslineinfo: 0
	Local vars: 0
	Upvalues: 1
	Upval 1: '_ENV'
	% 

Notes

1.  The RETURN0 and RETURN1 instructions in the binary include some
trailing operands which are undocumented.  These instructions will be
disassembled with those extra operands dumped in hex after the operand
name.

2.  Lua bytecodes for the instructions vary with each Lua release,
although the 5.3 to 5.4 transition was much more intrusive than the
5.4 to 5.5 transition.  The disassembler knows which version of the
compiler was used to compile the bytecodes, and will dump the correct
instructions appropriately.  Only Lua versions 5.4 and 5.5 are
supported at the time of writing (August 2026).

In addition, 5.5 introduces a new instruction addressing mode, and
a new way of encoding integers in the compiled output.

3.  The disassembler has been tested with a lot of programs, some of
which are included here for illustration purposes.  A whole test of
every available instruction or addressing mode has yet to be made.

4.  The luac compiler has a switch to disable debugging output, and
the disassembler works well with the output from that compiler.
