Anda di halaman 1dari 6

NAMA : SILVIA FARIDA

NPM : 227006031
KELAS : B

RANGKUMAN DARI VIDEO YOUTUBE MENGENAL BAHASA ASSEMBLY

Bahasa assembly dan arsitektur komputer adalah aspek penting dalam penulisan
perangkat lunak yang efisien. Meskipun tidak selalu diajarkan secara mendalam dalam sebagian
besar kursus perangkat lunak, pemahaman tentang hal ini dapat membantu dalam menulis kode
yang lebih cepat dan optimal.
Bahasa assembly adalah antarmuka terbaik untuk memahami apa yang terjadi di
bawahnya dalam arsitektur komputer. Proses kompilasi melibatkan beberapa tahap, seperti
preprocessing, kompilasi ke kode perakitan, perakitan ke kode biner, dan penghubungan untuk
menghasilkan executable akhir.
Pentingnya pemahaman bahasa assembly meliputi:
1. Memahami apa yang dilakukan kompiler: Bahasa assembly membantu mengungkapkan
apa yang dilakukan dan tidak dilakukan oleh kompiler, memungkinkan untuk melihat
perakitan yang dihasilkan.
2. Mendeteksi bug dalam kompiler: Pemahaman bahasa assembly membantu mendeteksi
bug dalam kompiler, terutama ketika menggunakan fitur yang jarang digunakan.
3. Optimasi: Bahasa assembly dapat digunakan untuk menulis kode yang lebih cepat dan
optimal daripada yang dihasilkan oleh kompiler.
4. Tulis perakitan manual: Dalam beberapa kasus, menulis perakitan manual masih
diperlukan, terutama jika kompiler tidak menghasilkan perakitan yang diinginkan.
5. Reverse engineering: Bahasa assembly penting untuk merekayasa balik program ketika
hanya sumbernya yang tersedia.
Pemahaman tentang bagaimana kompiler mengimplementasikan konstruksi bahasa C dalam
instruksi arsitektur x86 dan kemampuan membaca perakitan x86 dengan manual arsitektur
adalah keterampilan penting. Ini dapat membantu dalam menulis kode yang optimal dengan
memanfaatkan fungsi intrinsik kompiler dan bahasa assembly jika diperlukan. Dengan
pemahaman yang baik tentang bahasa assembly dan arsitektur komputer, seseorang dapat
menjadi pemrogram yang lebih kompeten dan efisien. Dalam pembicaraan tentang instruksi
arsitektur x86-64, kita membahas konsep utama dalam arsitektur set instruksi, termasuk register,
instruksi, tipe data, dan mode pengalamatan memori. Ada berbagai jenis register, termasuk
register tujuan umum, register bendera (RFLAGS), serta register vektor seperti XMM dan YMM
yang digunakan dalam operasi floating-point dalam vektor perangkat keras.
Kemudian, kita menjelaskan evolusi arsitektur x86-64 dari x86, yang awalnya memiliki kata
16-bit untuk mengakses memori. Dalam x86-64, register menjadi lebih lebar untuk mengatasi
memori yang semakin besar. Register x86-64 dapat mengakses kata-kata 64-bit dan dapat
digunakan untuk mengakses bagian-bagian yang lebih kecil dari kata itu. Format kode instruksi
x86-64 memiliki opcode diikuti oleh daftar operand. Operan dalam instruksi bisa berupa sumber
atau tujuan, tergantung pada instruksi tersebut. Sintaks AT&T dan sintaks Intel adalah dua format
yang digunakan dalam dokumentasi, dengan AT&T menjadi yang paling umum digunakan dalam
alat-alat modern. Penting untuk memahami perbedaan sintaks ini saat membaca dokumentasi
Intel. Kita juga mencantumkan beberapa opcode umum dalam arsitektur x86-64, seperti instruksi
pemindahan data, operasi aritmatika bilangan bulat, operasi logika biner, dan instruksi untuk
operasi logika Boolean. Pemahaman yang baik tentang instruksi arsitektur x86-64 sangat penting
untuk menulis kode yang efisien dan sesuai dengan perangkat keras yang digunakan, terutama
dalam konteks rekayasa kinerja perangkat lunak dan pengoptimalan kode.
Dalam instruksi arsitektur x86-64, terdapat berbagai jenis lompatan, termasuk lompatan
tanpa syarat yang selalu dieksekusi, dan lompatan bersyarat yang tergantung pada kondisi
tertentu. Selain itu, ada konsep subrutin dan operasi vektor yang melibatkan penggunaan opcode
dan akhiran untuk menggambarkan tipe data dan kode kondisi. Konsep utama yang dibahas
adalah tipe data dalam x86-64. Ada perbedaan antara tipe data dalam bahasa C dan x86-64,
dengan ukuran data yang dinyatakan dalam byte. Akhiran opcode digunakan untuk
menggambarkan tipe data, seperti b untuk kata (byte), w untuk kata (word), l atau d untuk kata
ganda (double word), q untuk kata quad (quad word), dan lainnya. Ekstensi tanda juga digunakan
dengan akhiran seperti z (zero-extend) dan s (sign-extend) untuk menggambarkan bagaimana
data diubah saat dipindahkan antar tipe data dengan ukuran yang berbeda. Lompatan bersyarat
dan gerakan bersyarat juga menggunakan sufiks untuk menunjukkan kode kondisi. Misalnya,
"ne" berarti lompatan harus diambil jika hasil perbandingan sebelumnya adalah tidak sama.
Bendera status, seperti carry, paritas, nol, tanda, trap, interupsi, tumpah, dan lainnya, digunakan
dalam instruksi bersyarat untuk mengendalikan aliran eksekusi kode. Lompatan bersyarat akan
melihat bendera-bendera ini untuk memutuskan apakah harus melompat atau melanjutkan
eksekusi kode. Pemahaman tentang opcode, akhiran tipe data, dan kode kondisi adalah penting
dalam pengembangan perangkat lunak yang efisien untuk arsitektur x86-64. Hal ini juga relevan
dalam konteks rekayasa kinerja perangkat lunak dan pengoptimalan kode.
Dalam instruksi arsitektur x86-64, bendera-bendera status yang penting meliputi:
1. Bendera Carry (CF) : Bendera ini menunjukkan apakah ada carry (pinjaman) dari bit
paling signifikan dalam operasi aritmatika.
2. Bendera Nol (ZF) : Bendera ini menunjukkan apakah hasil dari operasi ALU adalah nol.
Ini memeriksa apakah bit tanda dalam operasi ALU terakhir sudah diatur.
3. Bendera Luapan (OF) : Bendera ini mengindikasikan apakah terjadi overflow dalam
operasi aritmatika. Ini penting dalam operasi bilangan bulat yang melibatkan bit tanda.
Kode kondisi, seperti "e" untuk equal (sama) dan "ne" untuk not equal (tidak sama),
digunakan dalam instruksi lompatan bersyarat untuk menentukan kondisi di mana lompatan
harus diambil. Kode kondisi ini bergantung pada bendera-bendera status yang telah diatur selama
eksekusi instruksi sebelumnya. Selanjutnya, dalam x86-64, kita dapat mengakses memori
langsung atau tidak langsung. Mode pengalamatan langsung mengizinkan satu operan untuk
menentukan alamat memori, seperti menggunakan konstanta atau indeks register. Mode
pengalamatan tidak langsung mengizinkan kita untuk mengakses memori melalui register yang
berisi alamat memori. Dalam kasus mode pengalamatan tidak langsung, kita dapat
menambahkan offset untuk mengakses alamat yang diinginkan. Menggunakan mode
pengalamatan yang efisien sangat penting dalam pengembangan perangkat lunak karena dapat
mempengaruhi kinerja program. Mengambil data dari memori biasanya lebih lambat daripada
mengambilnya dari register, oleh karena itu, perangkat keras didesain dengan caching untuk
mempercepat akses ke memori. Pemahaman ini penting dalam pengembangan kode yang efisien
dan optimal.
Pada bahasa assembly x86-64, terdapat beberapa aspek penting yang perlu dipahami:
1. Instruksi-Pointer Relatif : Dalam beberapa situasi, alih-alih mengindeks dari daftar tujuan
umum, kita dapat mengindeks dari pointer instruksi. Ini memungkinkan kita untuk
melompat ke alamat yang relatif terhadap posisi instruksi saat ini, yang berguna dalam
pengaturan seperti lompatan ke beberapa instruksi di masa depan.
2. Mode Pengalamatan : Terdapat mode pengalamatan langsung dan tidak langsung. Mode
pengalamatan langsung memungkinkan satu operan untuk menentukan alamat memori,
sementara mode pengalamatan tidak langsung memungkinkan kita mengakses memori
melalui register yang berisi alamat memori. Ini memungkinkan pengindeksan memori
yang fleksibel.
3. Instruksi Lompatan : Instruksi lompatan digunakan untuk mengubah aliran eksekusi
program. Mereka menggunakan label sebagai operan untuk menunjukkan lokasi dalam
kode yang harus dijangkau. Label dapat berupa simbol, alamat yang tepat, atau alamat
yang relatif terhadap pointer instruksi.
4. Idiom Pengkodean : Terdapat beberapa idiom pengkodean yang umum dalam bahasa
assembly x86-64. Contohnya, instruksi `XOR` digunakan untuk menukar nilai dengan
nol dalam sebuah register. Instruksi `TEST` digunakan untuk memeriksa apakah suatu
register adalah nol dan dapat digunakan dalam instruksi lompatan bersyarat. Ada juga
instruksi "no-op" seperti `NOP` yang digunakan untuk alasan optimasi atau penyesuaian
cache.
Bahasa assembly x86-64 memungkinkan kontrol yang sangat rinci atas perangkat keras
komputer dan efisien dalam beberapa kasus. Namun, memahami instruksi dan mode
pengalamatan serta menggunakan idiom pengkodean yang benar adalah kunci dalam
mengembangkan kode yang efisien dan optimal.
Dalam bahasa assembly x86-64, terdapat perangkat keras floating-point dan vektor yang penting
untuk dipahami:
1. Floating-Point Unit (FPU) : Pada awalnya, komputer 80-86 tidak memiliki unit floating-
point, dan operasi floating-point dilakukan dalam perangkat lunak. Kemudian, chip
pendamping untuk floating-point dikembangkan, dan seiring dengan perkembangan
teknologi, ini diintegrasikan ke dalam CPU. Instruksi SSE, AVX, dan x87 mendukung
operasi floating-point skalar dengan presisi tunggal (float) dan ganda (double).
2. SSE dan AVX : Instruksi SSE (Streaming SIMD Extensions) dan AVX (Advanced Vector
Extensions) digunakan untuk operasi floating-point. SSE mendukung operasi skalar
dengan panjang vektor 128 bit, sementara AVX memperluasnya menjadi 256 bit.
Instruksi-instruksi ini menggunakan register XMM (SSE) dan YMM (AVX) serta
berbagai jenis tipe data floating-point.
3. AVX-512 : AVX-512 adalah perkembangan terbaru dalam instruksi vektor x86-64. Ini
memperluas panjang vektor menjadi 512 bit dan memungkinkan operasi yang lebih besar
dalam satu instruksi.
4. Instruksi Vektor : Instruksi vektor memungkinkan operasi simultan pada beberapa elemen
dalam register vektor. Unit vektor CPU memiliki beberapa "jalur" (lanes) yang dapat
melakukan operasi yang sama pada elemen-elemen yang sesuai dalam register vektor.
5. Pengindeksan Memori yang Selaras : Operasi vektor sering memerlukan pengindeksan
memori yang selaras dengan panjang vektor. Ini dapat memengaruhi kinerja, karena
beberapa arsitektur mendukung operasi vektor yang tidak selaras, tetapi dengan
penurunan kinerja.
6. Operasi Lintas Jalur : Beberapa arsitektur mendukung operasi lintas jalur, seperti
penggabungan atau pemecahan elemen-elemen vektor, permutasi, atau pengacakan.
Operasi semacam ini dapat meningkatkan efisiensi dalam pemrosesan data vektor.
7. Awalan Instruksi : Awalan instruksi, seperti "v" dalam AVX, "p" untuk instruksi vektor
bilangan bulat, dan lainnya, digunakan untuk membedakan instruksi-instruksi vektor dari
instruksi skalar tradisional.
Instruksi vektor memungkinkan eksekusi paralel yang efisien dari operasi floating-point dan
vektor dalam satu instruksi, yang dapat meningkatkan kinerja dalam pemrosesan data yang
sesuai. Penggunaan yang tepat dari instruksi-instruksi ini dan pemahaman tentang jenis tipe data
yang sesuai adalah kunci untuk mengoptimalkan kode assembly dalam bahasa x86-64.
Pada dasarnya, arsitektur komputer umumnya melibatkan serangkaian tahap pemrosesan
untuk menjalankan instruksi. Salah satu model yang umum adalah prosesor 5 tahap, yang
mencakup:
1. Pengambilan Instruksi: Instruksi diambil dari memori dalam tahap ini.
2. Decode Instruksi : Instruksi didekodekan untuk memahami opcode dan mode
pengalamatan yang diperlukan.
3. Eksekusi : Operasi aritmatika atau logika dijalankan oleh ALU (Arithmetic Logic Unit)
berdasarkan instruksi.
4. Pengalamatan Memori : Jika instruksi membutuhkan akses ke memori, tahap ini
digunakan untuk membaca atau menulis data ke lokasi memori yang sesuai.
5. Tulis Kembali : Hasil eksekusi ditulis kembali ke register.
Prosesor modern, seperti Intel Haswell, memiliki lebih banyak tahap pemrosesan, sekitar 14
hingga 19 tahap, yang meningkatkan efisiensi dan kinerja. Namun, rincian internal prosesor
seringkali tidak diungkapkan secara terbuka.
Beberapa fitur desain prosesor yang penting untuk dipahami adalah:
1. Perangkat Keras Vektor : Prosesor modern mendukung operasi vektor yang
memungkinkan eksekusi simultan pada beberapa elemen data. Ini berguna untuk operasi
yang melibatkan data vektor, seperti pemrosesan gambar atau ilmu pengetahuan
komputasi.
2. Super Scalar dan Eksekusi di Luar Pesanan : Prosesor modern dapat menjalankan
beberapa instruksi secara simultan dan mungkin menjalankannya di luar urutan aslinya
untuk meningkatkan kinerja.
3. Prediksi Cabang : Fitur ini memungkinkan prosesor untuk memprediksi jalur instruksi
yang akan diambil berikutnya. Ini membantu menghindari penundaan yang disebabkan
oleh skenario percabangan (branch misprediction).
4. Caching : Prosesor menggunakan cache untuk menyimpan data yang sering diakses,
sehingga mengurangi latensi akses ke memori utama. Ini adalah contoh dari penggunaan
lokalitas untuk meningkatkan kinerja.
5. Paralelisme : Paralelisme dapat berarti paralelisme tingkat kata (bit-level) atau
paralelisme tingkat instruksi (ILP). Ini mencakup vektorisasi (operasi pada elemen-
elemen vektor) dan multicore (penggunaan beberapa inti prosesor).
Pengoptimalan kinerja prosesor modern sering melibatkan penggunaan efisien dari fitur-fitur
ini, serta pemahaman tentang bagaimana instruksi dieksekusi dan bagaimana data diakses dalam
memori. Paralelisme tingkat instruksi dalam arsitektur prosesor melibatkan upaya untuk
menjalankan beberapa instruksi secara bersamaan guna meningkatkan throughput. Namun, ada
beberapa hambatan yang perlu diatasi, termasuk "hazard" yang dapat menghambat eksekusi
instruksi. Ada tiga jenis hazard yang umum:
1. Bahaya Struktural : Terjadi ketika dua instruksi mencoba menggunakan unit fungsional
yang sama secara bersamaan. Jika unit tersebut sedang digunakan, satu instruksi harus
menunggu.
2. Bahaya Data : Terjadi ketika instruksi tergantung pada hasil instruksi sebelumnya dalam
pipa. Instruksi kedua harus menunggu sampai instruksi pertama menulis nilai yang
dibutuhkan.
3. Bahaya Kontrol : Terjadi ketika instruksi tidak dapat menjalankan instruksi berikutnya
karena tidak tahu arah lompatan yang akan diambil.
Untuk mengatasi bahaya data, ada tiga jenis ketergantungan yang harus diperhatikan:
• Ketergantungan Sejati (Read After Write Dependency) : Instruksi kedua bergantung pada
hasil instruksi pertama karena instruksi kedua membaca data yang ditulis oleh instruksi
pertama.
• Anti-Ketergantungan (Write After Read Dependency) : Instruksi kedua harus menunggu
sampai instruksi pertama membaca nilai yang akan ditulis oleh instruksi kedua.
• Ketergantungan Output (Write After Write Dependency) : Instruksi kedua dan pertama
mencoba menulis ke lokasi yang sama dalam register atau memori.
Untuk meningkatkan paralelisme instruksi, prosesor modern memecah instruksi menjadi
operasi yang lebih sederhana, yang disebut "micro-ops," dan dapat menjalankannya di beberapa
unit fungsional sekaligus. Selain itu, bypassing memungkinkan instruksi untuk mengakses hasil
instruksi sebelumnya tanpa menunggu data tersebut masuk ke register. Prediksi cabang juga
digunakan untuk menghindari penundaan akibat cabang yang salah. Jika prediksi salah, prosesor
harus membatalkan eksekusi spekulatif dan biayanya dapat signifikan, sekitar 15 hingga 20
siklus. Selain itu, eksekusi spekulatif juga digunakan, di mana prosesor menebak hasil cabang
dan melanjutkan eksekusi. Jika tebakan benar, semuanya berjalan dengan baik, tetapi jika salah,
eksekusi harus dibatalkan. Semua ini adalah upaya yang kompleks untuk memanfaatkan
sebanyak mungkin instruksi dalam pipa secara paralel dan menghindari penundaan yang dapat
merugikan kinerja prosesor.

Anda mungkin juga menyukai