blob: d4abd109178ff9e887d7edf4520659dff2c96348 [file] [log] [blame] [view]
# Work with assembly language
## `disassemble`
Note: This is the `disassemble` command. You can also use `di` to express
`disassemble`.
The `disassemble` command disassembles from the current location. If available,
the instructions and call destinations are annotated with source line information:
For example:
```none {: .devsite-terminal data-terminal-prefix="[zxdb]" }
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:
```none {: .devsite-terminal data-terminal-prefix="[zxdb]" }
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`:
Note: `$rip` is a register that stores a number (an address) of the next
instruction to execute.
```
[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.
* `--raw` or `-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:
```none {: .devsite-terminal data-terminal-prefix="[zxdb]" }
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:
```none {: .devsite-terminal data-terminal-prefix="[zxdb]" }
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:
* `--all` or `-a`: Enable all register categories (does not imply `-e`).
* `--debug` or `-d`: Prints the debug registers.
* `--extended` or `-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 `rflags`
register for x64.
* `--float` or `-f`: Prints the dedicated floating-point registers. In most
cases you should use `--vector` instead because all 64-bit ARM code and most
x64 code uses vector registers for floating point.
* `--vector` or `-v`: Prints the vector registers.
### Registers in expressions
Registers can be used in [expressions](expressions.md) like variables. The
canonical name of a register is `$reg(register name)`.
For more information and examples, see [CPU registers][cpu-registers-doc].
### 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`:
```none {: .devsite-terminal data-terminal-prefix="[zxdb]" }
set vector-format double
```
This example returns the vector registers:
Note: The vector register table in `regs` are displayed with the low values
on the right side.
```
[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`:
1. Set the `vector-format` to float:
```none {: .devsite-terminal data-terminal-prefix="[zxdb]" }
set vector-format float
```
1. 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.
[cpu-registers-doc]: /docs/development/debugger/expressions.md#cpu-registers