Skip to content

Search Opcodes and Watchpoints

brkzlr edited this page Jun 25, 2026 · 3 revisions

These tools help you find code. Sometimes you start from a value and want to know what code touches it. Sometimes you start from code and want to know what addresses it touches. Sometimes you just want to search the disassembly for an instruction pattern.

Which Tool Should I Use?

Use Search Instructions when you know what the instruction might look like:

  • Find calls: call
  • Find stack accesses: [rsp]
  • Find register usage: rax
  • Find comparisons: cmp

Use Find out what writes/reads/accesses this address when you already found a value and want to know what code touches it.

Use Find out which addresses this instruction accesses when you found an interesting instruction and want to see which runtime addresses it reads or writes.

Use Set Watchpoint from the hex view when you want a normal GDB watchpoint that stops the process every time the memory is touched.

Search Instructions

Open it from Memory Viewer -> Tools -> Search Instructions.

This searches disassembled instructions in a selected address range. It does not search raw bytes. It searches the instruction text that PINCE gets from disassembly.

The useful fields are:

  • Search: Text or regex to search for
  • Case sensitive: Match uppercase/lowercase exactly
  • Regex: Treat the search as a Python regex instead of plain text
  • Start: First address to search
  • End: Last address to search

Press Search or hit Enter to run it.

The help button shows a few regex examples:

  • call|rax: find instructions containing call or rax
  • [re]cx: find both rcx and ecx
  • \[rsp\]: find literal [rsp]

If the regex is invalid, PINCE shows:

Invalid Regex

Search results have an address and instruction text. Double click a result to jump there in the disassembly view. Right click a result if you only want to copy the address or instruction.

Starting From a Value

This is the common game hacking workflow.

Once you find a value in the address table, right click it and choose one of these:

  • Find out what writes to this address: code that changes the value
  • Find out what reads this address: code that reads the value
  • Find out what accesses this address: both reads and writes

PINCE opens a tracking window and lets the game continue. Every time the watchpoint hits, PINCE records the instruction and continues again.

The tracking window shows:

  • Count: how many times that instruction hit
  • Address: instruction address
  • Register info: integer and float register values from the hit
  • Disassembly: code around the instruction

Double click a result to jump to that instruction in Memory Viewer.

Typical flow:

  1. Find health, ammo or whatever value you care about
  2. Right click it in the address table
  3. Pick Find out what writes to this address
  4. Do the thing in-game, like take damage or shoot
  5. Look at the instructions that show up
  6. Double click the interesting one
  7. Patch it, NOP it or inspect it further

For changing values, start with writes. For checks like if health <= 0, reads or accesses can be more useful.

Starting From an Instruction

Sometimes you already found an instruction and want to know what addresses it touches at runtime.

In the disassembly view, right click an instruction and choose:

Find out which addresses this instruction accesses

PINCE asks for register expressions. These are the address expressions it should collect when the instruction runs. For example, if the instruction is:

mov eax, [rcx+0x14]

you would usually enter:

rcx+0x14

When the instruction hits, PINCE records the addresses produced by that expression. The tracking window can also show the current value at those addresses using the selected value type.

Double click a result to add that runtime address to the address table.

This is useful when one instruction touches many objects and you want to see which addresses it actually uses while the game runs.

Normal Watchpoints From Hex View

The hex view has normal watchpoints. Right click a byte or selected range and use Set Watchpoint:

  • Write Only: GDB watch, stops when the memory is written
  • Read Only: GDB rwatch, stops when the memory is read
  • Both: GDB awatch, stops on read or write

Unlike tracked watchpoints, these stop the process every time they trigger. This is useful when you want to inspect the exact state at the moment of access, but it can make the game painful to run if the address is hit constantly.

If setting one fails, PINCE shows:

Failed to set watchpoint at address {address}

Limits and Slowdowns

Watchpoints are limited by CPU debug registers. On x86/x64, you usually only get 4 hardware watchpoint/breakpoint slots.

PINCE also splits larger watched ranges:

  • 64-bit target: chunks up to 8 bytes
  • 32-bit target: chunks up to 4 bytes

So watching a large value or range can consume multiple slots. If all hardware slots are used, setting another watchpoint can fail.

Tracked watchpoints continue automatically, but they are still based on GDB watchpoints. If the watched address is touched thousands of times per second, the game can still slow down badly.

Tips

Use the narrowest watch type that answers your question:

  • Use Write Only when looking for code that changes a value
  • Use Read Only when looking for code that checks or uses a value
  • Use Both when you're not sure yet

Try to trigger only the event you care about. If you're looking for health damage code, start the tracker right before taking damage, then stop it after you get a few hits.

If the result list is huge, the watchpoint probably ran during too much unrelated gameplay. Stop it, clear your setup and try again with a smaller action window.

Clone this wiki locally