Assembly
Assembly 备忘录

Assembly 备忘录

18 Graduates

Assembly 备忘录

Assembly Memo Challenge

Assembly Memo

在本单元中,我们将使用 sBPF 汇编语言为我们的程序创建一个日志机制。

一个简单的备忘录程序是您开始 sBPF 汇编之旅的完美起点!

如果您不熟悉汇编编程,请参阅汇编入门课程

Program Design

我们的程序将简单地将正确的内存位置放入正确的寄存器中,然后执行 sol_log_ 系统调用。它看起来像这样:

sbpf
.equ NUM_ACCOUNTS, 0x00
.equ DATA_LEN, 0x08
.equ DATA, 0x10
.globl entrypoint
entrypoint:
  ldxdw r0, [r1+NUM_ACCOUNTS]
  ldxdw r2, [r1+DATA_LEN]
  add64 r1, DATA
  call sol_log_
  exit

Memory Offsets

程序开始时声明了三个 .equ 常量,这些常量定义了指令数据的内存布局:

sbpf
.equ NUM_ACCOUNTS, 0x00  ; Offset for number of accounts
.equ DATA_LEN, 0x08      ; Offset for data length
.equ DATA, 0x10          ; Offset for actual data

这些常量标记了相对于 r1 的入口缓冲区指针的字节偏移:

  • NUM_ACCOUNTS (0x0000):指向指令数据头中用于验证的账户计数

  • DATA_LEN (0x08):指向指令数据头中的指令数据长度

  • DATA (0x10):指向指令数据头中的指令数据

与抽象内存布局的高级语言不同,汇编语言需要确切知道每一部分数据的位置。

Entrypoint and Initial Validation

sbpf
.globl entrypoint
entrypoint:
  ldxdw r0, [r1+NUM_ACCOUNTS]   ; Load number of accounts into r0

每个 sBPF 程序都从一个全局 .entrypoint 符号开始。Solana 运行时通过寄存器 r1 提供账户和指令数据。

第一条指令将账户数量加载到 r0 中。由于 r0 是虚拟机在退出时读取的寄存器,这样做有两个目的:

  1. 加载账户计数供我们使用

  2. 如果传递了任何账户(r0 中的非零值),程序将自动失败

Sol Log Syscall

接下来,我们为sol_log_系统调用准备参数:

sbpf
ldxdw r2, [r1+DATA_LEN]   ; Load length of memo into r2
add64  r1, DATA           ; Adjust r1 to point to memo bytes

这些指令设置了sol_log_的参数:

  • r2接收备忘录数据的长度

  • r1被调整为直接指向备忘录字节

然后,我们调用sol_log_并退出:

sbpf
call 16   ; Call sol_log_ (helper ID 16)
exit      ; Return using r0 value

Conclusion

该程序:

  1. 调用16(sol_log_)将备忘录打印到验证器日志

  2. 使用r0中的值退出

准备接受挑战了吗?
Blueshift © 2025Commit: e573eab