Jump to content

Accessing Information

From Haidhi Wiki
Revision as of 06:45, 9 October 2026 by SanzSkuy (talk | contribs) (Created page with "CPU x86-64 punya '''16 general-purpose register''' berukuran 64-bit. Register ini menyimpan data integer dan pointer. == Sejarah penamaan == Penamaan register berlapis karena evolusi instruction set: {| class="wikitable" ! Generasi !! Lebar !! Nama register !! Catatan |- | 8086 || 16-bit || <code>%ax</code>, <code>%bx</code>, <code>%cx</code>, <code>%dx</code>, <code>%si</code>, <code>%di</code>, <code>%bp</code>, <code>%sp</code> || Nama mencerminkan fungsi (accumulat...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

CPU x86-64 punya 16 general-purpose register berukuran 64-bit. Register ini menyimpan data integer dan pointer.

Sejarah penamaan

Penamaan register berlapis karena evolusi instruction set:

Generasi Lebar Nama register Catatan
8086 16-bit %ax, %bx, %cx, %dx, %si, %di, %bp, %sp Nama mencerminkan fungsi (accumulator, counter, source/destination index, stack pointer)
IA32 32-bit %eax … %ebp Prefix e = extended
x86-64 64-bit %rax … %rbp Prefix r
x86-64 (baru) 64-bit %r8 … %r15 Konvensi baru, suffix d/w/b untuk 32/16/8-bit

Sub-register (nested boxes)

%rax, %eax, %ax, %al bukan empat register berbeda, melainkan satu register fisik yang diakses dengan lebar berbeda:

|<------------------- %rax (64 bit) ------------------->|
                           |<------ %eax (32 bit) ----->|
                                          |<- %ax (16) ->|
                                                 |%al(8)|
  • Operasi byte → least significant byte
  • Operasi 16-bit → 2 byte terbawah
  • Operasi 32-bit → 4 byte terbawah
  • Operasi 64-bit → seluruh register

Aturan sisa byte saat menulis ke register

Ketika instruksi menghasilkan nilai kurang dari 8 byte ke register:

Ukuran tulis Efek ke byte sisanya
1 byte / 2 byte Tidak berubah
4 byte 4 byte atas di-nol-kan

Contoh, dengan %rax = 0x1122334455667788:

movb $0xAA, %al      # %rax = 0x11223344556677AA  (sisanya utuh)
movw $0xAAAA, %ax    # %rax = 0x112233445566AAAA  (sisanya utuh)
movl $0xAAAA, %eax   # %rax = 0x000000000000AAAA  (4 byte atas = 0)

Kenapa? Aturan zero-upper diadopsi saat ekspansi IA32 → x86-64 supaya hasil tulisan tidak bergantung pada isi lama register (menghindari partial register dependency), sehingga eksekusi out-of-order lebih lancar. Compiler memanfaatkannya, misalnya mov $0x0,%eax untuk return 0.

Peran register (System V ABI)

Register Peran
%rax Return value
%rdi, %rsi, %rdx, %rcx, %r8, %r9 Argumen ke-1 sampai ke-6 (urut)
%rsp Stack pointer (spesial, dipakai otomatis oleh push/pop/call/ret)
%rbx, %rbp, %r12–%r15 Callee saved: fungsi yang dipanggil wajib mengembalikan nilainya
%r10, %r11 (+ register argumen & %rax) Caller saved: boleh dirusak oleh fungsi yang dipanggil

Jembatan keledai urutan argumen: "Diane's Silk Dress Costs $89" → di, si, dx, cx, 8, 9.

Contoh: multstore

push %rbx          # rbx callee-saved → simpan nilai lama
mov  %rdx,%rbx     # rdx = argumen ke-3 (dest), amankan di rbx
call mult2         # x, y masih di rdi & rsi
mov  %rax,(%rbx)   # *dest = hasil mult2 (rax)
pop  %rbx          # pulihkan rbx
ret

dest dipindah ke %rbx karena %rdx caller-saved (bisa dirusak mult2), sedangkan %rbx dijamin selamat melewati call.

3.4.1 Operand Specifiers

Tiga jenis operand

Jenis Contoh Arti
Immediate $-577, $0x1F Konstanta, nilai tertanam di instruksi
Register %rax, %al Isi register, notasi R[ra]
Memory 0x104, (%rax), 8(%rax) Isi memori di effective address, notasi M[Addr]

Perhatian: $0x10 = angka 16, sedangkan 0x10 (tanpa $) = isi memori di alamat 16.

%rax vs (%rax)

  • %rax → isi register itu sendiri (seperti p di C)
  • (%rax) → isi register dipakai sebagai alamat, lalu baca memori di alamat itu (seperti *p di C)

Kurung ( ) di AT&T = dereference. Di AT&T, register wajib pakai %; rax tanpa % akan dianggap nama simbol.

Maksud AT&T (gcc, CS:APP) Intel (NASM, MASM)
Isi register %rax rax
Isi memori di alamat rax (%rax) [rax]
Konstanta $5 5

Bentuk umum memory reference

Imm(rb, ri, s)   →   alamat = Imm + R[rb] + R[ri] · s
  • Imm: displacement konstanta
  • rb: base register (64-bit)
  • ri: index register (64-bit)
  • s: skala, hanya 1, 2, 4, atau 8 (ukuran char, short, int, long/pointer)

Semua mode lain adalah kasus khusus dengan komponen yang dihilangkan:

Form Effective address Nama
Imm Imm Absolute
(rb) R[rb] Indirect
Imm(rb) Imm + R[rb] Base + displacement
(rb,ri) R[rb] + R[ri] Indexed
Imm(rb,ri) Imm + R[rb] + R[ri] Indexed
(,ri,s) R[ri]·s Scaled indexed
Imm(,ri,s) Imm + R[ri]·s Scaled indexed
(rb,ri,s) R[rb] + R[ri]·s Scaled indexed
Imm(rb,ri,s) Imm + R[rb] + R[ri]·s Scaled indexed

Tambahan x86-64 yang tidak ada di tabel: RIP-relative, misalnya lea 0x0(%rip),%rdi, alamat dihitung relatif terhadap instruksi berikutnya (dipakai untuk data global/string literal).

Kegunaan: akses array dan struct

long a[100];
x = a[i];

Dengan a di %rdx dan i di %rcx:

movq (%rdx,%rcx,8), %rax     # alamat = a + i*8

Satu instruksi tanpa perkalian terpisah. Untuk arr[i].field, offset field masuk ke Imm.

Cara menghitung nilai operand

Untuk memory operand selalu dua langkah:

  1. Hitung alamat: Imm + R[rb] + R[ri]·s
  2. Baca isi memori di alamat tersebut

Jebakan umum:

  • Displacement tanpa 0x adalah desimal: 260 = 0x104, 16 = 0x10
  • Koma di depan (0xFC(,%rcx,4)) berarti tanpa base register
  • Perhatikan carry saat menjumlah hex: 0xFC + 4 = 0x100
  • Jangan berhenti di alamat; jawaban adalah isi memorinya

Contoh (Practice Problem 3.1)

Data: %rax = 0x100, %rcx = 0x1, %rdx = 0x3; memori 0x100→0xFF, 0x104→0xAB, 0x108→0x13, 0x10C→0x11.

Operand Jenis Alamat Nilai
%rax Register — 0x100
0x104 Absolute 0x104 0xAB
$0x108 Immediate — 0x108
(%rax) Indirect 0x100 0xFF
4(%rax) Base + displacement 4 + 0x100 = 0x104 0xAB
9(%rax,%rdx) Indexed 9 + 0x100 + 3 = 0x10C 0x11
260(%rcx,%rdx) Indexed 0x104 + 1 + 3 = 0x108 0x13
0xFC(,%rcx,4) Scaled indexed 0xFC + 1·4 = 0x100 0xFF
(%rax,%rdx,4) Scaled indexed 0x100 + 3·4 = 0x10C 0x11