LogoLogo
IDA 8.4
IDA 8.4
  • Welcome to Hex-Rays docs
  • User Guide
    • User Interface
      • Menu Bar
        • File
          • Load file
          • Script File
          • Script command
          • Produce output files
          • Invoke OS Shell
          • Take database snapshot
          • Save database
          • Save database as...
          • Abort IDA
          • Exit IDA
        • Edit
          • Export data
          • Undo an action
          • Redo an action
          • Clear undo history
          • Disable undo
          • Convert to instruction
          • Convert to data
          • Convert to string literal
          • Convert to array
          • Undefine a byte
          • Give Name to the Location
          • Operand types
            • Offset
            • Number
            • Perform en masse operation
            • Convert operand to character
            • Convert operand to segment
            • Complex Offset Expression
            • Convert operand to symbolic constant (enum)
            • Convert operand to stack variable
            • Change operand sign
            • Bitwise negate operand
            • User-defined operand
            • Set operand type
          • Comments
          • Functions
          • Structures
            • Enums
          • Segments
          • Patch core
          • Other
            • Rename Any Address
          • Plugins
        • Jump
          • Center current line in window
          • Problems List
        • Search
          • REGULAR EXPRESSION SYNTAX SUMMARY
        • View
          • Open subviews
          • Graphs
          • Message Window
          • Arrows window
          • Database snapshot manager
          • Highlighting identifiers
          • Browser options
          • Lumina options
          • Assembler level and C level types
          • C++ type details
          • Bookmarks window
          • Calculator
          • View segment registers
          • View Internal Flags
          • Hide
          • Unhide
          • Del hidden range
          • Hide all items
          • Unhide all items
          • Setup hidden items
        • Debugger
          • Debugger window
          • Process Control
            • Start process
            • Process options
            • Pause process
            • Terminate process
            • Step into
            • Step over
            • Run to cursor
            • Run until return
            • Attach to process
            • Detach from process
            • Set current ip
            • Show application screen
          • Breakpoints
          • Watches
          • Tracing
          • Source code view
            • Watch view (source level)
          • Process Memory
            • Take memory snapshot
            • Manual memory regions
            • Refresh memory
          • Thread list
          • Module list
          • Stack trace
          • Exceptions
          • Debugger options
          • Switch debugger
        • Lumina
        • Options
          • Low & High Suspicious Operand Limits
        • Windows
          • Rename a stack variable
          • Miscellanous Options
          • Environment variables
          • Reset Hidden Messages
          • Various dialog help messages
        • List of all menu options
      • Desktops
      • Command line
      • How To Use List Viewers in IDA
      • Licenses
        • Apache License for Ghidra
        • Apache License for LLVM
        • Common Public License Version 1.0
        • APPLE PUBLIC SOURCE LICENSE
        • PCRE2 LICENCE
        • GNU Lesser General Public License v2.1 for libiberty
      • Database conversion from idb to i64
    • Disassembler
      • Interactivity
      • Background Analysis
      • Graph view
        • Graphing tutorial
      • Proximity view
      • Navigation
        • Anchor
        • How to Enter a Segment Value
        • How to Enter a Number
        • How to Enter an Identifier
        • How to enter text
        • How to Enter an Address
      • Disassembly Gallery
        • Philips 51XA-G3
        • 6502 and 65C02 Disassembler
        • 6301, 6303, 6800, 6801 and 6803 Disassembler
        • 68040, Amiga
        • 6805 Disassembler
        • 6808 Disassembler
        • 6809 OS9 Flex Disassembler
        • 6809 Disassembler
        • 6811 Disassembler
        • 68HC12 Disassembler
        • 68HC16 Disassembler
        • 68k Amiga Disassembler
        • 68k Mac OS
        • 68k Palm Pilot
        • Unix COFF
        • NEC 78k0 and 78k0s Processor
        • 80196 Processor
        • 8051 Disassembler
        • Analog Devices 218x.
        • Alpha Processor – NT COFF
        • Alpha Processor – Unix ELF
        • Android ARM Executables (.elf)
        • ARC Processor
        • ARM Processor EPOC App
        • ARM Processor EPOC PE File
        • ARM Processor EPOC ROMFile
        • EPOC SIS File Handler
        • ARM Processor iOS (iPhone): Unlock
        • ARM Processor iOS (iPhone): Objective-C metadata
        • ARM Processor iOS (iPhone): Objective-C Instance variables
        • ARM Processor iOS (iPhone): Parameter Identification & Tracking (PIT)
        • ARM Processor iOS (iPhone): Start
        • ARM Processor iOS (iPhone): Switch statements
        • ARM Processor iOS (iPhone): C++ signatures
        • ARM Processor iOS (iPhone): Write
        • ARM Processor: Linux ELF
        • ARM Processor: AOF SDK
        • ARM Processor: Windows CE COFF Format
        • ARM Processor: Windows CE PE Format
        • ATMEL AVR Disassembler
        • C166 Processor
        • C166 Processor with ELF file
        • Rockwell C39
        • Microsoft .NET CLI Disassembler. VisualBasic library
        • CR16
        • Android Dalvik Executables (.dex)
        • Microsoft .NET CLI Disassembler
        • DSP56K
        • Fujitsu FR (.elf)
        • Gameboy
        • H8 300: COFF FILE Format
        • H8 300s: COFF FILE Format
        • H8 500
        • HPPA Risc Processor: HP-UX SOM
        • i51
        • i860
        • Intel i960
        • Intel IA-64 (Itanium)
        • Java Bytecode
        • Angstrem KR 1878
        • Renesas/Hitachi M16C
        • Renesas/Hitachi M32R
        • M740
        • M7700
        • M7900
        • MIPS Processor: Nintendo N64
        • MIPS R5900 Processor : Sony bin
        • MIPS Processor: Sony ELF
        • MIPS Processor: Sony PSX
        • MIPS Processor: Sony PSX
        • MIPS Processor: Unix COFF File Format
        • MIPS Processor: Unix ELF File Format
        • MIPS Processor: Windows CE PE File Format
        • MIPS Processor: Windows CE PE2 File Format
        • Panasonic MN102
        • Atmel OAK DSP
        • 80×86 Architecture: DOS Extender
        • 80×86 Architecture: Watcom Runtime
        • 80×86 Architecture: Geos APP
        • 80×86 Architecture: Geos DRV
        • 80×86 Architecture: Geos LIB
        • 80×86 Architecture: GNU COFF Format
        • 80×86 Architecture: OS/2 Linear Executable Format
        • 80×86 Architecture: Netware NLM
        • 80×86 Architecture: QNX Executable
        • 80×86 Architecture: Watcom Runtime
        • 80×86 Architecture: Windows OMF
        • 80×86 Architecture: Windows Portable Executable Format
        • 80×86 Architecture: Windows Virtual Device Driver
        • 80×86 Architecture: Windows 16 bits DLL
        • X-Box Disassembler
        • PDP 11: SAV File
        • PIC
        • PIC 12xx
        • Power PC AIF ECOFF file Format
        • Power PC Linux ELF
        • Mac OS PEF File
        • Mac OS X File
        • Windows NT PE File
        • Hitachi SH-1 Processor
        • Hitachi SH-3 Processor: Windows CE COFF format
        • Hitachi SH-3 Processor: Windows CE PE format
        • Hitachi SH-4 Processor: ELF File Format
        • Hitachi SH-4 Processor: Windows CE PE File Format
        • Super Nintendo Entertainement System (SNES)
        • SPARC Solaris COFF
        • SPARC Solaris ELF
        • SPARC Sun ELF
        • SPARC Sun ELF SO
        • ST 20C4
        • ST 7
        • ST 9
        • Toshiba TLCS 900
        • TMS 320c2 COFF
        • TMS 320c5
        • TMS 320c54
        • TMS 320c6 COFF File Format
        • TRICORE
        • SunPlus unSP
        • NEC V850
        • Z180 COFF File Format
        • Z380 COFF File Format
        • Z8
        • Z80
      • Supported processors
      • Supported file formats
        • Windmp file loader
      • Bitfields
        • Bit Fields tutorial
      • Structures tutorial
      • Union tutorial
      • Variable length structures tutorial
      • Data types, operands and constructs
      • Packed executables
    • Decompiler
      • Prerequisites
      • Quick primer
      • Exception handler
      • Introduction to Decompilation vs. Disassembly
        • Comparisons of ARM disassembly and decompilation
        • Comparisons of PowerPC disassembly and decompilation
        • Comparisons of MIPS disassembly and decompilation
        • Hex-Rays v7.4 vs. v7.3 Decompiler Comparison Page
        • Hex-Rays v7.3 vs. v7.2 Decompiler Comparison Page
        • Hex-Rays v7.2 vs. v7.1 Decompiler Comparison Page
      • Interactive operation
        • Rename
        • Set type
        • Set number representation
        • Edit indented comment
        • Edit block comment
        • Hide/unhide C statements
        • Split/unsplit expression
        • Force call type
        • Set call type
        • Add/del variadic arguments
        • Del function argument
        • Add/delete function return type
        • Jump to cross reference
        • Jump to cross reference globally
        • Generate HTML file
        • Mark/unmark as decompiled
        • Copy to assembly
        • Show/hide casts
        • Reset pointer type
        • Convert to struct *
        • Create new struct type
        • Split variable
        • Select union field
        • Jump to paired paren
        • Collapse/uncollapse item
        • Map to another variable
      • Batch operation
      • Configuration
      • Third party plugins
      • Floating point support
      • Support for intrinsic functions
      • Overlapped variables
      • gooMBA
      • Failures and troubleshooting
      • FAQ
      • Limitations
      • Tips and tricks
    • Debugger
      • Instant debugger
      • Remote debugging
        • Remote iOS Debugger
        • Android debugger
        • Dalvik debugger
        • Remote GDB Debugger
          • Remote GDB Debugger options
          • Debugging with gdbserver
          • Debugging with VMWare
          • Debugging with OpenOCD
          • Debugging with QEMU
          • External programs and GDB Debugger
          • Debugging code snippets with QEMU
        • PIN debugger
          • Building the PIN tool
          • Connecting a remote PIN tool instance from IDA
          • PIN support for MacOSX
        • Replayer debugger
        • Bochs debugger
          • Bochs Disk Image operation mode
          • Bochs IDB operation mode
          • Bochs PE operation mode
          • Bochs debugger FAQ
      • Local debugging
        • WinDbg Debugger
        • Linux debugger
        • Intel/ARM macOS debugger
      • Debugger tutorials
        • Debugging Dalvik Programs
        • IDA Win32 Local Debugging
        • IDA Linux Local Debugging
        • IDA Win32 to Win32 Debugging
        • IDA Win32 to Win64 Debugging
        • Debugging Mac OSX Applications with IDA Pro
        • Debugging iOS Applications with IDA Pro
        • Debugging Linux Applications locally
        • Debugging Linux/Windows Applications with PIN Tracer module
        • Debugging Windows Applications with IDA Bochs Plugin
        • Debugging Windows Applications with IDA WinDbg Plugin
        • Using the Bochs debugger plugin in Linux
        • Debugging Windows Kernel with VMWare and IDA WinDbg Plugin
        • Debugging Linux Kernel under VMWare using IDA GDB debugger
        • Windows Debugger Hub
        • Linux Debugger
        • Debugging a Windows executable locally and remotely
        • Debugging the XNU Kernel with IDA Pro
        • Remote debugging with IDA Pro
        • IDA Scriptable Debugger: overview
          • IDA Scriptable Debugger: scriptability
        • Debugging code snippets with QEMU debugger (a la IDA Bochs debugger)
        • Trace Replayer and managing traces
        • Using IDA Pro's tracing features
        • Working with PIN
        • Appcall
    • Signatures
      • FLIRT
        • IDA F.L.I.R.T. Technology: In-Depth
        • Supported Compilers
          • Turbo Pascal
          • Delphi
      • Makesig
    • Type Libraries
      • IDAClang
      • TILIB
    • Configuration
      • Configuration files
      • Command line switches
      • Keyboard macros
    • Teams
      • IDA Teams Licenses
      • Diffing and Merging Databases with IDA Teams
      • Teams lc command reference manual
      • hv command reference manual
      • Hex-Rays Vault’s visual client user manual
    • Lumina
      • lc command reference manual
    • Plugins
      • Open Plugin Architecture
      • Plugin options
      • Plugins Shipped with IDA
        • Swift plugin
        • Golang plugin
        • Rust plugin
        • picture_search
        • Objective-C Analysis Plugin
        • DYLD Shared Cache Utils
      • Plugin Contest
      • How to write your own plugin?
    • Helper Tools
  • Developer Guide
    • C++ SDK
      • C++ SDK reference
      • Using the Decompiler SDK: Decompiler Plug-In
    • IDAPython
      • IDAPython API Reference
    • IDC
      • Core concepts
        • Expressions
        • Statements
        • Functions
        • Variables
        • Constants
        • Exceptions
        • Classes
        • Predefined symbols
        • loader_input_t class
        • Slices
      • IDC API Reference
        • Index of debugger related IDC functions
        • Alphabetical list of IDC functions
          • set_selector
          • enable_tracing
          • get_prev_fixup_ea
          • del_segm
          • get_bmask_cmt
          • end_type_updating
          • Find
          • toggle_bnot
          • patch_byte
          • get_module_info
          • set_member_name
          • create_float
          • del_struc_member
          • read_dbg_memory
          • get_enum_width
          • getn_thread_name
          • del_struc
          • filelength
          • set_manual_insn
          • is_value...() functions
          • get_ip_val
          • del_extra_cmt
          • create_insn
          • op_offset_high16
          • get_cmt
          • expand_struc
          • get_idb_path
          • set_frame_size
          • get_file_ext
          • has_value
          • readshort
          • sanitize_file_name
          • get_member_flag
          • create_struct
          • ARM specific
          • Disk Write Error
          • set_enum_member_cmt
          • rename
          • set_ida_state
          • get_member_size
          • msg
          • qbasename
          • get_enum_member_enum
          • auto_mark_range
          • plan_to_apply_idasgn
          • set_named_type
          • op_offset
          • rename_entry
          • strlen
          • get_extra_cmt
          • get_enum_flag
          • fgetc
          • Internal Error
          • op_stkvar
          • get_last_index
          • get_field_ea
          • get_last_struc_idx
          • How to use the help subsystem
          • get_struc_id
          • select_thread
          • create_array
          • get_struc_cmt
          • set_array_string
          • set_func_attr
          • set_storage_type
          • get_struc_size
          • demangle_name
          • get_next_fixup_ea
          • get_next_bmask
          • delattr
          • gen_simple_call_chart
          • patch_qword
          • get_enum_name
          • loader_input_t.getc
          • get_first_struc_idx
          • get_debugger_event_cond
          • read_dbg_qword
          • define_local_var
          • generate_disasm_line
          • add_idc_hotkey
          • tolower
          • del_selector
          • set_debugger_event_cond
          • get_imagebase
          • gen_file
          • get_entry
          • find_custom_data_format
          • get_debug_name_ea
          • add_default_til
          • set_func_end
          • exit_process
          • delete_array
          • xtol
          • get_exception_code
          • detach_process
          • set_enum_cmt
          • get_wide_word
          • put_bookmark
          • is_loaded
          • add_enum_member
          • parse_decls
          • readstr
          • get_entry_qty
          • ord
          • sprintf
          • get_root_filename
          • get_enum_member_cmt
          • create_word
          • set_func_flags
          • loader_input_t.tell
          • create_align
          • read_dbg_dword
          • get_struc_idx
          • next_addr
          • get_bytes
          • batch
          • start_process
          • Cannot Create File
          • process_config_line
          • del_user_info
          • qmakefile
          • set_struc_name
          • print_decls
          • create_custom_data
          • del_enum_member
          • format_cdata
          • get_fixup_target_sel
          • get_item_size
          • loader_input_t.gets
          • get_last_bmask
          • Step Tracing Options
          • get_enum_idx
          • selector_by_name
          • Already recording a macro for...
          • get_enum_cmt
          • next_not_tail
          • prev_head
          • set_color
          • set_numbered_type
          • get_member_name
          • auto_wait
          • get_enum_member_bmask
          • fseek
          • get_segm_start
          • attach_process
          • Trace file functions
          • get_enum_member_value
          • op_stroff
          • get_next_offset
          • set_processor_type
          • get_bookmark_desc
          • Entering String for Search
          • create_data
          • lastattr
          • get_operand_value
          • collect_stack_trace
          • toupper
          • get_fixup_target_dis
          • set_cmt
          • add_entry
          • set_segm_addressing
          • qmake_full_path
          • get_source_linnum
          • fputc
          • resume_thread
          • get_func_attr
          • get_first_enum_member
          • add_sourcefile
          • get_first_bmask
          • read_selection_start
          • hasattr
          • get_member_cmt
          • gen_flow_graph
          • get_array_element
          • get_tinfo
          • loader_input_t
          • tinfo_errstr
          • TRUNC
          • add_segm_ex
          • Not enough memory available to complete operation.
          • Local types information and manipulation helpers
          • set_source_linnum
          • get_next_enum_member
          • loader_input_t.readbytes
          • set_array_params
          • jumpto
          • get_bookmark
          • set_enum_bf
          • prev_not_tail
          • toggle_sign
          • loader_input_t.size
          • Trace events functions
          • get_func_flags
          • get_gotea
          • Bad BIOS & DOS Comments Base
          • set_segm_attr
          • get_item_head
          • set_default_sreg_value
          • print_insn_mnem
          • set_member_cmt
          • get_ordinal_qty
          • set_target_assembler
          • add_user_stkpnt
          • set_local_type
          • Hidden ranges
          • del_items
          • compile_idc_text
          • Dalvik debugger extension functions
          • byte_value
          • create_dword
          • is_code
          • del_func
          • get_enum
          • make_array
          • rotate_left
          • recalc_spd
          • search_path
          • CommonBits
          • get_processor_name
          • set_func_cmt
          • get_prev_bmask
          • Hashes
          • split_sreg_range
          • process_ui_action
          • set_fixup
          • get_fixup_target_type
          • create_oword
          • get_flags
          • get_func_name
          • create_strlit
          • add_struc
          • atol
          • load_debugger
          • mkdir
          • set_struc_idx
          • sizeof
          • get_enum_member_by_name
          • save_database
          • guess_type
          • get_segm_name
          • print_operand
          • qisabspath
          • get_member_qty
          • set_struc_cmt
          • get_fixup_target_flags
          • idadir
          • object.retrieve
          • add_auto_stkpnt
          • get_numbered_type_name
          • get_enum_member_name
          • get_next_index
          • prev_addr
          • get_name_ea
          • get_sp_delta
          • set_bmask_cmt
          • get_struc_qty
          • readlong
          • set_segm_name
          • get_prev_offset
          • set_segm_alignment
          • get_strlit_contents
          • forget_exception
          • get_item_end
          • add_func
          • get_name
          • Asks
          • get_spd
          • Debugger: control
          • get_wide_byte
          • plan_and_wait
          • set_enum_flag
          • RunPythonStatement
          • del_sourcefile
          • get_prev_struc_idx
          • find_selector
          • get_frame_regs_size
          • op_num
          • define_exception
          • create_double
          • create_byte
          • read_selection_end
          • Disk Positioning Error
          • OpTypes
          • op_plain_offset
          • move_segm
          • get_member_id
          • set_segm_combination
          • get_current_thread
          • trim
          • Debugger: options
          • getn_thread
          • get_frame_id
          • typeinfo.print
          • to_ea
          • rebase_program
          • add_struc_member
          • get_exception_qty
          • get_first_index
          • import_type
          • set_segm_type
          • find_custom_data_type
          • get_next_seg
          • find_func_end
          • get_next_struc_idx
          • get_last_enum_member
          • getattr
          • get_frame_size
          • get_screen_ea
          • loader_input_t.read
          • Bad Macro
          • set_reg_value
          • Debugger: modules
          • create_pack_real
          • writestr
          • exec_idc
          • get_enum_size
          • set_enum_name
          • create_tbyte
          • sel2para
          • atoa
          • loader_input_t.close
          • add_enum
          • ltoa
          • set_enum_idx
          • substr
          • del_idc_hotkey
          • Breakpoint handling functions
          • loader_input_t.seek
          • cleanup_appcall
          • object.store
          • get_type
          • qexit
          • get_debug_name
          • get_array_id
          • Can't Open File
          • suspend_process
          • process_config_directive
          • get_entry_name
          • get_last_member
          • get_struc_name
          • clear_selection
          • fclose
          • firstattr
          • How to move/resize windows
          • create_yword
          • dbg_appcall
          • get_qword
          • patch_dword
          • begin_type_updating
          • read_dbg_byte
          • get_fpnum
          • qsleep
          • get_first_member
          • get_nsec_stamp
          • del_stkpnt
          • eval
          • savefile
          • eval_python
          • Xrefs
          • strstr
          • writeshort
          • get_sreg
          • get_segm_end
          • get_func_off_str
          • set_func_start
          • del_array_element
          • get_full_flags
          • set_exception_flags
          • rename_array
          • get_frame_args_size
          • op_flt
          • get_min_spd_ea
          • apply_type
          • get_prev_index
          • loadfile
          • retrieve_input_file_md5
          • get_wide_dword
          • patch_dbg_byte
          • Functions provided by the WinDbg debugger
          • get_original_byte
          • get_member_strid
          • call_system
          • writelong
          • get_thread_qty
          • nextattr
          • send_dbg_command
          • get_first_seg
          • get_processes
          • patch_word
          • get_manual_insn
          • ftell
          • get_entry_ordinal
          • set_array_long
          • delete_all_segments
          • TO_LONG
          • Function chunk related functions
          • Debugger: events
          • get_prev_func
          • op_seg
          • validate_idb_names
          • fprintf
          • fopen
          • strfill
          • del_fixup
          • get_bmask_name
          • Disk Read Error
          • inf_attr
          • is_bf
          • read_dbg_word
          • qdirname
          • get_segm_attr
          • func_contains
          • get_enum_qty
          • del_source_linnum
          • get_sourcefile
          • clr_database_flag
          • bTree Error
          • set_name
          • Refresh Screen
          • op_enum
          • getn_enum
          • get_db_byte
          • setattr
          • get_forced_operand
          • op_bin
          • Functions provided by the replayer debugger
          • prevattr
          • update_extra_cmt
          • get_str_type
          • op_man
          • choose_func
          • set_bmask_name
          • get_curline
          • decode_insn
          • set_segment_bounds
          • get_struc_by_idx
          • set_segm_class
          • write_dbg_memory
          • get_exception_name
          • get_enum_member
          • is_mapped
          • del_enum
          • get_frame_lvar_size
          • get_operand_type
          • set_root_filename
          • compile_idc_file
          • typeinfo.size
          • get_local_tinfo
          • get_fixup_target_off
          • is_union
          • unlink
          • get_segm_by_sel
          • set_enum_width
          • take_memory_snapshot
          • exec_python
          • get_next_func
          • get_member_offset
          • get_func_cmt
          • parse_decl
          • create_qword
          • next_head
          • suspend_thread
          • loader_input_t.getz
          • get_color
          • get_reg_value
          • load_and_run_plugin
          • set_database_flag
          • set_enum_member_name
          • set_member_type
          • get_prev_enum_member
      • IDC examples
        • Batch analysis
        • Device driver analysis
        • New file format definition
        • Structures manipulation
        • VxD analysis
        • Analyzing encrypted code
  • Admin Guide
    • Lumina server
    • Teams server
    • License server
      • Installing on Windows
      • Installing on Linux
      • Installing on OS X
Powered by GitBook
LogoLogo

Need Help?

  • FAQs
  • Support

Community

  • Forum
  • Plugins

Resources

  • Blog
  • Download center

© 2025 Copyright Hex-Rays

On this page
  • More hexadecimal numbers in the output
  • Support for variable size structures
  • UTF-32 strings are printed inline
  • Better argument detection for printf
  • Better argument detection for scanf
  • Resolved TEB references
  • Better automatic selection of union fields
  • Yet one more example of union fields
  • Improved support for EABI helpers
  • Improved local variable allocation
  • Better recognizition of string references
  • Better handling of structures returned by value
  • More while loops
  • Shorter code
  • Improved recognition of magic divisions
  • Less gotos
  • Division may generate an exception
  • Order of variadic arguments
  • Improved division recognition

Was this helpful?

Export as PDF
  1. User Guide
  2. Decompiler
  3. Introduction to Decompilation vs. Disassembly

Hex-Rays v7.3 vs. v7.2 Decompiler Comparison Page

Last updated 6 months ago

Was this helpful?

Below you will find side-by-side comparisons of v7.2 and v7.3 decompilations. Please maximize the window too see both columns simultaneously.

The following examples are displayed on this page:

NOTE: these are just some selected examples that can be illustrated as side-by-side differences. There are many other improvements and new features that are not mentioned on this page. We just got tired selecting them. Some of the improvements that did not do to this page:

  • objc-related improvements

  • value range analysis can eliminate more useless code

  • better resolving of got-relative memory references

  • too big shift amounts are converted to lower values (e.g. 33->1)

  • more for-loops

  • better handling of fragemented variables

  • many other things...


More hexadecimal numbers in the output

When a constant looks nicer as a hexadecimal number, we print it as a hexadecimal number by default. Naturally, beauty is in the eye of the beholder, but the new beahavior will produce more readable code, and less frequently you will fell compelled to change the number representation. By the way, this tiny change is just one of numerious improvements that we keep adding in each release. Most of them go literally unnoticed. It is just this time we decided to talk about them

bool __fastcall ge_100000001(__int64 a1)
{
  return a1 >= 0x100000001LL;
}
bool __fastcall ge_100000001(__int64 a1)
{
  return a1 >= 4294967297LL;
}

Support for variable size structures

EfiBootRecord points to a structure that has RecordExtents[0] as the last member. Such structures are considered as variable size structures in C/C++. Now we handle them nicely.

BlockNumber = EfiBootRecord->RecordExtents[ExtentIndex64].BlockNumber;
BlockCount = EfiBootRecord->RecordExtents[ExtentIndex64].BlockCount;
BlockNumber = *(UINT64 *)((char *)&EfiBootRecord[1].BlockHeader.Checksum + ExtentIndex64);
BlockCount = *(UINT64 *)((char *)&EfiBootRecord[1].BlockHeader.ObjectOid + ExtentIndex64);

UTF-32 strings are printed inline

We were printing UTF-8 and other string types, UTF-32 was not supported yet. Now we print it with the 'U' prefix.

v3 = std::operator<<<std::char_traits<char>>(&std::cout, U"This is U\"Hello\"
    .rodata:0000000000000120  text "UTF-32LE", 'This is U"Hello"',0
    ...
    v10 = std::ostream::operator<<(v9, aThisIsUHello_0);

Better argument detection for printf

The difference between these outputs is subtle but pleasant. The new version managed to determine the variable types based on the printf format string. While the old version ended up with int a2, int a3, the new version correctly determined them as one __int64 a2.

int __fastcall ididi(int a1, __int64 a2, int a3, __int64 a4, int a5)
{
  int varg_r0; // [sp+28h] [bp-10h]
  __int64 varg_r2; // [sp+30h] [bp-8h]

  varg_r0 = a1;
  varg_r2 = a2;
  my_print("d=%I64d\n", a2);
  my_print("d1=%I64d\n", a4);
  my_print("%d-%I64d-%d-%I64d-%d\n", varg_r0, varg_r2, a3, a4, a5);
  return 0;
}
int __fastcall ididi(int a1, int a2, __int64 a3, int a4, __int64 a5, int a6)
{
  int v6; // r1
  char v8; // [sp+4h] [bp-34h]
  int varg_r0; // [sp+28h] [bp-10h]
  __int64 varg_r2; // [sp+30h] [bp-8h]

  varg_r0 = a1;
  varg_r2 = a3;
  my_print("d=%I64d\n", a2, a3);
  my_print("d1=%I64d\n", v6, a5);
  my_print("%d-%I64d-%d-%I64d-%d\n", varg_r0, varg_r2, a4, v8, a5, a6);
  return 0;
}

Better argument detection for scanf

A similar logic works for scanf-like functions. Please note that the old version was misdetecting the number of arguments. It was possible to correct the misdetected arguments using the Numpad-Minus hotkey but it is always better when there is less routine work on your shoulders, right?

scanf("8: %d%i %x%o %s%s %C%c", &v12, &v7, &v3, &v4, &v2, &v9, &v8, &v13);
scanf("8:   %[ a-z]%c %2c%c %2c%2c %[ a-z]%c", &v12, &v7, &v3, &v4, &v2, &v9, &v8, &v13);
  scanf("8: %d%i %x%o %s%s %C%c", &v12, &v7, &v3, &v4, &v2, &v9, &v8, &v13, &v10, &v0, &v6, &v5, &v1, &v11);
  scanf(
    "8:   %[ a-z]%c %2c%c %2c%2c %[ a-z]%c",
    &v12,
    &v7,
    &v3,
    &v4,
    &v2,
    &v9,
    &v8,
    &v13,
    &v10,
    &v0,
    &v6,
    &v5,
    &v1,
    &v11);

Resolved TEB references

While seasoned reversers know what is located at fs:0, it is still better to have it spelled out. Besides, the type of v15 is automatically detected as struct _EXCEPTION_REGISTRATION_RECORD *.

v15 = NtCurrentTeb()->NtTib.ExceptionList;
v15 = __readfsdword(0);

Better automatic selection of union fields

Again, the user can specify the union field that should be used in the output (the hotkey is Alt-Y) but there are situations when it can be automatically determined based on the access type and size. The above example illustrates this point. JFYI, the type of entry is:

union __XmStringEntryRec
{
  _XmStringEmptyHeader empty;
  _XmStringOptSegHdrRec single;
  _XmStringUnoptSegHdrRec unopt_single;
  _XmStringArraySegHdrRec multiple;
};
struct __XmStringEmptyHeader
{
  unsigned __int32 type : 2;
};
struct __XmStringOptSegHdrRec
{
  unsigned __int32 type : 2;
  unsigned __int32 text_type : 2;
  unsigned __int32 tag_index : 3;
  unsigned __int32 rend_begin : 1;
  unsigned __int8 byte_count;
  unsigned __int32 rend_end : 1;
  unsigned __int32 rend_index : 4;
  unsigned __int32 str_dir : 2;
  unsigned __int32 flipped : 1;
  unsigned __int32 tabs_before : 3;
  unsigned __int32 permanent : 1;
  unsigned __int32 soft_line_break : 1;
  unsigned __int32 immediate : 1;
  unsigned __int32 pad : 2;
};

While we can not handle bitfields yet, their presence does not prevent using other, regular fields, of the structure.

if ( entry->single.byte_count )
if ( *((_BYTE *)&entry->empty + 1) )

Yet one more example of union fields

I could not resist the temptation to include one more example of automatic union selection. How beautiful the code on the right is!

void __fastcall h_generic_calc_Perm32x8(V256 *res, V256 *argL, V256 *argR)
{
  res->w32[0] = argL->w32[argR->w32[0] & 7];
  res->w32[1] = argL->w32[argR->w32[1] & 7];
  res->w32[2] = argL->w32[argR->w32[2] & 7];
  res->w32[3] = argL->w32[argR->w32[3] & 7];
  res->w32[4] = argL->w32[argR->w32[4] & 7];
  res->w32[5] = argL->w32[argR->w32[5] & 7];
  res->w32[6] = argL->w32[argR->w32[6] & 7];
  res->w32[7] = argL->w32[argR->w32[7] & 7];
}
void __fastcall h_generic_calc_Perm32x8(V256 *res, V256 *argL, V256 *argR)
{
  LODWORD(res->w64[0]) = *((_DWORD *)argL->w64 + (argR->w64[0] & 7));
  HIDWORD(res->w64[0]) = *((_DWORD *)argL->w64 + (HIDWORD(argR->w64[0]) & 7));
  LODWORD(res->w64[1]) = *((_DWORD *)argL->w64 + (argR->w64[1] & 7));
  HIDWORD(res->w64[1]) = *((_DWORD *)argL->w64 + (HIDWORD(argR->w64[1]) & 7));
  LODWORD(res->w64[2]) = *((_DWORD *)argL->w64 + (argR->w64[2] & 7));
  HIDWORD(res->w64[2]) = *((_DWORD *)argL->w64 + (HIDWORD(argR->w64[2]) & 7));
  LODWORD(res->w64[3]) = *((_DWORD *)argL->w64 + (argR->w64[3] & 7));
  HIDWORD(res->w64[3]) = *((_DWORD *)argL->w64 + (HIDWORD(argR->w64[3]) & 7));
}

Improved support for EABI helpers

No comments needed, we hope. The new decompiler managed to fold constant expressions after replacing EABI helpers with corresponding operators.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  printf("r = %d == 42\n", 42);
  printf("r = %lld == 42\n", 42LL);
  printf("ABORT %d\n", 0x40000001);
  return 0;
}
void __fastcall h_generic_calc_Perm32x8(V256 *res, V256 *argL, V256 *argR)
{
  LODWORD(res->w64[0]) = *((_DWORD *)argL->w64 + (argR->w64[0] & 7));
  HIDWORD(res->w64[0]) = *((_DWORD *)argL->w64 + (HIDWORD(argR->w64[0]) & 7));
  LODWORD(res->w64[1]) = *((_DWORD *)argL->w64 + (argR->w64[1] & 7));
  HIDWORD(res->w64[1]) = *((_DWORD *)argL->w64 + (HIDWORD(argR->w64[1]) & 7));
  LODWORD(res->w64[2]) = *((_DWORD *)argL->w64 + (argR->w64[2] & 7));
  HIDWORD(res->w64[2]) = *((_DWORD *)argL->w64 + (HIDWORD(argR->w64[2]) & 7));
  LODWORD(res->w64[3]) = *((_DWORD *)argL->w64 + (argR->w64[3] & 7));
  HIDWORD(res->w64[3]) = *((_DWORD *)argL->w64 + (HIDWORD(argR->w64[3]) & 7));
}

Improved local variable allocation

Now it works better especially in complex cases.

tbd
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // r0
  int v4; // r0
  int v5; // r0
  int v6; // r0
  int v7; // r0
  __int64 v8; // r0
  int v9; // r2
  __int64 v11; // [sp+0h] [bp-14h]
  int v12; // [sp+Ch] [bp-8h]
  int v13; // [sp+Ch] [bp-8h]

  v3 = _mulvsi3(7, 6, envp);
  v4 = _negvsi2(v3);
  v5 = _addvsi3(v4, 101);
  v12 = _subvsi3(v5, 17);
  printf("r = %d == 42\n", v12);
  v11 = _mulvdi3(7, 0, 6, 0);
  v6 = _negvdi2(v12, v12 >> 31);
  v7 = _addvdi3(v6, v6 >> 31, 101, 0);
  v8 = _subvdi3(v7, v7 >> 31, 17, 0);
  printf("r = %lld == 42\n", HIDWORD(v8), v11);
  v13 = _mulvsi3(0x7FFFFFFF, 0x3FFFFFFF, v9);
  printf("ABORT %d\n", v13);
  return 0;
}

Better recognizition of string references

In this case too, the user could set the prototype of sub_1135FC as accepting a char * and this would be enough to reveal string references in the output, but the new decompiler can do it automatically.

  sub_1135FC(-266663568, "This is a long long long string");
  if ( v2 > 0x48u )
  {
    sub_108998("Another str");
  sub_1135FC(-266663568, 89351520);
  if ( v2 > 0x48u )
  {
    sub_108998(89351556);

Better handling of structures returned by value

The code on the left had a very awkward sequence to copy a structure. The code on the right eliminates it as unnecessary and useless.

  _BYTE v1[12]; // rax
  ...
  return *(mystruct *)v1;
}
  _BYTE v1[12]; // ax
  mystruct result; // 0:ax.11

  ...
  *(_QWORD *)result.ca1 = *(_QWORD *)v1;
  result.s1 = *(_WORD *)&v1[8];
  result.c1 = v1[10];
  return result;
}

More while loops

Do you care about this improvement? Probably you do not care because the difference is tiny. However, in additon to be simpler, the code on the right eliminated a temporary variable, v5. A tiny improvement, but an improvement it is.

while ( *++v4 )
    ;
do
    v5 = *++v4;
  while ( v5 );

Shorter code

Another tiny improvement made the output considerably shorter. We like it!

unsigned __int8 *__fastcall otp_memset(unsigned __int8 *pDest, unsigned __int8 val, int size)
{
  unsigned __int8 *i; // r3

  for ( i = pDest; (unsigned int)size-- >= 1; ++i )
    *i = val;
  return pDest;
}
unsigned __int8 *__fastcall otp_memset(unsigned __int8 *pDest, unsigned __int8 val, int size)
{
  unsigned __int8 *i; // r3
  _BOOL1 v4; // cf

  for ( i = pDest; ; ++i )
  {
    v4 = (unsigned int)size-- >= 1;
    if ( !v4 )
      break;
    *i = val;
  }
  return pDest;
}
}

Improved recognition of magic divisions

This is a very special case: a division that uses the rcr instruction. Our microcode does not have the opcode for it but we implemented the logic to handle some special cases, just so you do not waste your time trying to decipher the meaning of convoluted code (yes, rcr means code that is difficult to understand).

unsigned __int64 __fastcall konst_mod251_shr3(unsigned __int64 a1)
{
  return (a1 >> 3) % 0xFB;
}
__int64 __fastcall konst_mod251_shr3(unsigned __int64 a1)
{
  unsigned __int64 v1; // rcx

  v1 = a1 >> 3;
  _RDX = v1 + ((v1 * (unsigned __int128)0x5197F7D73404147ui64) >> 64);
  __asm { rcr     rdx, 1 }
  return v1 - 251 * (_RDX >> 7);
}

Less gotos

Well, we can not say that we produce less gotos in all cases, but there is some improvement for sure. Second, note that the return type got improved too: now it is immediately visible that the function returns a boolean (0/1) value.

_BOOL8 __fastcall sub_0(__int64 a1, int *a2)
{
  int v2; // eax
  int v3; // eax
  int v4; // eax

  v2 = *a2;
  if ( *a2 > 522 )
  {
    v4 = v2 - 4143;
    return !v4 || v4 == 40950;
  }
  if ( v2 != 522 )
  {
    v3 = v2 - 71;
    if ( v3 )
    {
      if ( (unsigned int)(v3 - 205) >= 2 )
        return 0;
    }
  }
  return 1;
}
__int64 __fastcall sub_0(__int64 a1, int *a2)
{
  int v2; // eax
  int v3; // eax
  int v4; // eax

  v2 = *a2;
  if ( *a2 > 522 )
  {
    v4 = v2 - 4143;
    if ( !v4 || v4 == 40950 )
      goto LABEL_8;
LABEL_9:
    return 0;
  }
  if ( v2 != 522 )
  {
    v3 = v2 - 71;
    if ( v3 )
    {
      if ( (unsigned int)(v3 - 205) >= 2 )
        goto LABEL_9;
    }
  }
LABEL_8:
  return 1;
}

Division may generate an exception

What a surprise, the code on the right is longer and more complex! Indeed, it is so, and it is because now the decompiler is more careful with the division instructions. They potentially may generate the zero division exception and completely hiding them from the output may be misleading. If you prefer the old behaviour, turn off the division preserving in the configuration file.

__int64 __fastcall sub_4008C0(int a1)
{
  int v1; // ecx
  int v2; // edx
  int v4; // [rsp+0h] [rbp-4h]

  v1 = 2;
  if ( a1 > 2 )
  {
    do
    {
      nanosleep(&rmtp, &rqtp);
      v2 = a1 % v1++;
      v4 = 1 / v2;
    }
    while ( v1 != a1 );
  }
  return 0LL;
}
__int64 __fastcall sub_4008C0(int a1)
{
  int v1; // ecx

  v1 = 2;
  if ( a1 > 2 )
  {
    do
    {
      nanosleep(&rmtp, &rqtp);
      ++v1;
    }
    while ( v1 != a1 );
  }
  return 0LL;
}

Order of variadic arguments

Do you notice the difference? If not, here is a hint: the order of arguments of sub_88 is different. The code on the right is more correct because the the format specifiers match the variable types. For example, %f matches float a. At the first sight the code on the left looks completely wrong but (surprise!) it works correctly on x64 machines. It is so because floating point and integer arguments are passed at different locations, so the relative order of floating/integer arguments in the call does not matter much. Nevertheless, the code on the right causes less confusion.

int __cdecl func1(const float a, int b, void *c)
{
  return sub_88("%f, %d, %p\n", a, (unsigned int)b, c);
}
int __cdecl func1(const float a, int b, void *c)
{
  return sub_88("%f, %d, %p\n", (unsigned int)b, c, a);
}

Improved division recognition

This is a never ending battle, but we advance!

int int_h_mod_m32ui64(void)
{
  return h() % 32;
}
int int_h_mod_m32ui64(void)
{
  __int64 v0; // r10

  v0 = h();
  return (abs64(v0) & 0x1F ^ (SHIDWORD(v0) >> 31)) - (SHIDWORD(v0) >> 31);
}
More hexadecimal numbers in the output
Support for variable size structures
UTF-32 strings are printed inline
Better argument detection for printf
Better argument detection for scanf
Resolved TEB references
Better automatic selection of union fields
Yet one more example of union fields
Improved support for EABI helpers
Improved local variable allocation
Better recognizition of string references
Better handling of structures returned by value
More while loops
Shorter code
Improved recognition of magic divisions
Less gotos
Division may generate an exception
Order of variadic arguments
Improved division recognition