fxos is an extended disassembler specifically used to reverse-engineer the OS, bootcode, and syscalls of CASIO fx and fx-CG series. It used to be part of the fxSDK. If you have a use for fxos, then be sure to also check the Planète Casio bible, which gathers most of the reverse-engineering knowledge and research of the community.
If you're familiar with IDA, Ghidra, or other industry-grade reverse-engineering tools, then fxos won't be able to compete. This is more of a scripting playground with very OS-centric features for me. Some of the things it can do that usual tools might not do directly include:
- Finding OS-specific data like bootcode/OS headers/footers, dates, versions
- Computing and checking checksums
- Analyzing syscall tables and consistently identifying syscall table entries
- (TODO) Comparing functions across OS versions to find changes
On the other hand, there are no call graph, cross-references, or function type analysis (yet). I have plans for a simple abstract interpreter to bridge some of the gap between pure disassembly and decompilation.
fxos runs on Linux and should build successfully on MacOS. If there are compatibility issues with your favorite system, let me know.
fxos is mainly standalone; to build, you will need the following tools. The versions indicated are the ones I use, and clearly not the minimum requirements.
- g++ (9.2.0)
- flex (2.6.4)
- CMake (3.15) and make (eg. 4.2.1)
The only real configure option is the install path. CMake's default is
/usr/local; a viable alternative is
% cmake -B build # -DCMAKE_INSTALL_PREFIX=$HOME/.local % make -C build -j$(nproc) install
Setting up the library
fxos works with a library of files ranging from OS binaries to assembler
instruction tables to scripts. The library is formed of one or more folders
defined in the
FXOS_PATH environment variable.
Folders in the path serve two purposes:
fxosrcfile at the root of a folder is executed at startup.
- All paths are interpreted relative to the
Unless you want to redo the research by yourself, I suggest using shared
community data from the fxdoc repository. New folders
could be created easily on the same model; read the
fxosrc script to see how
it is structured.
fxos has a command-line interface kind of like rizin. Type
? to get a list
of commands, and any command name followed by
? to get help on a particular
The dot command
. is used to run a script, which is a file with a series of
fxos commands. This is used at startup to run every
fxosrc script found in
- Identifiers/names are C identifiers but dots (
.) are allowed.
- Usual decimal, hex (
0x), binary (
- Syscalls are identified with
%<hex>, such as
$is the current position in the selected virtual space.
- Commands accept arithmetic but only within parentheses; you can write
e (1+2)but not
- Ranges can be specified as
- Paths should use quotes:
"/os/fx/3.10/3.10.bin". Only identifiers/names can be written without quotes in commands.
- Commands can be chained with
- Anything from a
#to end of line is a comment.
A virtual space is an emulation of the calculator's virtual memory. Usually
there is one for each OS being studied. Each virtual space has a number of
bindings, which is a mapping from a virtual address to a file (usually a dump
of the calculator's ROM or RAM). Use
vl to show the virtual spaces and their
bindings. The name of the current virtual space is shown in the prompt along
with the current position, for instance:
cg_3.60 @ 0x80000000>
A new empty space can be created with
vc, and then files can be mapped
vm. File paths are interpreted relative to
even if they start with
vs command is used to switch between different virtual spaces.
Each virtual space can have symbols defined, which are names associated to
either addresses or syscall numbers.
ms will define a new symbol at an
explicit address or syscall entry (which is kept symbolic, ie. it will work
across different OS versions) and
is lists all symbols for a virtual space.
Besides fxos scripts and the actual binary files being used, there is currently
only one other type of data file: assembly instruction listings. See
asm/sh3.txt for an explanation of the syntax; essentially each line has:
- The opcode pattern, a 16-character string using
- A mnemonic.
- Zero, one or two arguments among a finite set.
Here is an excerpt from the SH-4A extensions table.
type: assembly name: sh-4a-extensions --- 0000nnnn01110011 movco.l r0, @rn 0000mmmm01100011 movli.l @rm, r0 0100mmmm10101001 movua.l @rm, r0 0100mmmm11101001 movua.l @rm+, r0 0000nnnn11000011 movca.l r0, @rn
Internally, fxos keeps a table with all 65536 opcodes and fills it with instances of instructions described in assembly tables.
(TODO) Disassembly listings are intended to be produced and maintained by fxos
while still being edited by hand. In order for this to work properly, manual
edits should only use
#-comments, either at the start of a line or with a
symbol followed by a space (to distinguish from constants like
# Set SR.BL = 1 (block interrupt) and SR.IMASK = 0x00*0 (error ?) 4143a: 04 02 stc sr,r4 # get SR register. 4143c: e5 10 mov #16,r5 # r5 = 0x00000010
Contributing issues, results, and code
Any bug reports, issues and improvement suggestions are welcome. See the bug tracker.
If you have reverse-engineering results so share, the best place to do so is on the Planète Casio bible. Ping me or Breizh_craft on the Planète Casio shoutbox to have an SSH access set up for you.
PRs are also most welcome. Before submitting code, make sure to run
clang-format to avoid any editor/configuration mishaps:
% clang-format -i include/**/*.h lib/**/*.cpp shell/**/*.cpp