disassemble
The disassemble command disassembles from the current location. If available,
the instructions and call destinations are annotated with source line information:
For example:
disassemble
miscsvc.cc:118
 ▶ 0x20bc1c7aa60a  mov     dword ptr [rbx + 0x10c], eax
miscsvc.cc:122
   0x20bc1c7aa610  movabs  rax, -0x5555555555555556
   0x20bc1c7aa61a  mov     qword ptr [rbx + 0xe8], rax
   0x20bc1c7aa621  mov     qword ptr [rbx + 0xe8], 0x0
   0x20bc1c7aa62c  mov     rdi, qword ptr [rbx + 0xb0]
   0x20bc1c7aa633  mov     rax, qword ptr [rbx + 0xe8]
   0x20bc1c7aa63a  mov     qword ptr [rbx + 0x20], rax
   0x20bc1c7aa63e  call    0x20d    ➔ std::__2::size<>()
Functions
If you specify an address or symbol, the disassemble command disassembles on
the respective address or symbol. If you provide a function name, it
disassembles the entire function:
disassemble main
miscsvc.cc:88
   0x20bc1c7aa000  push    rbp
   0x20bc1c7aa001  mov     rbp, rsp
   0x20bc1c7aa004  push    rbx
   0x20bc1c7aa005  and     rsp, -0x20
   0x20bc1c7aa009  sub     rsp, 0x140
   0x20bc1c7aa010  mov     rbx, rsp
   0x20bc1c7aa013  mov     rax, qword ptr fs:[0x10]
   ...
PC relative offsets
In some cases, you may want to disassemble based on the PC (program counter) relative offset.
For example, to disassemble at the address $rip - 0x7:
[zxdb] di -- -0x7 # Disassemble at the address $rip - 0x7
     350     FX_LOGS(FATAL) << "Failed to construct the cobalt app: " << app.status();
     351   }
     352   inspector.Health().Ok();
     353   loop.Run();
   0x591e76352b  xor   edx, edx
   0x591e76352d  call  0x260fae   ➔ async::Loop::Run(async::Loop*, zx::time, bool)
     354   FX_LOGS(INFO) << "Cobalt will now shut down.";
 ▶ 0x591e763532  mov   edi, 0x30
   0x591e763537  call  0x81ab4    ➔ fuchsia_logging::ShouldCreateLogMessage(fuchsia_logging::LogSeverity)
   0x591e76353c  mov   byte ptr [rbp - 0x1b1], 0x0
   0x591e763543  test  al, 0x1
   0x591e763545  jne   0x2
   0x591e763547  jmp   0x74
Arguments
The disassemble command accepts the following arguments:
- --num=<lines>or- -n <lines>: The number of lines or instructions to emit. If the location is a function name, it defaults to the instructions in the given function. If the location is an address or symbol, it defaults to 16.
- --rawor- -r: Output raw bytes in addition to the decoded instructions.
Stepping in machine instructions
To step through machine instructions you can use following zxdb commands:
- nexti/- ni: Advances to the next instruction, but steps over call instructions for the target architecture..
- stepi/- si: Advances exactly one machine instruction..
For example:
nexti
🛑 main(int, const char**) • main.cc:102
main.cc:99
 ▶ 0x23f711346233  mov   edx, 0x20
   0x23f711346238  call  0x35a3a3  ➔ __asan_memcpy
   0x23f71134623d  mov   rdi, qword ptr [rbx + 0x258]
   0x23f711346244  call  0x1677    ➔ $anon::DecodeCommandLine
[zxdb] nexti
🛑 main(int, const char**) • main.cc:102
main.cc:99
 ▶ 0x23f711346238  call  0x35a3a3 ➔ __asan_memcpy
   0x23f71134623d  mov   rdi, qword ptr [rbx + 0x258]
   0x23f711346244  call  0x1677   ➔ $anon::DecodeCommandLine
   0x23f711346249  mov   rdi, qword ptr [rbx + 0x260]
Zxdb maintains information about whether the last command was an assembly command or source-code and shows that information on stepping or breakpoint hits.
To switch to assembly-language mode, use disassemble.
To switch to source-code mode, use list.
regs
The regs command shows the most common CPU registers.
For example:
regs
General Purpose Registers
      rax  0xfffffffffffffffa = -6
      rbx          0x50b7085b
      rcx                 0x0 = 0
      rdx      0x2023de8c87a0
      rsi  0x7fffffffffffffff
      rdi          0x50b7085b
      rbp      0x224bb1e0b950
      rsp      0x224bb1e0b928
      ...
The regs command accepts the following arguments:
- --allor- -a: Enable all register categories (does not imply- -e).
- --debugor- -d: Prints the debug registers.
- --extendedor- -e: Enables more verbose flag decoding. This enables more information that is not normally useful for everyday debugging. This includes information such as the system level flags within the- rflagsregister for x64.
- --floator- -f: Prints the dedicated floating-point registers. In most cases you should use- --vectorinstead because all 64-bit ARM code and most x64 code uses vector registers for floating point.
- --vectoror- -v: Prints the vector registers.
Registers in expressions
Registers can be used in expressions like variables. The
canonical name of a register is $reg(register name).
For more information and examples, see CPU registers.
Vector registers
The regs --vector command displays vector registers in a table according
to the current vector-format setting.
Use get vector-format to see the current values.
Use set vector-format <new-value> to set a new vector format.
The following values are supports:
- i8(signed) or- u8(unsigned): Array of 8-bit integers.
- i16(signed) or- u16(unsigned): Array of 16-bit integers.
- i32(signed) or- u32(unsigned): Array of 32-bit integers.
- i64(signed) or- u64(unsigned): Array of 64-bit integers.
- i128(signed) or- u128(unsigned): Array of 128-bit integers.
- float: Array of single-precision floating point.
- double: Array of double-precision floating point. This is the default.
This example sets the vector-format to double:
set vector-format double
This example returns the vector registers:
[zxdb] regs -v
Vector Registers
  mxcsr 0x1fa0 = 8096
   Name [3] [2] [1]       [0]
   ymm0   0   0   0         0
   ymm1   0   0   0   3.14159
   ymm2   0   0   0         0
   ymm3   0   0   0         0
   ...
Vector registers can also be used like arrays in expressions. The
vector-format setting controls how each register is converted into an array
value.
For example, to show the low 32 bits interpreted as a floating-point value of
the x86 vector register ymm1:
- Set the - vector-formatto float:- set vector-format float
- Print the vector register - ymm1:- [zxdb] print ymm1[0] 3.14159
When converting to an array, the low bits are assigned to be index 0, increasing from there.