zxdb 中的組合語言

拆解

disassemble 指令 (di) 會從目前位置拆解。如果有,操作說明和呼叫目的地會添加來源行資訊:

[zxdb] di
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<>()

di 指令也可接受地址或符號做為參數。如果指定函式名稱,就會拆解整個函式:

[zxdb] di 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]
   ...

切換按鈕

disassemble 指令接受以下切換按鈕:

  • --num=<lines>-n <lines>:要發出的行數或指示。預設值為指定函式中的操作說明 (如果地點是函式名稱),否則預設值為 16。

  • --raw-r:除了已解碼的指示外,請輸出原始位元組。

機器操作說明

您可以使用下列 Zxdb 指令執行機器操作說明:

  • nexti / ni:跳至下一個操作說明,逐步執行函式呼叫。

  • stepi / si:請接著進行接下來的函式呼叫操作。

例如:

[zxdb] ni
🛑 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] ni
🛑 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 會維護最後一個指令是否為組合指令或原始碼,並顯示有關步數或中斷點命中的資訊。如要切換至組合語言模式,請輸入 disassemble,並切換回原始碼模式,請輸入 list

註冊

regs 指令會顯示最常見的 CPU 註冊數。

[zxdb] regs
General Purpose Registers
      rax  0xfffffffffffffffa = -6
      rbx          0x50b7085b
      rcx                 0x0 = 0
      rdx      0x2023de8c87a0
      rsi  0x7fffffffffffffff
      rdi          0x50b7085b
      rbp      0x224bb1e0b950
      rsp      0x224bb1e0b928
      ...

只要切換至 regs 指令,即可查看 CPU 暫存器的其他類別和選項:

  • --all-a:啟用所有註冊類別 (不含 -e)。

  • --float-f:列印專屬的浮點暫存器。大多數情況下,應改用 --vector,因為所有 64 位元 ARM 程式碼和大部分 x64 程式碼都會使用向量登錄做為浮點值。

  • --vector-v:列印向量登錄。詳情請參閱以下說明。

  • --debug-d:列印偵錯註冊。

  • --extended-e:啟用更詳細的標記解碼功能。產生的更多資訊通常不適合用於日常偵錯。這包括 rflags 中為 x64 註冊的系統層級標記等資訊。

在運算式中註冊

註冊作業可用於變數等運算式。註冊的正式名稱是 $reg(register name)

[zxdb] print $reg(x3)
79

此外,如果沒有同名的變數,您可以使用原始註冊名稱:

[zxdb] print x3
79

您可使用正規運算式評估語法指派註冊:

[zxdb] print x3 = 0
0

向量註冊

regs --vector 指令會根據目前的 vector-format 設定,在資料表中顯示向量登錄。使用 get vector-format 查看目前的值和說明文件,並使用 set vector-format <new-value> 設定新的向量格式。可能的值為:

  • i8 (帶正負號) 或 u8 (無正負號):8 位元整數的陣列。
  • i16 (帶正負號) 或 u16 (無正負號):16 位元整數的陣列。
  • i32 (帶正負號) 或 u32 (無正負號):32 位元整數的陣列。
  • i64 (帶正負號) 或 u64 (無正負號):64 位元整數的陣列。
  • i128 (帶正負號) 或 u128 (無正負號):128 位元整數的陣列。
  • float:單精度浮點陣列。
  • double:雙精度浮點陣列。此為預設值。
[zxdb] set vector-format double

[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-format 設定可控制每個暫存器轉換為陣列值的方式。舉例來說,如要顯示解譯為 x86 向量暫存器 ymm1 的 32 位元低點值:

[zxdb] set vector-format float

[zxdb] print ymm1[0]
3.14159

轉換為陣列時,會將低位元指派為索引 0,從該陣列遞增。請注意,regs 中的向量登錄表格會在右側顯示較低的值。