Skip to content

ASM and pseudocode: a controlled demo

These captures show the real MachLift application analyzing MachLift Demo, a small test fixture compiled from C with clang -O2 for ARM64/macOS 14. The executable is packaged in an IPA-shaped archive; this is a controlled container test, not an iOS application or evidence of complete iOS ABI support.

The selected executable is Payload/App.app/App. Its symbols are retained, so MachLift can display the function names supplied by the fixture. The addresses below belong to this particular build and can change on recompilation.

The fixture’s source contains:

__attribute__((noinline)) uint64_t machlift_fixture_blend(uint64_t a, uint64_t b) {
return a * 2 + b + 7;
}

In the analyzed executable, _machlift_fixture_blend begins at 0x0000000100000418. The disassembly shows a shifted-register addition, an immediate addition, and a return:

0x100000418 add x8, x1, x0, lsl #1
0x10000041C add x0, x8, #7
0x100000420 ret

MachLift showing the blend demo’s three ARM64 instructions alongside generated arithmetic pseudocode.

The generated function body is reproduced verbatim:

func sub_100000418(x0: UInt64, x1: UInt64) -> UInt64 {
let v0 = x1 &+ x0 << 1 &+ 7
return v0
}

This is approximate Swift-like pseudocode. The input was C; the output does not establish that the original program was Swift. x0 and x1 represent incoming register contents, and v0 is a generated local name. The address-derived function name does not recover the original signature. Wrapping operators describe machine arithmetic. The return interpretation uses the AAPCS64 return-register convention, rather than a recovered source type.

_machlift_fixture_classify, at 0x0000000100000504, provides a larger example. The disassembly includes cbz, tbnz, cmp, b.hi, bl, and str instructions. The generated output represents conditional paths, an early return, a call destination, and memory effects.

MachLift showing the classify demo’s ARM64 instructions and conditional pseudocode in the Side by Side view.

The screenshot is scrolled to the function body. Long lines continue horizontally in the application; the selectable excerpt below includes the complete generated body:

func sub_100000504(x1: UInt64, x2: UInt64, x0: UInt64, x20: UInt64) -> UInt64 {
if x1 == 0 {
return 0
} else {
var v0: UInt64
if UInt32(truncatingIfNeeded: x2) & 1 != 0 {
UnsafeMutableRawPointer(bitPattern: UInt(x0 &+ 8))!.storeBytes(of: x1, as: UInt64.self)
let v1 = x0
v0 = sub_10000043c(x0: x1, x1: x1, x2: x2, x20: x20)
} else {
if x2 > 15 {
v0 = UInt64(7)
} else {
UnsafeMutableRawPointer(bitPattern: UInt(x0 &+ 16))!.storeBytes(of: x2, as: UInt64.self)
v0 = x2 &- x1
}
}
UnsafeMutableRawPointer(bitPattern: UInt(x0))!.storeBytes(of: v0, as: UInt64.self)
return v0
}
}

The application reports that this pseudocode depends on assumptions about code MachLift did not read. The call names its transfer destination; register labels describe machine state, not a recovered argument list. The callee’s signature, parameter order, return type, and inputs outside the displayed registers are not recovered. Stack arguments are not modeled by this call representation. Return values use the AAPCS64 convention.

The displayed stores establish a memory effect at an address and width. They do not establish Swift fields, arrays, or source-level pointer types. The generated pointer expressions are explanatory pseudocode and are not an invitation to execute recovered output.

Select a function candidate in Functions, then choose Disassembly, Pseudocode, or Side by Side. Read the symbol, address, assumptions, and instruction mappings together. Pseudocode availability depends on the function and supported analysis; these two examples do not establish full program recovery.

The homepage captures include full-resolution image links. Continue with evidence and uncertainty or the IPA exploration guide.