Assembly
Pengenalan Assembly

Pengenalan Assembly

Instruksi

Sekarang setelah Anda memahami register dan region memori sBPF, mari kita periksa instruksi yang memanipulasinya.

Instruksi adalah operasi fundamental yang dilakukan program Anda—menambahkan angka, memuat dari memori, atau melompat ke lokasi yang berbeda.

Apa itu Instruksi?

Instruksi adalah blok dasar pembangun program Anda. Anggap saja sebagai perintah yang memberi tahu prosesor persis apa yang harus dilakukan:

  • add64 r1, r2: "Tambahkan nilai dalam register r1 dan r2, simpan hasilnya di r1"
  • ldxdw r0, [r10 - 8]: "Muat 8 byte dari memori stack ke dalam register r0"
  • jeq r1, 42, +3: "Jika r1 sama dengan 42, lompat maju 3 instruksi"

Setiap instruksi melakukan tepat satu operasi dan dikodekan sebagai data 8 byte yang tepat untuk dekoding VM secara instan.

Instruksi sBPF bekerja dengan ukuran data yang berbeda:

  • byte = 8 bit (1 byte)
  • halfword = 16 bit (2 byte)
  • word = 32 bit (4 byte)
  • doubleword = 64 bit (8 byte)

Sebagian besar operasi sBPF menggunakan nilai 64-bit (doubleword) karena register berukuran 64 bit, tetapi Anda dapat memuat dan menyimpan ukuran yang lebih kecil saat diperlukan untuk efisiensi.

Kategori dan Format Instruksi

Ketika Anda mengompilasi kode Rust, C, atau assembly, toolchain menghasilkan aliran instruksi lebar-tetap 8-byte yang dikemas ke dalam bagian .text ELF Anda.

Setiap instruksi mengikuti struktur yang konsisten yang dapat didekode VM dalam satu kali proses:

 
   1 byte    4 bits   4 bits     2 bytes         4 bytes
┌──────────┬────────┬────────┬──────────────┬──────────────────┐
│  opcode  │  dst   │  src   │   offset     │      imm         │
└──────────┴────────┴────────┴──────────────┴──────────────────┘
  • opcode: Mendefinisikan jenis operasi. 3 bit teratas memilih kelas instruksi (aritmatika, memori, lompat, panggil, keluar), sementara 5 bit bawah menentukan varian yang tepat (tambah, kalikan, muat, lompat-jika-sama).
  • dst: Nomor register tujuan (r0–r10) tempat hasil disimpan—hasil aritmatika, nilai yang dimuat, atau pengembalian fungsi pembantu.
  • src: Register sumber yang menyediakan input. Untuk aritmatika dua-operand (add r1, r2), ini menyediakan nilai kedua. Untuk operasi memori, ini dapat menyediakan alamat dasar. Untuk varian langsung (add r1, 10), 4 bit ini digabungkan ke dalam opcode.
  • offset: Integer kecil yang memodifikasi perilaku instruksi. Untuk load/store, ini ditambahkan ke alamat sumber untuk mencapai [src + offset]. Untuk lompatan, ini adalah target cabang relatif yang diukur dalam instruksi.
  • imm: Bidang nilai langsung. Operasi aritmatika menggunakannya untuk konstanta (add r1, 42), CALL menggunakannya untuk nomor syscall (sol_log = 16), dan operasi memori mungkin memperlakukannya sebagai pointer absolut.

Kategori Instruksi

Jenis instruksi yang berbeda menggunakan bidang-bidang ini dengan cara spesifik:

  • Pergerakan Data: Memindahkan nilai antara register dan memori:
sbpf
mov64 r1, 42           // Put immediate value 42 into r1
                       // opcode=move_imm, dst=1, src=unused, imm=42
 
ldxdw r0, [r10 - 8]    // Load 8 bytes from stack into r0  
                       // opcode=load64, dst=0, src=10, offset=-8, imm=unused
 
stxdw [r1 + 16], r0    // Store r0 to memory at [r1 + 16]
                       // opcode=store64, dst=1, src=0, offset=16, imm=unused
  • Aritmatika: Melakukan operasi matematika:
sbpf
add64 r1, r2           // r1 = r1 + r2
                       // opcode=add_reg, dst=1, src=2, offset=unused, imm=unused
 
add64 r1, 100          // r1 = r1 + 100  
                       // opcode=add_imm, dst=1, src=unused, offset=unused, imm=100
  • Alur Kontrol: Mengubah urutan eksekusi:
sbpf
ja +5                  // Jump forward 5 instructions unconditionally
                       // opcode=jump, dst=unused, src=unused, offset=5, imm=unused
 
jeq r1, r2, +3         // If r1 == r2, jump forward 3 instructions
                       // opcode=jump_eq_reg, dst=1, src=2, offset=3, imm=unused
 
jeq r1, 42, +3         // If r1 == 42, jump forward 3 instructions  
                       // opcode=jump_eq_imm, dst=1, src=unused, offset=3, imm=42

Pengkodean Opcode

Pengkodean opcode menangkap beberapa informasi di luar jenis operasi:

  • Kelas instruksi: Aritmatika, memori, lompatan, panggilan, dll.
  • Ukuran operasi: Operasi 32-bit vs 64-bit
  • Jenis sumber: Register vs nilai langsung
  • Operasi spesifik: Tambah vs kurang, muat vs simpan, dll.

Ini menciptakan opcode yang berbeda untuk varian instruksi. Misalnya, add64 r1, r2 (sumber register) menggunakan opcode yang berbeda dari add64 r1, 42 (sumber langsung). Demikian juga, add64 dan add32 memiliki opcode berbeda untuk ukuran operasi yang berbeda.

Operasi aritmatika lebih lanjut membedakan antara varian bertanda dan tanpa tanda. udiv64 memperlakukan nilai sebagai tanpa tanda (0 hingga 18 kuintiliun), sementara sdiv64 menangani nilai bertanda (-9 kuintiliun hingga +9 kuintiliun).

Eksekusi Instruksi

Opcode menentukan bagaimana VM menafsirkan bidang-bidang yang tersisa.

Ketika VM menemukan add64 r1, r2, ia membaca opcode dan mengenalinya sebagai operasi aritmatika 64-bit menggunakan dua register:

Bidang dst menunjukkan hasilnya masuk ke r1, bidang src menentukan r2 sebagai operan kedua, dan bidang offset dan immediate diabaikan.

Untuk add64 r1, 42, opcode berubah untuk menunjukkan operasi langsung. Sekarang dst masih menunjuk ke r1, tetapi src menjadi tidak berarti, dan bidang immediate menyediakan operan kedua (42).

Operasi memori menggabungkan beberapa bidang secara bermakna:

Untuk ldxdw r1, [r2+8], opcode menunjukkan pemuatan memori 64-bit, dst menerima nilai yang dimuat, src menyediakan alamat dasar, dan offset (8) ditambahkan untuk membuat alamat akhir r2 + 8.

Instruksi aliran kontrol mengikuti pola yang sama:

Ketika Anda menulis jeq r1, r2, +5, opcode mengenkode lompatan bersyarat yang membandingkan dua register. Jika r1 sama dengan r2, VM akan menambahkan offset (5) ke program counter, melompat maju 5 instruksi.

Opcode menentukan bidang mana yang bermakna. Format instruksi tetap konstan: opcode memberi tahu Anda cara menafsirkan setiap bidang, menghilangkan mode pengalamatan kompleks atau kasus khusus.

Pemanggilan Fungsi dan Syscall

Mekanisme pemanggilan sBPF berkembang di berbagai versi untuk kejelasan dan keamanan yang lebih baik. Hingga sBPF v3, call imm memiliki dua tujuan: nilai immediate menentukan apakah Anda memanggil fungsi internal atau menggunakan syscall.

Runtime membedakan antara keduanya berdasarkan rentang nilai immediate, dengan nomor syscall biasanya berupa bilangan bulat positif kecil seperti 16 untuk sol_log.

Dari sBPF v3 dan seterusnya, instruksi dipisahkan untuk perilaku yang eksplisit. call sekarang menangani pemanggilan fungsi internal menggunakan offset relatif, sementara syscall imm secara eksplisit memanggil fungsi runtime. Pemisahan ini membuat intensi bytecode jelas dan memungkinkan verifikasi yang lebih baik.

Pemanggilan tidak langsung melalui callx juga berkembang. Versi sebelumnya mengenkode register target di bidang immediate, tetapi dari v2 dan seterusnya, register target dienkode di bidang register sumber untuk konsistensi dengan format instruksi umum.

Tabel Referensi Opcode

Operasi Load Memory

opcodeMnemonicDeskripsi
lddwlddw dst, immLoad immediate 64-bit (slot pertama)
lddwlddw dst, immLoad immediate 64-bit (slot kedua)
ldxwldxw dst, [src + off]Load word dari memory
ldxhldxh dst, [src + off]Load halfword dari memory
ldxbldxb dst, [src + off]Load byte dari memory
ldxdwldxdw dst, [src + off]Load doubleword dari memory

Operasi Penyimpanan Memori

opcodeMnemonicDeskripsi
stwstw [dst + off], immSimpan word immediate
sthsth [dst + off], immSimpan halfword immediate
stbstb [dst + off], immSimpan byte immediate
stdwstdw [dst + off], immSimpan doubleword immediate
stxwstxw [dst + off], srcSimpan word dari register
stxhstxh [dst + off], srcSimpan halfword dari register
stxbstxb [dst + off], srcSimpan byte dari register
stxdwstxdw [dst + off], srcSimpan doubleword dari register

Operasi Aritmatika (64-bit)

opcodeMnemonicDeskripsi
add64add64 dst, immTambah immediate
add64add64 dst, srcTambah register
sub64sub64 dst, immKurang immediate
sub64sub64 dst, srcKurang register
mul64mul64 dst, immKali immediate
mul64mul64 dst, srcKali register
div64div64 dst, immBagi immediate (unsigned)
div64div64 dst, srcBagi register (unsigned)
sdiv64sdiv64 dst, immBagi immediate (signed)
sdiv64sdiv64 dst, srcBagi register (signed)
mod64mod64 dst, immModulo immediate (unsigned)
mod64mod64 dst, srcModulo register (unsigned)
smod64smod64 dst, immModulo immediate (signed)
smod64smod64 dst, srcModulo register (signed)
neg64neg64 dstNegasi

Operasi Aritmatika (32-bit)

opcodeMnemonicDeskripsi
add32add32 dst, immTambah immediate (32-bit)
add32add32 dst, srcTambah register (32-bit)
sub32sub32 dst, immKurang immediate (32-bit)
sub32sub32 dst, srcKurang register (32-bit)
mul32mul32 dst, immKali immediate (32-bit)
mul32mul32 dst, srcKali register (32-bit)
div32div32 dst, immBagi immediate (32-bit)
div32div32 dst, srcBagi register (32-bit)
sdiv32sdiv32 dst, immBagi immediate (signed 32-bit)
sdiv32sdiv32 dst, srcBagi register (signed 32-bit)
mod32mod32 dst, immModulo immediate (32-bit)
mod32mod32 dst, srcModulo register (32-bit)
smod32smod32 dst, immModulo immediate (signed 32-bit)
smod32smod32 dst, srcModulo register (signed 32-bit)

Operasi Logika (64-bit)

opcodeMnemonicDeskripsi
or64or64 dst, immBitwise OR langsung
or64or64 dst, srcBitwise OR register
and64and64 dst, immBitwise AND langsung
and64and64 dst, srcBitwise AND register
lsh64lsh64 dst, immGeser kiri langsung
lsh64lsh64 dst, srcGeser kiri register
rsh64rsh64 dst, immGeser kanan langsung
rsh64rsh64 dst, srcGeser kanan register
xor64xor64 dst, immBitwise XOR langsung
xor64xor64 dst, srcBitwise XOR register
mov64mov64 dst, immPindah langsung
mov64mov64 dst, srcPindah register
arsh64arsh64 dst, immGeser kanan aritmatika langsung
arsh64arsh64 dst, srcGeser kanan aritmatika register

Operasi Logika (32-bit)

opcodeMnemonicDeskripsi
or32or32 dst, immBitwise OR langsung (32-bit)
or32or32 dst, srcBitwise OR register (32-bit)
and32and32 dst, immBitwise AND langsung (32-bit)
and32and32 dst, srcBitwise AND register (32-bit)
lsh32lsh32 dst, immGeser kiri langsung (32-bit)
lsh32lsh32 dst, srcGeser kiri register (32-bit)
rsh32rsh32 dst, immGeser kanan langsung (32-bit)
rsh32rsh32 dst, srcGeser kanan register (32-bit)
xor32xor32 dst, immBitwise XOR langsung (32-bit)
xor32xor32 dst, srcBitwise XOR register (32-bit)
mov32mov32 dst, immPindah langsung (32-bit)
mov32mov32 dst, srcPindah register (32-bit)
arsh32arsh32 dst, immGeser kanan arit langsung (32-bit)
arsh32arsh32 dst, srcGeser kanan arit register (32-bit)

Operasi Alur Kontrol

opcodeMnemonicDescription
jaja offLompatan tanpa syarat (jump 0 = lompat ke berikutnya)
jeqjeq dst, imm, offLompat jika sama dengan nilai langsung
jeqjeq dst, src, offLompat jika sama dengan register
jgtjgt dst, imm, offLompat jika lebih besar dari nilai langsung (unsigned)
jgtjgt dst, src, offLompat jika lebih besar dari register (unsigned)
jgejge dst, imm, offLompat jika lebih besar atau sama dengan nilai langsung (unsigned)
jgejge dst, src, offLompat jika lebih besar atau sama dengan register (unsigned)
jsetjset dst, imm, offLompat jika bit diatur (mask nilai langsung)
jsetjset dst, src, offLompat jika bit diatur (mask register)
jnejne dst, imm, offLompat jika tidak sama dengan nilai langsung
jnejne dst, src, offLompat jika tidak sama dengan register
jsgtjsgt dst, imm, offLompat jika lebih besar dari nilai langsung (signed)
jsgtjsgt dst, src, offLompat jika lebih besar dari register (signed)
jsgejsge dst, imm, offLompat jika lebih besar atau sama dengan nilai langsung (signed)
jsgejsge dst, src, offLompat jika lebih besar atau sama dengan register (signed)
jltjlt dst, imm, offLompat jika kurang dari nilai langsung (unsigned)
jltjlt dst, src, offLompat jika kurang dari register (unsigned)
jlejle dst, imm, offLompat jika kurang dari atau sama dengan nilai langsung (unsigned)
jlejle dst, src, offLompat jika kurang dari atau sama dengan register (unsigned)
jsltjslt dst, imm, offLompat jika kurang dari nilai langsung (signed)
jsltjslt dst, src, offLompat jika kurang dari register (signed)
jslejsle dst, imm, offLompat jika kurang dari atau sama dengan nilai langsung (signed)
jslejsle dst, src, offLompat jika kurang dari atau sama dengan register (signed)

Operasi Pemanggilan Fungsi

opcodeMnemonicDeskripsi
callcall imm atau syscall immMemanggil fungsi atau syscall
callxcallx immPanggilan tidak langsung (register di bidang imm)
exitexit atau returnKembali dari fungsi

Operasi Byte Swap

opcodeMnemonicDeskripsi
bebe dst, immByte swap (16, 32, atau 64 bit)
lele dst, immKonversi little endian (usang)
Daftar Isi
Lihat Sumber
Blueshift © 2025Commit: 1e001ec