GameGuardian has a built-in disassembler / assembler.
It allows you to disassemble the binary chunk Lua 5.2 into assembler listing, make changes and assemble the listing back into binary chunk.
The assembler is quite simple and based on the binary chunk Lua 5.2 format.
For more information on Lua 5.2 virtual machine commands, see the Internet resources. For example:
VM Lua 5.2 commands are very similar to VM Lua 5.1 commands, so it’s useful to learn
"A No-Frills Introduction to Lua 5.1 VM Instructions" by Kein-Hong Man:
http://luaforge.net/docman/83/98/ANoFrillsIntroToLua51VMInstructions.pdf
GameGuardian implements Lua 5.3 almost in full, with some details: Lua in GameGuardian
In particular, the opcodes IDIV, BNOT, BAND, BOR, BXOR, SHL
and SHR
were added. At the same time, binary compatibility with Lua 5.2 is preserved, which makes it possible to run valid binary scripts from Lua 5.2 in GameGuardian.
The assembler is very simple and contains three types of statements:
.numparams
.SETTABUP
.Assembler is not designed to write code from scratch. Only for small edits of pre-disassembled code.
Therefore, there will not be a full description of all statements and opcodes.
If you need to get statements for specific Lua code in order to use them, write a Lua file and disassemble it.
The notation of part of the opcodes has been changed to reflect the registers that they affect, and to simplify the understanding of listing. For example,
Some opcodes are minimized. For example,
Will be presented as
In almost all places where constant indexes should be, the constants themselves are used instead. For example,
The same goes for prototypes that are assigned automatic increment names:
Code jumps are also implemented using labels:
If you parse chunk with invalid code, then some of the indexes of constants, prototypes, jump offsets and operators may not be valid.
In this case, you will see constants as CONST[A]
, jump offsets as GOTO[A]
, prototypes as FUNC[A]
, and opcodes as OP[A] 0xB
.
The number in the square brackets will indicate the index used.
After the opcode, the entire command will be indicated in hexadecimal.
These statements, when assembling, will be assembled back into the code that they were originally, as far as possible.
This allows you to disassemble and assemble even chunks with invalid code and unknown opcodes.
Statements are case sensitive. The order of statements is important. Examine the disassembled files to see the correct case and order of statements.
Prototype and labels can be arbitrary. When disassembling, they are generated with numbers, but you can change them to something meaningful.
The format for writing constants is the same as in Lua. An exception for strings that cannot be written in notation with square brackets: [[text]]
.
Compatibility between assembly files between different versions of GameGuardian is not guaranteed. You must always disassemble and assemble on the same version of GameGuardian, otherwise there may be various kinds of problems.
Chunk, after assembly and disassembly may change. Don't rely on it being the same byte-by-byte.
Additional data after the end of the chunk is stored in a separate .tail
file, which is added to the end of the chunk during assembly.