CHAPTER 7

 CHAPTER 7 
 Using Assembly Language with C/C++



## Pendahuluan

Menggabungkan Kekuatan C++ dan Bahasa Assembly

Di dunia pemrograman modern, sangat jarang kita membangun sebuah sistem sepenuhnya hanya dengan menggunakan bahasa assembly. Sebaliknya, pendekatan yang jauh lebih umum dan efisien adalah dengan menggabungkan kekuatan bahasa tingkat tinggi seperti C++ dengan kecepatan dan kontrol tingkat rendah dari bahasa assembly.

Mengapa kita melakukan ini? Karena ada tugas-tugas tertentu—terutama yang berkaitan langsung dengan perangkat keras seperti driver atau kontrol peripheral—yang sulit atau tidak efisien jika dikerjakan murni dengan C++. Bahasa assembly memberi kita akses langsung ke instruksi-instruksi khusus prosesor, seperti MMX dan SEC yang ada pada CPU modern, yang mungkin tidak didukung secara langsung oleh C++.

Dalam seri artikel ini, kita akan mendalami ide untuk mencampur kode C++ dan assembly. Kita akan menggunakan Microsoft Visual C++ Express, sebuah tool gratis yang bisa Anda unduh. Namun, konsep yang kita pelajari di sini bersifat universal dan dapat diterapkan pada kompiler C++ standar lainnya. Mari kita mulai petualangan untuk membuka potensi penuh dari perangkat keras kita!


## Apa Saja yang Akan Anda Pelajari?

Setelah mengikuti seri tutorial ini, Anda akan mampu untuk:

  1. Menggunakan bahasa assembly di dalam blok _asm pada kode C++.

  2. Mempelajari aturan-aturan penting untuk pengembangan perangkat lunak mode campuran (C++ dan Assembly).

  3. Menggunakan struktur data dan sintaks C++ yang umum bersama dengan bahasa assembly.

  4. Memanfaatkan antarmuka 16-bit (DOS) dan 32-bit (Microsoft Windows) menggunakan kode assembly.

  5. Menggunakan objek bahasa assembly dan menggabungkannya dengan program C++.


  • 7–1 USING ASSEMBLY LANGUAGE WITH C++ FOR 16-BIT DOS APPLICATIONS


          EXAMPLE 7-1

Kode ini adalah program C dengan sisipan inline assembly yang bertujuan membaca satu karakter keyboard, dan hanya menampilkannya jika karakter itu adalah angka 0-9.

Berikut adalah penjelasan untuk setiap baris dari kode assembly tersebut.

## Penjelasan Kode Baris per Baris

### Langkah 1: Membaca Input dari Keyboard

  • mov ah, 8

    Perintah ini memindahkan (move) nilai 8 ke dalam register ah. Dalam pemrograman DOS, nilai di register ah menentukan fungsi apa yang akan dipanggil. Fungsi 8 adalah untuk "membaca satu karakter dari keyboard tanpa menampilkannya ke layar (no echo)".

  • int 21h

    Ini adalah perintah untuk memanggil interrupt DOS 21h, yang merupakan gerbang utama untuk layanan sistem operasi. Perintah ini akan menjalankan fungsi yang sudah disiapkan di register ah (yaitu fungsi 8). Setelah dieksekusi, karakter yang ditekan pengguna akan disimpan di dalam register al.

### Langkah 2: Menyaring (Filter) Input

  • cmp al, '0'

    Perintah ini membandingkan (compare) nilai ASCII dari karakter di al dengan nilai ASCII dari karakter '0'.

  • jb big

    Jump if Below. Jika hasil perbandingan sebelumnya menunjukkan nilai al lebih rendah dari '0' (misalnya, pengguna menekan spasi atau huruf), program akan langsung melompat ke label big:.

  • cmp al, '9'

    Jika karakter lolos dari saringan pertama, perintah ini membandingkannya dengan nilai ASCII dari karakter '9'.

  • ja big

    Jump if Above. Jika nilai al lebih tinggi dari '9' (misalnya, karakter { atau |), program akan melompat ke label big:. Kedua perintah cmp dan j ini memastikan hanya angka 0-9 yang akan diproses lebih lanjut.

### Langkah 3: Menampilkan (Echo) Karakter yang Valid

  • mov dl, al

    Baris ini hanya akan dieksekusi jika karakter yang diinput adalah angka 0-9. Perintah ini menyalin (move) karakter dari al ke register dl. Register dl adalah register standar yang digunakan untuk menampilkan karakter di DOS.

  • mov ah, 2

    Perintah ini memindahkan nilai 2 ke register ah. Fungsi 2 adalah layanan DOS untuk "menampilkan satu karakter ke layar".

  • int 21h

    Memanggil interrupt DOS lagi. Kali ini, ia akan menjalankan fungsi 2, yaitu menampilkan karakter apa pun yang saat ini ada di dalam register dl.

### Langkah 4: Titik Akhir

  • big:

    Ini adalah sebuah label penanda. Jika input tidak valid, program akan melompat ke sini, melewati semua instruksi untuk menampilkan karakter, dan langsung mengakhiri blok _asm.






         TABLE 7-1

1. Pengertian Compiler Switch

Compiler switch (atau sering disebut flag) adalah sebuah parameter atau perintah tambahan yang Anda sertakan saat mengkompilasi program. Perintah ini berfungsi untuk mengubah cara kerja kompiler, misalnya untuk mengaktifkan fitur tertentu, menampilkan peringatan (warnings), atau—seperti dalam kasus ini—melakukan optimasi untuk perangkat keras spesifik. Switch di sini ditandai dengan awalan /G.

2. Fungsi Opsi /G

  • /G1 (Target: 8088/8086): Opsi ini menginstruksikan compiler untuk menghasilkan kode yang kompatibel dengan prosesor paling dasar dalam keluarga x86, yaitu Intel 8088 dan 8086. Kode yang dihasilkan menggunakan set instruksi 16-bit standar tanpa adanya fitur-fitur modern. Ini memastikan kompatibilitas maksimal dengan perangkat keras lawas yang menjadi cikal bakal komputer pribadi (PC).

  • /G2 (Target: 80188/80186/80286): Opsi ini menargetkan generasi prosesor berikutnya. Intel 80188/80186 menambahkan beberapa instruksi baru yang lebih efisien, dan 80286 memperkenalkan "protected mode" yang menjadi dasar untuk multitasking. Dengan memilih /G2compiler akan memanfaatkan instruksi tambahan tersebut untuk menghasilkan kode yang sedikit lebih cepat dan efisien dibandingkan target /G1.

  • /G3 (Target: 80386): Ini adalah lompatan besar karena 80386 merupakan prosesor 32-bit pertama dalam keluarga Intel. Menggunakan switch /G3 memungkinkan compiler untuk menghasilkan kode yang memanfaatkan arsitektur 32-bit, termasuk register yang lebih besar dan mode memori yang lebih canggih. Ini membuka jalan untuk aplikasi yang lebih kuat dan sistem operasi modern.


## Perbandingan Opsi Kompiler /G1, /G2, dan /G3

Fitur/G1/G2/G3
Target ProsesorIntel 8088 / 8086Intel 80188 / 80186 / 80286Intel 80386
Arsitektur16-bit16-bit32-bit
Inovasi UtamaArsitektur x86 dasar, fondasi dari semua PC modern.Pengenalan Protected Mode (pada 80286) dan beberapa instruksi baru yang lebih efisien.Revolusi 32-bit: Pengenalan register 32-bit (EAX, dll.) dan mode pengalamatan memori 32-bit.
Implikasi PerformaPerforma dasar. Kode yang dihasilkan tidak efisien untuk standar modern.Sedikit lebih cepat dari /G1 karena bisa menggunakan instruksi yang lebih optimal untuk tugas tertentu.Lompatan Performa Besar. Mampu memproses data dalam bongkahan 32-bit, jauh lebih cepat untuk kalkulasi dan manajemen memori.
Keunggulan UtamaKompatibilitas Maksimal. Program dapat berjalan di hampir semua mesin PC-compatible, bahkan yang paling kuno.Keseimbangan antara kompatibilitas dengan mesin AT-class (286) dan sedikit peningkatan performa.Akses ke Kekuatan 32-bit. Membuka potensi performa yang signifikan dan kemampuan mengelola memori lebih besar.
Kelemahan UtamaKinerja Terbatas. Tidak dapat memanfaatkan inovasi CPU apa pun setelah tahun 1981.Menghilangkan Kompatibilitas Awal. Program tidak akan berjalan pada PC generasi pertama (8088/8086).Tidak Kompatibel Mundur. Program tidak akan berjalan sama sekali di mesin 16-bit murni seperti 80286 atau 8086.

        EXAMPLE 7-2



Kode ini adalah program C dengan sisipan inline assembly (_asm) yang berfungsi sebagai kalkulator penjumlahan dua digit sederhana. Program ini mengharapkan input dari pengguna dalam format angka+angka (contoh: 5+3) dan akan langsung menampilkan hasilnya.

Berikut adalah penjelasan untuk setiap baris dan blok kode assembly tersebut.


## Penjelasan Kode Baris per Baris

### Langkah 1: Membaca Angka Pertama

  • mov ah, 1

    Mempersiapkan register ah dengan nilai 1 untuk memanggil fungsi DOS "baca karakter dari keyboard dengan echo".

  • int 21h

    Memanggil interrupt DOS. Karakter angka pertama yang diketik pengguna (misalnya '5') akan dibaca dan disimpan di register al.

  • mov a, al

    Menyimpan karakter angka pertama dari al ke dalam variabel C bernama a.

### Langkah 2: Membaca Operator '+' dan Angka Kedua

  • mov ah, 1 dan int 21h

    Membaca karakter berikutnya, yang diharapkan adalah tanda +.

  • cmp al, '+'

    Membandingkan (compare) karakter yang baru dibaca dengan karakter '+'.

  • jne endl

    Jump if Not Equal. Jika karakter yang dibaca bukan +, program akan langsung lompat ke akhir (label endl:), karena input tidak sesuai format.

  • mov ah, 1 dan int 21h

    Jika input adalah +, program akan membaca karakter berikutnya, yaitu angka kedua (misalnya '3').

  • mov b, al

    Menyimpan karakter angka kedua dari al ke dalam variabel C bernama b.

### Langkah 3: Proses Penjumlahan

  • mov ah, 2, mov dl, '=', int 21h

    Menampilkan karakter = ke layar sebagai penanda sebelum hasil.

  • mov ah, 0

    Membersihkan register ah (mengisinya dengan nol). Ini penting untuk langkah aaa selanjutnya.

  • mov al, a

    Mengambil kembali karakter angka pertama dari variabel a dan memasukkannya ke al.

  • add al, b

    Menambahkan (add) nilai ASCII dari angka kedua (di b) ke al. Hasilnya masih dalam format ASCII yang belum benar secara matematis.

  • aaa

    ASCII Adjust for Addition. Ini adalah instruksi kunci. Ia mengonversi hasil penjumlahan ASCII di al menjadi format BCD (Binary Coded Decimal) yang benar. Jika hasilnya lebih dari 9, al akan berisi digit satuan dan ah akan berisi digit puluhan (nilai 1).

### Langkah 4: Menampilkan Hasil

  • add ax, 3030h

    Menambahkan 30h (nilai ASCII untuk '0') ke ah dan al secara bersamaan. Ini mengubah kedua digit (puluhan di ah dan satuan di al) menjadi karakter ASCII yang dapat dicetak.

  • cmp ah, '0'

    Membandingkan digit puluhan di ah dengan karakter '0'.

  • je down

    Jump if Equal. Jika digit puluhannya adalah '0' (artinya hasil penjumlahan kurang dari 10), program akan lompat ke label down: untuk hanya mencetak digit satuan.

  • push ax, mov dl, ah, ..., pop ax

    Blok ini dieksekusi jika hasilnya 10 atau lebih. Ia mencetak digit puluhan (ah) ke layar. push ax dan pop ax digunakan untuk menyimpan dan mengembalikan nilai ax karena proses pencetakan akan mengubah nilai ah.

  • down:

    Label tujuan untuk mencetak digit satuan.

  • mov dl, al, mov ah, 2, int 21h

    Mencetak digit satuan (al) ke layar.

### Langkah 5: Akhir Program

  • endl:

    Label akhir program. Program akan berakhir di sini setelah selesai mencetak atau jika input tidak valid.


        EXAMPLE 7-3

Kode ini adalah program C dengan sisipan inline assembly yang bertujuan untuk mengambil sebuah kalimat dan menampilkannya kembali ke layar, di mana setiap kata dicetak pada baris yang baru.

Berikut adalah penjelasan untuk setiap baris dan blok dari kode tersebut.


## Penjelasan Kode Baris per Baris

### Bagian C: Kerangka Program

  • char strings[] = "..."

    Mendefinisikan sebuah variabel C bernama strings yang berisi kalimat yang akan diproses.

  • int sc = -1;

    Mendefinisikan sebuah variabel C bernama sc (singkatan dari string counter) sebagai -1. Ini akan digunakan sebagai indeks untuk mengakses setiap karakter dalam strings.

  • while (strings[sc++] != 0)

    Ini adalah loop utama yang akan terus berjalan selama karakter yang diperiksa bukan karakter null (penanda akhir string). sc++ berarti nilai sc akan digunakan terlebih dahulu untuk mengakses array, baru kemudian nilainya dinaikkan. Karena sc dimulai dari -1, pada putaran pertama ia akan mengakses strings[0].

### Bagian Assembly: Logika Inti di Dalam Loop

Blok _asm ini dieksekusi untuk setiap karakter di dalam string.

  • push si

    Menyimpan (push) nilai dari register si ke dalam stack. Ini adalah praktik yang baik untuk menjaga nilai register agar tidak berubah setelah blok assembly selesai, karena bisa saja register tersebut sedang digunakan oleh bagian lain dari program C.

  • mov si, sc

    Memindahkan (move) nilai indeks saat ini dari variabel C sc ke dalam register si. Register si (Source Index) sering digunakan untuk menunjuk alamat dalam operasi string.


  • mov dl, strings[si]

    Mengambil karakter dari array strings pada posisi indeks si dan menyimpannya di register dl. Register dl digunakan untuk menyimpan karakter yang akan ditampilkan ke layar.

  • cmp dl, ' '

    Membandingkan (compare) karakter di dl dengan karakter spasi (' ').

  • jne next

    Jump if Not Equal. Jika karakter tersebut bukan spasi, maka program akan melompat ke label next:.


  • Blok Jika Karakter ADALAH Spasi (Baris mov ah,2 hingga mov dl,13):

    Blok ini hanya berjalan jika jne tidak terjadi (artinya karakter adalah spasi).

    • mov ah, 2 dan mov dl, 10 dan int 21h: Ini adalah urutan perintah DOS untuk mencetak karakter. ah=2 adalah fungsi cetak, dl=10 adalah kode ASCII untuk Line Feed (pindah baris ke bawah). int 21h mengeksekusinya.

    • mov dl, 13 dan int 21h: Perintah yang sama diulang, tetapi kali ini dl=13 adalah kode ASCII untuk Carriage Return (mengembalikan kursor ke awal baris). Kombinasi keduanya akan membuat baris baru.


  • next:

    Ini adalah label tujuan jika karakter yang diperiksa bukan spasi.

  • mov ah, 2 dan int 21h

    Perintah standar DOS untuk mencetak karakter yang ada di register dl. Karena dl masih berisi karakter asli dari string, maka karakter itulah yang akan ditampilkan di layar.

  • pop si

    Mengembalikan nilai asli register si dari stack yang disimpan di awal. Ini adalah pasangan dari perintah push si.



        EXAMPLE 7-4

Kode ini adalah program C dengan sebuah fungsi (Str) yang menggunakan inline assembly untuk menampilkan isi dari sebuah string karakter ke layar, diikuti dengan baris baru.

Berikut adalah penjelasan untuk setiap baris dan blok dari kode tersebut.


## Penjelasan Kode Baris per Baris

### Bagian C: Inisialisasi dan Pemanggilan Fungsi

  • char string1[] = ...

    Mendefinisikan tiga buah string (kalimat) yang berbeda dan menyimpannya dalam tiga variabel array C.

  • void main(void)

    Fungsi utama tempat program dimulai.

  • Str(string1);

    Memanggil fungsi Str dan mengirimkan alamat dari string1 sebagai argumen. Program akan menjalankan fungsi Str untuk mencetak kalimat pertama. Proses ini diulang untuk string2 dan string3.


### Fungsi Str dan Logika Assembly

Fungsi Str menerima satu argumen: string_adr, yang merupakan pointer (penunjuk alamat memori) ke awal dari sebuah string.

  • _asm { ... }

    Memulai blok di mana kode bahasa assembly akan ditulis.

  • mov bx, string_adr

    Memindahkan (move) alamat string yang diterima dari C (string_adr) ke dalam register bx. Register bx sekarang berfungsi sebagai penunjuk ke karakter saat ini di dalam string.

  • top:

    Ini adalah sebuah label yang menandai titik awal dari loop pencetakan karakter.

  • mov ah, 2

    Menyiapkan register ah dengan nilai 2 untuk memanggil fungsi DOS "tampilkan karakter".

  • mov dl, [bx]

    Mengambil karakter dari alamat memori yang ditunjuk oleh bx dan menyimpannya di register dl. Tanda kurung siku [bx] artinya "ambil nilai dari alamat yang ada di bx".

  • inc bx

    Menaikkan (increment) nilai bx sebesar satu, sehingga sekarang bx menunjuk ke karakter berikutnya di dalam string.

  • cmp al, 0

    Catatan Penting: Baris ini sepertinya mengandung bug atau kesalahan logika. Tujuannya adalah untuk memeriksa apakah karakter yang baru dibaca adalah karakter null (nilai 0, penanda akhir string). Namun, karakter tersebut ada di register dl, bukan al. Seharusnya perintah ini adalah cmp dl, 0. Jika kita asumsikan tujuannya benar, maka baris ini membandingkan (compare) karakter dengan 0.

  • je bot

    Jump if Equal. Jika perbandingan sebelumnya sama (artinya karakter adalah null), maka program akan melompat ke label bot:, keluar dari loop.

  • int 21h

    Memanggil interrupt DOS. Karena ah berisi 2, maka fungsi "tampilkan karakter" akan dieksekusi, mencetak karakter yang ada di dl ke layar.

  • jmp top

    Lompat (jump) kembali ke label top: tanpa syarat untuk memproses karakter berikutnya.

  • bot:

    Label ini adalah tujuan lompatan ketika akhir string (null) telah tercapai.

  • Blok Baris Baru (mov dl, 13 hingga int 21h terakhir):

    Setelah seluruh string dicetak, blok ini akan dieksekusi. Tujuannya adalah untuk mencetak baris baru.

    • mov dl, 13 dan int 21h: Mencetak karakter Carriage Return (CR), yang mengembalikan kursor ke awal baris.

    • mov dl, 10 dan int 21h: Mencetak karakter Line Feed (LF), yang memindahkan kursor satu baris ke bawah.


        EXAMPLE 7-5



Kode ini adalah sebuah program C yang mendefinisikan sebuah struktur data (mirip database kecil) dan kemudian menggunakan beberapa fungsi yang ditulis dalam bahasa assembly untuk menampilkan isi dari struktur data tersebut ke layar.

Berikut adalah penjelasan untuk setiap baris dan blok dari kode tersebut.


## Penjelasan Kode Baris per Baris

### Bagian 1: Definisi dan Inisialisasi Data (C)

  • typedef struct records { ... } RECORD;

    Mendefinisikan sebuah tipe struktur data baru bernama RECORD. Setiap RECORD akan berisi empat data: first_name (nama depan), last_name (nama belakang), age (umur), dan salary (gaji).

  • RECORD record[4] = { ... };

    Membuat sebuah array bernama record yang dapat menampung 4 buah data RECORD. Langsung di baris ini, empat data sampel diinisialisasikan ke dalam array tersebut.

### Bagian 2: Program Utama (C)

  • void main(void)

    Fungsi utama tempat eksekusi program dimulai.

  • int pnt = -1;

    Mendeklarasikan variabel pnt (pointer/penunjuk) sebagai -1, yang akan digunakan sebagai indeks untuk mengakses array record.

  • while (pnt++ < 3)

    Membuat sebuah loop yang akan berjalan sebanyak 3 kali (untuk pnt = 0, 1, dan 2), memproses tiga data pertama dari array record.

  • Str(record[pnt].last_name); dan Str(record[pnt].first_name);

    Memanggil fungsi Str untuk mencetak nama belakang, lalu nama depan dari data record saat ini.

  • Numb(record[pnt].age); dan Numb(record[pnt].salary);

    Memanggil fungsi Numb untuk mencetak umur, lalu gaji dari data record saat ini.

  • Crlf();

    Memanggil fungsi Crlf untuk mencetak baris baru, agar data berikutnya tercetak di bawahnya.


### Bagian 3: Fungsi-fungsi Assembly

### Fungsi Str (Mencetak String)

Fungsi ini mengambil alamat sebuah string dan mencetaknya karakter per karakter.

  • mov bx, string_adr: Memuat alamat string ke register bx.

  • top:: Label untuk memulai loop pencetakan.

  • mov dl, [bx]: Mengambil satu karakter dari alamat yang ditunjuk bx.

  • inc bx: Memindahkan penunjuk bx ke karakter berikutnya.

  • cmp al, 0: (Catatan: Ada potensi bug di sini, seharusnya cmp dl, 0). Membandingkan karakter yang dibaca dengan null (akhir string).

  • je bot: Jika karakter adalah null, lompat ke akhir (label bot).

  • int 21h: Mencetak karakter di dl ke layar.

  • jmp top: Kembali ke awal loop.

  • bot:: Label akhir.

  • mov al, 20h dan int 21h: Mencetak spasi (20h adalah kode ASCII untuk spasi) setelah string selesai dicetak.

### Fungsi Crlf (Mencetak Baris Baru)

Fungsi ini hanya bertugas untuk membuat baris baru di layar.

  • mov ah, 2, mov dl, 13, int 21h: Mencetak Carriage Return (CR), mengembalikan kursor ke awal baris.

  • mov dl, 10, int 21h: Mencetak Line Feed (LF), memindahkan kursor satu baris ke bawah.

### Fungsi Numb (Mencetak Angka)

Fungsi ini adalah yang paling kompleks. Ia mengambil sebuah angka integer, mengubahnya menjadi serangkaian digit karakter, lalu mencetaknya.

  • mov ax, temp: Memuat angka dari variabel C temp ke register ax.

  • mov bx, 10: Menetapkan 10 sebagai pembagi (untuk konversi ke basis 10/desimal).

  • Loop L1: (Ekstraksi Digit):

    • mov dx, 0: Membersihkan dx. Ini wajib karena div menggunakan pasangan dx:ax sebagai angka yang akan dibagi.

    • div bx: Membagi ax dengan 10. Hasilnya ada di ax dan sisanya (digit satuan) ada di dx.

    • push dx: Sisa pembagian (digit) disimpan ke dalam stack. Ini membalik urutan digit (misal: 123 diekstrak sebagai 3, 2, 1).

    • cmp ax, 0 dan jne L1: Jika hasilnya belum nol, ulangi loop untuk mendapatkan digit berikutnya.

  • Loop L2: (Pencetakan Digit):

    • pop dx: Mengambil satu digit dari stack (sekarang urutannya benar: 1, 2, 3).

    • add dl, 30h: Menambahkan 30h (nilai ASCII '0') untuk mengubah digit angka (misal: 5) menjadi karakter yang bisa dicetak ('5').

    • int 21h: Mencetak digit tersebut.

    • jmp L2: Terus ulangi sampai stack kosong.

    • (Catatan: Logika untuk mendeteksi stack kosong di cmp dx,bl agak tidak konvensional, tapi pada intinya L2 akan terus berjalan sampai semua digit yang di-push selesai di-pop).

  • L3:: Label akhir.

  • mov dl, 20h dan int 21h: Mencetak spasi setelah angka selesai dicetak.



        EXAMPLE 7-6



Kode ini adalah sebuah program kalkulator sederhana yang ditulis dalam bahasa C dengan fungsi-fungsi intinya (membaca angka dan menampilkan angka) dibuat menggunakan inline assembly. Program ini dapat melakukan operasi tambah, kurang, kali, dan bagi.

Berikut adalah penjelasan untuk setiap baris dan fungsi dari kode tersebut secara berurutan.


## Penjelasan Kode Baris per Baris

### Bagian 1: Program Utama (main)

Fungsi main bertindak sebagai pengendali utama yang mengatur alur kalkulator.

  • void main(void): Fungsi utama tempat program dimulai.

  • while (1): Membuat sebuah loop tak terbatas agar kalkulator bisa terus digunakan untuk perhitungan baru tanpa harus me-restart program.

  • oper = Readnum();: Memanggil fungsi Readnum() untuk membaca angka pertama dari pengguna. Angka yang diketik akan disimpan di variabel global temp, dan karakter operator (+, -, *, /) akan dikembalikan dan disimpan di variabel oper.

  • temp1 = temp;: Menyimpan angka pertama dari temp ke temp1 agar tidak hilang.

  • if ( Readnum() == '=' ): Memanggil Readnum() lagi untuk membaca angka kedua (yang akan disimpan lagi di temp). Setelah itu, program memeriksa apakah karakter setelah angka kedua adalah =. Jika ya, maka perhitungan akan dilanjutkan.

  • switch (oper): Blok ini memilih operasi matematika yang sesuai berdasarkan operator (oper) yang dimasukkan setelah angka pertama.

    • case '+': temp += temp1; break;: Jika operatornya +, maka angka kedua (temp) ditambahkan dengan angka pertama (temp1). Hasilnya disimpan kembali di temp.

    • case '-': temp = temp1 - temp; break;: Melakukan operasi pengurangan.

    • case '/': temp = temp1 / temp; break;: Melakukan operasi pembagian.

    • case '*': temp = temp1 * temp; break;: Melakukan operasi perkalian.

  • Dispn(temp);: Setelah operasi selesai, fungsi Dispn() dipanggil untuk menampilkan hasil akhir (yang tersimpan di temp) ke layar.

  • else break;: Jika pengguna tidak mengetik = setelah angka kedua, if akan gagal dan break akan dieksekusi, menghentikan loop while(1) dan mengakhiri program.


### Bagian 2: Fungsi Readnum (Membaca Angka)

Fungsi ini sangat penting, ia membaca serangkaian digit dari keyboard dan mengubahnya menjadi sebuah angka integer.

  • _asm { ... }: Memulai blok inline assembly.

  • Readnum1:: Label untuk loop pembacaan karakter.

  • mov ah, 1 & int 21h: Perintah standar DOS untuk membaca satu karakter dari keyboard.

  • cmp al, 30h ... ja Readnum2: Blok ini adalah filter. Ia memeriksa apakah karakter yang diinput (al) adalah angka (antara '0' / 30h dan '9' / 39h). Jika bukan, program melompat ke Readnum2.

  • sub al, 30h: Mengubah karakter ASCII angka menjadi nilai numerik sebenarnya (misal: karakter '5' (nilai 53) menjadi angka 5).

  • shl temp, 1 ... add temp, bx: Ini adalah trik assembly untuk mengalikan temp dengan 10 (temp = temp * 10) untuk memberi ruang bagi digit baru.

  • add byte ptr temp, al ...: Menambahkan digit yang baru dibaca ke nilai temp yang sudah ada.

  • jmp Readnum1: Lompat kembali untuk membaca karakter berikutnya, memungkinkan input angka multi-digit (seperti 123).

  • Readnum2:: Label akhir pembacaan angka. Karakter non-angka (operator) yang menghentikan loop masih tersimpan di al.

  • mov a, ax: Menyimpan karakter operator dari al ke variabel a.

  • return a;: Mengembalikan karakter operator ke fungsi main. Angka yang sudah dikonversi tersimpan di variabel global temp.


### Bagian 3: Fungsi Dispn (Menampilkan Angka)

Fungsi ini mengambil sebuah angka integer dan menampilkannya sebagai teks desimal di layar.

  • mov ax, DispnTemp: Memuat angka yang akan ditampilkan ke register ax.

  • Loop Dispn1: (Ekstraksi Digit):

    • mov dx, 0: Mengosongkan dx sebelum operasi pembagian.

    • div bx: Membagi ax dengan 10. Hasilnya disimpan di ax, dan sisanya (digit satuan) disimpan di dx.

    • push dx: Sisa pembagian (digit) disimpan ke dalam stack. Proses ini membalik urutan digit.

    • cmp ax, 0 & jne Dispn1: Mengulangi proses sampai angkanya habis dibagi (hasilnya 0).

  • Loop Dispn2: (Pencetakan Digit):

    • pop dx: Mengambil satu digit dari stack (sekarang urutannya sudah benar).

    • cmp dl, bl & je Dispn3: Memeriksa apakah stack sudah kosong dengan membandingkan nilai yang di-pop dengan nilai 10 yang dimasukkan di awal sebagai penanda.

    • add dl, 30h: Mengubah digit numerik kembali menjadi karakter ASCII.

    • int 21h: Mencetak karakter digit ke layar.

    • jmp Dispn2: Mengulangi loop untuk mencetak digit selanjutnya.

  • Dispn3:: Label akhir.

  • mov dl, 13 ... int 21h: Mencetak baris baru (Carriage Return & Line Feed) setelah angka selesai ditampilkan.


  •  7–2 USING ASSEMBLY LANGUAGE WITH VISUAL C/C++ FOR 32-BIT APPLICATIONS


            FIGURE 7-1


Gambar ini menampilkan langkah awal dalam membuat program menggunakan Microsoft Visual C++ 2008. Jendela yang tampil adalah "New Project", di mana pengguna sedang memilih untuk membuat sebuah "Win32 Console Application". Pilihan ini secara spesifik digunakan untuk membangun program berbasis teks yang berjalan di dalam command prompt (konsol), yaitu aplikasi yang tidak memiliki antarmuka grafis seperti jendela atau tombol visual. Untuk melanjutkan, pengguna perlu mengisi nama untuk proyeknya, menentukan di folder mana program tersebut akan disimpan, lalu menekan tombol "OK" untuk membuat kerangka dasar programnya.


        EXAMPLE 7-7


Kode ini adalah sebuah program C++ yang berfungsi untuk meminta pengguna memasukkan sebuah angka desimal, kemudian program akan menampilkan representasi angka tersebut dalam semua basis bilangan dari 2 hingga 16 (biner, oktal, desimal, heksadesimal, dll.).

Fungsi inti untuk konversi dan penampilan bilangan ditulis menggunakan inline assembly. Berikut adalah penjelasan untuk setiap baris dan fungsinya.


## Penjelasan Kode Baris per Baris

### Bagian 1: Program Utama (_tmain)

Fungsi ini menangani interaksi dengan pengguna (input) dan mengatur loop untuk menampilkan hasil dalam berbagai basis.

  • _cputs(buffer);

    Mencetak string dari buffer ("Enter a number between 0 and 1000: ") ke layar untuk meminta input dari pengguna.

  • a = _getche();

    Membaca satu karakter yang diketik pengguna dan langsung menampilkannya di layar (get character and echo).

  • while ( a >= '0' && a <= '9' )

    Memulai sebuah loop yang akan terus berjalan selama karakter yang dimasukkan adalah sebuah digit (antara '0' dan '9'). Ini memungkinkan pengguna memasukkan angka multi-digit.

  • _asm sub a, 30h;

    Blok inline assembly ini mengurangi nilai ASCII dari karakter digit dengan 30h (nilai ASCII '0') untuk mendapatkan nilai numerik sebenarnya. Contoh: karakter '5' (nilai 53) menjadi angka 5.

  • b = b * 10 + a;

    Ini adalah logika untuk membangun sebuah angka integer. Angka yang sudah ada (b) dikalikan 10, lalu ditambahkan dengan digit baru (a). Contoh: jika b=12 dan digit baru adalah 3, maka b menjadi 12*10 + 3 = 123.

  • a = _getche();

    Membaca karakter berikutnya untuk melanjutkan loop atau mengakhirinya jika bukan digit.

  • for ( i = 2; i < 17; i++ )

    Ini adalah loop utama untuk penampilan hasil. Variabel i akan berjalan dari 2 hingga 16, mewakili setiap basis bilangan.

  • _cputs(buffer1);

    Mencetak "Base: ".

  • disps(10, i);

    Memanggil fungsi disps untuk menampilkan nilai i (basis saat ini) dalam format desimal (basis 10).

  • _putch('=');

    Mencetak karakter =.

  • disps(i, b);

    Ini adalah panggilan terpenting. Ia memanggil fungsi disps untuk mengonversi dan menampilkan angka yang dimasukkan pengguna (b) ke dalam basis i.

  • _putch(10); _putch(13);

    Mencetak baris baru (Line Feed dan Carriage Return).

  • _getche();

    Menunggu pengguna menekan tombol apa pun sebelum program berakhir.


### Bagian 2: Fungsi disps (Konversi dan Tampilkan)

Fungsi ini adalah inti dari program. Ia menerima sebuah angka (data) dan sebuah basis (base), lalu menampilkan angka tersebut dalam basis yang ditentukan menggunakan algoritma pembagian berulang.

  • mov eax, data dan mov ebx, base

    Memuat angka yang akan dikonversi ke register eax dan basis tujuannya ke register ebx.

  • Loop disps1: (Ekstraksi Digit):

    • mov edx, 0: Mengosongkan register edx. Ini wajib karena operasi div menggunakan pasangan register edx:eax sebagai dividen.

    • div ebx: Membagi eax dengan basis di ebx. Hasil bagi disimpan di eax, dan sisa bagi (yang merupakan digit dalam basis baru) disimpan di edx.

    • push edx: Sisa bagi (digit) disimpan ke dalam stack. Ini dilakukan karena digit diekstrak dari yang paling tidak signifikan (kanan) ke yang paling signifikan (kiri), sementara kita perlu menampilkannya dalam urutan terbalik.

    • cmp eax, 0 dan jne disps1: Jika hasil baginya belum nol, ulangi loop untuk mendapatkan digit berikutnya.

  • Loop disps2: (Pencetakan Digit):

    • pop edx: Mengambil satu digit dari puncak stack.

    • cmp ebx, edx ... je disps4: Ini adalah cara untuk memeriksa apakah stack sudah kosong dengan menggunakan nilai base yang di-push sebelumnya sebagai penanda akhir. Jika nilai yang di-pop sama dengan base, berarti semua digit sudah dicetak, lalu lompat ke disps4.

    • add dl, 30h: Mengubah nilai digit numerik (0-9) menjadi karakter ASCII ('0'-'9').

    • cmp dl, 39h dan jbe disps3: Memeriksa apakah karakter tersebut masih dalam rentang digit ('0'-'9'). Jika ya, langsung lompat ke disps3 untuk mencetaknya.

    • add dl, 7: Jika digitnya lebih dari 9 (yaitu 10-15 untuk heksadesimal), tambahkan 7 ke nilai ASCII-nya untuk mengubahnya menjadi karakter huruf ('A'-'F').

  • disps3:

    • mov temp, edx: Memindahkan karakter yang siap cetak ke variabel C temp.

    • _putch(temp): Memanggil fungsi C _putch untuk mencetak karakter tersebut ke layar.

    • _asm jmp disps2: Melompat kembali ke awal loop pencetakan untuk mengambil digit berikutnya dari stack.

  • disps4:

    Label akhir, menandakan fungsi telah selesai dieksekusi.



            FIGURE 7-2


Gambar ini menampilkan proses pembuatan proyek baru di Microsoft Visual C++ 2008, namun untuk jenis aplikasi yang berbeda. Pengguna di sini memilih templat "Windows Forms Application" yang berada di bawah kategori "CLR". Pilihan ini bertujuan untuk memulai pengembangan sebuah aplikasi yang memiliki antarmuka pengguna grafis (GUI) khas Windows—lengkap dengan elemen visual seperti jendela, tombol-tombol, dan menu—berbeda dari aplikasi konsol yang hanya berbasis teks. Kategori "CLR" (Common Language Runtime) mengindikasikan bahwa program ini akan dibangun di atas platform .NET Framework. Sebelum melanjutkan, pengguna perlu memberikan nama dan lokasi untuk proyek tersebut, yang kemudian akan menghasilkan kerangka dasar untuk sebuah aplikasi Windows visual.



             FIGURE 7-3




Gambar ini memperlihatkan antarmuka desainer visual dari Microsoft Visual C++ 2008, yang merupakan area kerja utama setelah membuat sebuah proyek "Windows Forms Application". Di bagian tengah layar, Anda melihat "Form1", yaitu representasi visual dari jendela utama aplikasi yang sedang dirancang. Di sebelah kanan, terdapat panel "Properties" yang sangat penting, yang berisi daftar lengkap semua atribut dari elemen yang sedang dipilih (dalam hal ini adalah "Form1" itu sendiri). Melalui panel ini, seorang pengembang dapat dengan mudah mengubah berbagai properti seperti judul jendela (properti Text), warna latar belakang (BackColor), ukuran, dan perilaku lainnya secara visual tanpa harus menulis kode. Lingkungan kerja seperti ini dirancang untuk mempercepat proses perancangan antarmuka pengguna grafis (GUI) sebuah aplikasi Windows.


            FIGURE 7-4

Gambar ini merupakan kelanjutan dari proses desain antarmuka pengguna pada gambar sebelumnya. Di sini, pengembang telah melakukan langkah selanjutnya dengan menambahkan sebuah elemen kontrol interaktif, yaitu sebuah tombol (button), ke atas permukaan "Form1". Tombol ini, yang untuk sementara menampilkan teks default "button1", adalah komponen fundamental dalam aplikasi GUI yang nantinya akan diberi fungsi spesifik. Setelah menempatkan tombol ini, langkah berikutnya bagi seorang programmer adalah menulis kode yang akan dieksekusi ketika pengguna akhir mengklik tombol tersebut, serta mengubah propertinya (seperti teks yang ditampilkan) melalui jendela Properties agar lebih deskriptif.



        EXAMPLE 7-8


Kode ini adalah sebuah template atau kerangka fungsi yang dibuat secara otomatis oleh lingkungan pemrograman Visual Studio saat Anda membuat sebuah aplikasi dengan antarmuka grafis (seperti Windows Forms) menggunakan C++/CLI.

Fungsi ini disebut event handler, yang tugasnya adalah mengeksekusi kode tertentu ketika sebuah event (kejadian) terjadi, dalam hal ini adalah kejadian sebuah tombol diklik.

Berikut adalah penjelasan untuk setiap bagian dari kode tersebut.


## Penjelasan Kode Baris per Baris

  • private:

    Ini adalah sebuah access specifier dalam C++. private berarti fungsi button1_Click ini hanya dapat diakses atau dipanggil dari dalam class di mana ia didefinisikan. Ini adalah praktik standar untuk event handler agar tidak bisa dipanggil dari luar secara sembarangan.

  • System::Void

    Ini adalah tipe data kembalian (return type) dari fungsi. System::Void adalah cara penulisan dalam C++/CLI (ekstensi C++ untuk .NET Framework) yang setara dengan void pada C++ standar. Ini berarti fungsi ini tidak mengembalikan nilai apa pun setelah selesai dieksekusi.

  • button1_Click

    Ini adalah nama fungsi. Nama ini biasanya dibuat secara otomatis oleh Visual Studio. Pola penamaannya adalah [NamaObjek]_[NamaEvent]. Jadi, button1_Click adalah fungsi yang akan menangani (handle) kejadian Click pada objek yang bernama button1.

  • (System::Object^ sender, System::EventArgs^ e)

    Ini adalah dua parameter (input) yang secara otomatis diterima oleh fungsi saat kejadian terjadi:

    • System::Object^ sender: Parameter sender adalah penunjuk ke objek yang memicu kejadian tersebut. Dalam kasus ini, sender akan merujuk pada button1 itu sendiri. Tanda ^ adalah sintaks C++/CLI untuk handle, yang mirip dengan pointer.

    • System::EventArgs^ e: Parameter e adalah objek yang berisi data tambahan terkait kejadian tersebut. Untuk kejadian klik sederhana, e biasanya tidak berisi informasi penting, tetapi untuk kejadian lain (seperti mouse-move), ia bisa berisi data seperti koordinat X dan Y.

  • { dan }

    Tanda kurung kurawal ini mendefinisikan isi atau badan dari fungsi. Di sinilah Anda sebagai programmer akan menulis kode yang ingin Anda jalankan ketika button1 diklik. Dalam contoh ini, isinya masih kosong, yang berarti jika tombol diklik, tidak ada aksi apa pun yang akan terjadi.



         EXAMPLE 7-9




Kedua versi kode tersebut adalah implementasi dari event handler button1_Click dalam C++/CLI, yang tujuannya adalah mengubah teks yang ditampilkan pada sebuah tombol (button1) ketika tombol tersebut diklik.

Meskipun hasilnya mirip, keduanya menunjukkan dua cara yang sedikit berbeda untuk mencapai tujuan tersebut.


## Penjelasan Kode Baris per Baris

### Versi (a)

Versi ini mengubah teks tombol secara langsung.

  • private: System::Void button1_Click(...)

    Ini adalah definisi fungsi event handler yang akan berjalan ketika button1 diklik.

  • {

    Memulai badan (isi) dari fungsi.

  • button1->Text = "Wow, Hello";

    Ini adalah baris aksi utamanya.

    • button1->Text: Mengakses properti Text dari objek button1. Properti Text adalah apa yang ditampilkan secara visual di atas tombol. Tanda -> digunakan untuk mengakses anggota dari sebuah objek melalui handle (mirip pointer).

    • = "Wow, Hello";: Menetapkan (assign) sebuah nilai string literal baru, yaitu "Wow, Hello", ke properti Text. Setelah baris ini dieksekusi, tulisan pada tombol akan langsung berubah menjadi "Wow, Hello".

  • }

    Mengakhiri badan fungsi.


### Versi (b)

Versi ini menggunakan variabel perantara untuk menyimpan string sebelum mengubah teks tombol.

  • private: System::Void button1_Click(...)

    Definisi fungsi yang sama seperti sebelumnya.

  • {

    Memulai badan fungsi.

  • String^ str1 = "Wow, Hello World";

    Baris ini melakukan dua hal:

    • String^ str1: Mendeklarasikan sebuah handle ke objek String .NET yang bernama str1. String^ adalah tipe data untuk string dalam lingkungan C++/CLI.

    • = "Wow, Hello World";: Membuat sebuah objek string baru dengan isi "Wow, Hello World" dan menetapkan str1 untuk merujuk ke objek tersebut.

  • button1->Text = str1;

    Menetapkan properti Text dari button1 dengan nilai dari objek string str1. Sama seperti versi (a), ini akan mengubah tulisan pada tombol, tetapi kali ini menjadi "Wow, Hello World".

  • }

    Mengakhiri badan fungsi.

Secara fungsional, keduanya melakukan hal yang sama. Versi (b) dengan variabel perantara lebih berguna jika Anda perlu memanipulasi atau membangun string tersebut dari beberapa bagian sebelum menampilkannya.


            FIGURE 7-5



Gambar ini menampilkan antarmuka pengguna (UI) yang sudah selesai dirancang untuk sebuah aplikasi Windows fungsional bernama "Converter". Berdasarkan elemen-elemen yang ada, aplikasi ini bertujuan untuk mengonversi sebuah angka dari sistem desimal ke sistem bilangan lain berdasarkan radix (basis) yang dimasukkan oleh pengguna. Antarmukanya terdiri dari label yang jelas ("Decimal Number", "Radix", "Result"), beberapa kotak teks untuk tempat pengguna memasukkan data dan melihat hasil, serta sebuah tombol "Convert" yang akan memicu proses kalkulasi. Ini adalah contoh dari sebuah aplikasi sederhana dengan desain yang lengkap dan intuitif, yang merupakan hasil akhir dari proses perancangan visual yang telah ditunjukkan pada gambar-gambar sebelumnya.



        EXAMPLE 7-10


Kode ini adalah implementasi dari event handler button1_Click dalam C++/CLI. Tujuannya adalah untuk mengambil teks dari sebuah kotak input (TextBox) dan mengubahnya menjadi sebuah angka integer ketika tombol button1 diklik.

Ini adalah operasi yang sangat umum dalam aplikasi yang membutuhkan input numerik dari pengguna.


## Penjelasan Kode Baris per Baris

  • private: System::Void button1_Click(...)

    Ini adalah definisi fungsi event handler yang akan berjalan ketika button1 diklik. private berarti fungsi ini hanya bisa diakses dari dalam class-nya, dan System::Void berarti fungsi ini tidak mengembalikan nilai.

  • {

    Memulai badan (isi) dari fungsi.

  • int number = Convert::ToInt32(textBox1->Text);

    Ini adalah baris utama yang melakukan seluruh pekerjaan. Mari kita pecah menjadi tiga bagian:

    1. textBox1->Text: Bagian ini mengakses properti Text dari sebuah kontrol yang bernama textBox1. Properti Text selalu berisi data dalam format string (teks), yaitu apa pun yang diketik oleh pengguna ke dalam kotak teks tersebut.

    2. Convert::ToInt32(...): Ini adalah pemanggilan sebuah fungsi statis dari class Convert milik .NET Framework. Fungsi ToInt32 secara spesifik bertugas untuk mengambil sebuah string dan mengonversinya menjadi sebuah angka integer 32-bit.

    3. int number = ...;: Bagian ini mendeklarasikan sebuah variabel integer baru bernama number dan menyimpan hasil dari operasi konversi ke dalamnya.

    Jadi, jika pengguna mengetik "45" di dalam textBox1, setelah baris ini dieksekusi, variabel number akan berisi nilai numerik 45 yang siap digunakan untuk kalkulasi.

  • }

    Mengakhiri badan fungsi.



        EXAMPLE 7-11


Kode ini adalah versi yang lebih aman dan tangguh dari contoh sebelumnya. Tujuannya tetap sama: mengambil teks dari sebuah TextBox dan mengubahnya menjadi angka. Namun, kode ini menambahkan penanganan kesalahan (error handling) menggunakan blok try-catch.

Ini sangat penting karena program tidak akan crash jika pengguna memasukkan teks yang bukan angka.


## Penjelasan Kode Baris per Baris

  • private: System::Void button1_Click(...)

    Ini adalah definisi fungsi event handler yang akan berjalan ketika button1 diklik.

  • {

    Memulai badan (isi) dari fungsi.

  • try

    Memulai sebuah blok try. Kode apa pun yang berada di dalam kurung kurawal { ... } setelah try akan "diawasi". Jika terjadi kesalahan (disebut exception) saat kode tersebut dijalankan, program tidak akan langsung berhenti.

  • int number = Convert::ToInt32(textBox1->Text);

    Baris ini, yang berada di dalam blok try, mencoba melakukan konversi teks dari textBox1 menjadi sebuah angka integer. Inilah "operasi berisiko" yang sedang diawasi. Jika pengguna memasukkan "123", baris ini akan berhasil. Jika pengguna memasukkan "abc", baris ini akan gagal dan memicu sebuah exception.

  • }

    Mengakhiri blok try.

  • catch (...)

    Memulai blok catch. Blok ini hanya akan dieksekusi jika terjadi exception di dalam blok try. Sintaks (...) berarti "tangkap jenis kesalahan apa pun".

  • {

    Memulai badan dari blok catch.

  • MessageBox::Show("The input must be an integer!");

    Jika konversi gagal, program akan melompat ke sini. Perintah ini akan menampilkan sebuah jendela pop-up (MessageBox) di layar dengan pesan "The input must be an integer!". Ini adalah cara yang jauh lebih ramah untuk memberi tahu pengguna bahwa input mereka salah, daripada membiarkan program berhenti bekerja (crash).

  • }

    Mengakhiri blok catch.

  • }

    Mengakhiri badan fungsi button1_Click.



        EXAMPLE 7-12


Kode ini adalah implementasi lengkap untuk sebuah konverter basis bilangan. Program ini mengambil sebuah angka dan sebuah basis (radix) dari input pengguna, melakukan konversi, lalu menampilkan hasilnya.

Kode ini sangat baik karena mencakup validasi input dan penanganan kesalahan (error handling). Berikut adalah penjelasan untuk setiap baris dan blok fungsinya.


## Penjelasan Kode Baris per Baris

### Bagian 1: Deklarasi dan Inisialisasi

  • private: System::Void button1_Click(...):

    Definisi fungsi event handler yang berjalan saat button1 diklik.

  • String^ result = "";:

    Mendeklarasikan sebuah variabel String .NET bernama result dan menginisialisasinya sebagai string kosong. Variabel ini akan digunakan untuk membangun hasil konversi.

  • int number; dan int radix;:

    Mendeklarasikan dua variabel integer untuk menyimpan angka yang akan dikonversi (number) dan basis tujuannya (radix).

### Bagian 2: Input dan Penanganan Kesalahan

  • try { ... }:

    Memulai blok try untuk mengawasi kode konversi input, yang berpotensi menimbulkan kesalahan jika input tidak valid.

  • number = Convert::ToInt32(textBox1->Text);:

    Mencoba mengubah teks dari textBox1 menjadi sebuah angka integer dan menyimpannya di number.

  • radix = Convert::ToInt32(textBox2->Text);:

    Mencoba mengubah teks dari textBox2 menjadi integer dan menyimpannya di radix.

  • catch (...) { ... }:

    Jika salah satu atau kedua konversi di atas gagal (misalnya pengguna mengetik "abc"), blok catch ini akan dieksekusi.

  • MessageBox::Show("All inputs must be integers!");:

    Menampilkan jendela pesan pop-up yang memberitahu pengguna bahwa input harus berupa angka.

### Bagian 3: Validasi Input Radix

  • if (radix < 2 || radix > 36):

    Setelah input berhasil diubah menjadi angka, baris ini memeriksa apakah nilai radix berada di luar rentang yang valid (2 hingga 36). Program ini dibatasi hingga basis 36 karena menggunakan angka 0-9 dan huruf A-Z.

  • MessageBox::Show(...):

    Jika radix tidak valid, tampilkan pesan kesalahan yang sesuai.

  • else { ... }:

    Jika radix valid, maka blok else yang berisi algoritma konversi akan dieksekusi.

### Bagian 4: Algoritma Konversi Basis

Blok ini adalah inti dari program yang mengubah number menjadi string dalam basis radix.

  • do { ... } while (number != 0);:

    Memulai sebuah loop do-while yang akan terus berjalan sampai number menjadi 0.

  • char digit = number % radix;:

    Menghitung sisa bagi (modulo) dari number dengan radix. Sisa bagi ini adalah digit paling kanan dari angka dalam basis yang baru.

  • number /= radix;:

    Membagi number dengan radix (pembagian integer) untuk "menghapus" digit yang baru saja diekstrak, mempersiapkan iterasi berikutnya.

  • if (digit > 9):

    Memeriksa apakah digit yang didapat lebih besar dari 9. Ini terjadi pada basis 11 atau lebih tinggi (misalnya, digit 10 akan menjadi 'A', 11 menjadi 'B', dst.).

  • digit += 7;:

    Jika digit > 9, tambahkan 7. Ini adalah trik untuk mengubahnya menjadi karakter huruf. Setelah ditambahkan 0x30 nanti, nilai 10 akan menjadi 'A', 11 menjadi 'B', dan seterusnya.

  • digit += 0x30;:

    Menambahkan 0x30 (nilai ASCII untuk '0') untuk mengubah nilai digit numerik (0-9) menjadi karakter ASCII yang bisa dicetak ('0'-'9').

  • result = digit + result;:

    Ini adalah langkah penting. Karakter digit yang baru ditambahkan di awal string result. Ini dilakukan karena algoritma ini mengekstrak digit dari kanan ke kiri, sehingga harus dibangun kembali dari kanan ke kiri juga.

### Bagian 5: Menampilkan Hasil

  • textBox3->Text = result;:

    Setelah loop selesai, string result yang sudah jadi akan ditampilkan di dalam textBox3.



             FIGURE 7-6


Gambar ini menampilkan jendela "Property Pages" atau halaman properti dari sebuah proyek di Visual C++, yang merupakan tempat untuk mengatur konfigurasi tingkat lanjut dari sebuah aplikasi. Pengguna sedang berada di bagian Configuration Properties -> General dan akan mengubah pengaturan untuk "Common Language Runtime support". Sesuai dengan keterangan gambar dan menu dropdown yang terbuka, pengguna sedang mengaktifkan opsi "/clr", yaitu sebuah compiler switch yang fundamental. Tindakan ini bertujuan untuk mengubah proyek dari aplikasi C++ standar (native) menjadi aplikasi yang mendukung dan dapat berinteraksi dengan lingkungan .NET Framework (managed). Dalam konteks yang dijelaskan oleh keterangan gambar, langkah ini merupakan prasyarat yang harus dilakukan untuk memungkinkan penggunaan bahasa assembly di dalam proyek tersebut.



        EXAMPLE 7-13


Kode ini menunjukkan dua versi dari sebuah fungsi bernama Adjust yang ditulis dalam C++/CLI. Tujuan kedua fungsi ini sama persis: yaitu untuk mengambil sebuah angka 16-bit (short) yang merepresentasikan satu digit heksadesimal (nilai 0-15) dan mengubahnya menjadi karakter ASCII yang sesuai ('0'-'9' atau 'A'-'F').

Kedua versi tersebut mencapai hasil yang sama, tetapi dengan urutan logika assembly yang sedikit berbeda.


## Penjelasan Kode Baris per Baris

### Bagian Awal (Setup)

  • #pragma once:

    Sebuah direktif kompiler yang memastikan file header ini hanya disertakan satu kali selama proses kompilasi untuk mencegah error.

  • namespace FirstApp { ... }:

    Mendefinisikan sebuah namespace bernama FirstApp untuk mengelompokkan kode terkait.

  • using namespace System; ...:

    Menyatakan bahwa program akan menggunakan berbagai namespace dari .NET Framework, yang menyediakan fungsionalitas untuk komponen, form, data, dan grafis.


### Fungsi Adjust (Versi Pertama)

Versi ini memeriksa nilai numerik terlebih dahulu, baru kemudian mengubahnya ke ASCII.

  • short Adjust(short n):

    Definisi fungsi C++ bernama Adjust yang menerima satu argumen n (angka 0-15) dan akan mengembalikan sebuah short.

  • _asm { ... }:

    Memulai blok inline assembly.

  • mov ax, n:

    Memindahkan (move) nilai dari variabel n ke dalam register 16-bit ax.

  • cmp ax, 9:

    Membandingkan (compare) nilai di ax dengan 9.

  • jle later:

    Jump if Less or Equal. Jika nilai ax kurang dari atau sama dengan 9, maka lompat ke label later:.

  • add ax, 7:

    Baris ini hanya dieksekusi jika nilai ax lebih besar dari 9 (yaitu 10-15). Menambahkan 7 ke nilai tersebut adalah langkah pertama untuk mengubahnya menjadi karakter 'A' - 'F'.

  • later::

    Label tujuan lompatan.

  • add ax, 30h:

    Menambahkan 30h (nilai ASCII untuk karakter '0') ke nilai di ax.

    • Jika ax awalnya 0-9, hasilnya menjadi '0'-'9'.

    • Jika ax awalnya 10-15 (dan sudah ditambah 7), hasilnya menjadi 'A'-'F'.

  • mov n, ax:

    Memindahkan hasil akhir (yang sudah berupa kode ASCII) dari register ax kembali ke variabel C n.

  • return n;:

    Mengembalikan nilai n yang sudah dikonversi.


### Fungsi Adjust (Versi Alternatif)

Versi ini mengubah ke ASCII terlebih dahulu, baru kemudian mengoreksinya jika perlu.

  • _asm { ... }:

    Memulai blok inline assembly.

  • mov ax, n:

    Memindahkan nilai n ke register ax.

  • add ax, 30h:

    Langsung menambahkan 30h untuk mengubah nilai n menjadi karakter ASCII-nya (misal: 10 menjadi karakter setelah '9').

  • cmp ax, 39h:

    Membandingkan nilai karakter di ax dengan 39h (nilai ASCII untuk '9').

  • jle later:

    Jika karakter tersebut adalah '9' atau kurang, maka konversinya sudah benar, jadi lompat ke later:.

  • add ax, 7:

    Jika karakter lebih besar dari '9', tambahkan 7 untuk mengoreksinya menjadi karakter huruf yang benar ('A' - 'F').

  • later::

    Label tujuan, di mana nilai di ax sudah pasti merupakan karakter ASCII yang benar. Isi dari ax secara implisit akan dikembalikan oleh fungsi (meskipun tidak ada mov n, ax, kompiler biasanya menggunakan ax untuk nilai kembalian).



        EXAMPLE 7-14


Kode ini adalah versi yang lebih modular dan disempurnakan dari program konverter basis bilangan sebelumnya. Perbedaan utamanya adalah ia sekarang memanggil fungsi eksternal bernama Adjust (yang telah kita lihat di contoh sebelumnya) untuk membantu dalam proses konversi.

Program ini mengambil angka dan basisnya, memvalidasi input, melakukan konversi, dan menampilkan hasilnya.


## Penjelasan Kode Baris per Baris

### Bagian 1: Inisialisasi dan Blok try

  • private: System::Void button1_Click(...):

    Definisi fungsi event handler yang berjalan saat button1 diklik.

  • String^ result = "";:

    Mendeklarasikan dan menginisialisasi sebuah string kosong yang akan digunakan untuk membangun hasil konversi.

  • try { ... }:

    Memulai blok try untuk mengawasi kode yang berpotensi menyebabkan kesalahan, terutama saat mengonversi input pengguna dari teks ke angka.

### Bagian 2: Input dan Validasi

Blok ini berada di dalam try dan menangani pembacaan, konversi, dan validasi input.

  • unsigned int number = Convert::ToUInt32(textBox1->Text);:

    Membaca teks dari textBox1 dan mengonversinya menjadi sebuah unsigned integer 32-bit. Penggunaan unsigned berarti angka ini tidak bisa negatif, tetapi jangkauan positifnya menjadi dua kali lebih besar.

  • unsigned int radix = Convert::ToUInt32(textBox2->Text);:

    Melakukan hal yang sama untuk textBox2, mengubahnya menjadi basis (radix).

  • if (radix < 2 || radix > 36):

    Memeriksa apakah radix yang dimasukkan berada di luar rentang yang valid (antara 2 dan 36).

  • MessageBox::Show(...):

    Jika radix tidak valid, tampilkan jendela pesan pop-up dengan pesan kesalahan yang sesuai.

  • else { ... }:

    Jika radix valid, maka blok else yang berisi algoritma konversi akan dijalankan.

### Bagian 3: Algoritma Konversi dan Penampilan Hasil

Ini adalah inti dari logika konversi.

  • do { ... } while (number != 0);:

    Memulai sebuah loop do-while yang akan terus berjalan selama number belum menjadi nol.

  • result = (Char)Adjust(number % radix) + result;:

    Ini adalah baris yang paling penting dan cerdas. Mari kita pecah:

    1. number % radix: Menghitung sisa bagi untuk mendapatkan digit paling kanan dalam basis yang baru (nilainya antara 0-35).

    2. Adjust(...): Memanggil fungsi Adjust (dari contoh sebelumnya) untuk mengubah nilai numerik digit (misalnya 10) menjadi karakter ASCII yang sesuai (misalnya 'A').

    3. (Char): Melakukan casting atau konversi tipe data dari hasil Adjust menjadi sebuah karakter.

    4. ... + result: Menambahkan karakter baru ini di awal string result yang sudah ada. Ini membangun string hasil dalam urutan yang benar.

  • number /= radix;:

    Membagi number dengan radix untuk mempersiapkan iterasi loop berikutnya.

  • textBox3->Text = result;:

    Setelah loop selesai, string result yang sudah lengkap ditampilkan di textBox3.

### Bagian 4: Blok catch

  • catch (...) { ... }:

    Blok ini hanya akan berjalan jika terjadi kesalahan di dalam blok try (misalnya, pengguna mengetik "halo" bukannya angka).

  • MessageBox::Show(...):

    Menampilkan pesan kesalahan yang memberitahu pengguna tentang rentang input desimal yang valid untuk unsigned integer.


  • 7–3 MIXED ASSEMBLY AND C++ OBJECTS

        EXAMPLE 7-15


Kode ini adalah sebuah fungsi eksternal yang ditulis sepenuhnya dalam bahasa assembly (MASM). Tujuannya adalah untuk menerima sebuah pointer ke sebuah string dan membalik urutan karakter di dalam string tersebut.

Fungsi ini dirancang untuk dapat dipanggil dari program C/C++, yang ditandai oleh direktif .model flat, C. Algoritma yang digunakan sangat cerdas, yaitu dengan memanfaatkan struktur data stack (tumpukan).

Berikut adalah penjelasan untuk setiap baris dan blok kode tersebut.


## Penjelasan Kode Baris per Baris

### Bagian 1: Direktif dan Setup Awal

Bagian ini mengatur lingkungan untuk assembler.

  • .586: Memberi tahu assembler untuk menggunakan set instruksi dari prosesor Pentium (80586), yang mendukung operasi 32-bit.

  • .model flat, C: Menetapkan model memori. flat berarti menggunakan satu ruang alamat linier (standar untuk OS modern), dan C berarti menggunakan konvensi pemanggilan dari bahasa C, agar bisa diintegrasikan dengan C++.

  • .stack 1024: Mengalokasikan ruang stack sebesar 1024 byte.

  • .code: Menandakan dimulainya segmen kode.

  • public Reverse: Membuat prosedur Reverse dapat diakses secara publik, sehingga program C/C++ dapat me-link dan memanggilnya.

  • Reverse proc uses esi, arraychar:ptr: Mendefinisikan sebuah prosedur bernama Reverse. uses esi secara otomatis menyimpan dan mengembalikan nilai register esi. arraychar:ptr mendefinisikan parameter input bernama arraychar yang merupakan sebuah pointer.


### Bagian 2: Mendorong Karakter ke Stack (Proses Push)

Bagian ini membaca seluruh string dan mendorong setiap karakternya ke dalam stack. Karena stack bersifat LIFO (Last-In, First-Out), karakter terakhir akan berada di puncak tumpukan.

  • mov esi, arraychar: Memuat alamat awal string dari parameter arraychar ke dalam register esi, yang akan digunakan sebagai penunjuk.

  • mov eax, 0 dan push eax: Mendorong nilai 0 (karakter null) ke stack terlebih dahulu. Ini akan berfungsi sebagai penanda akhir saat mengambil data kembali.

  • .repeat ... .until byte ptr [esi] == 0: Ini adalah struktur loop tingkat tinggi MASM. Loop akan terus berjalan sampai karakter yang ditunjuk esi adalah 0 (penanda akhir string).

    • mov al, [esi]: Mengambil satu karakter dari alamat yang ditunjuk esi dan menyimpannya di al.

    • push eax: Mendorong karakter tersebut ke puncak stack.

    • inc esi: Menaikkan penunjuk esi untuk menunjuk ke karakter berikutnya.


### Bagian 3: Mengambil Karakter dari Stack (Proses Pop)

Setelah semua karakter berada di stack dalam urutan terbalik, bagian ini mengambilnya kembali satu per satu dan menuliskannya kembali ke lokasi string asli.

  • mov esi, arraychar: Mengatur ulang penunjuk esi kembali ke alamat awal string.

  • .while eax != 0: Memulai loop yang akan berjalan selama nilai yang di-pop dari stack bukan 0 (penanda akhir yang kita dorong di awal).

    • pop eax: Mengambil nilai dari puncak stack dan menyimpannya di eax. Pada iterasi pertama, ini akan menjadi karakter terakhir dari string asli.

    • mov [esi], al: Menyimpan karakter dari al ke lokasi memori yang ditunjuk oleh esi. Ini akan menimpa string asli dengan karakter yang terbalik.

    • inc esi: Menaikkan penunjuk esi untuk menulis di posisi berikutnya.

  • .endw: Mengakhiri blok .while.

  • Ret: Perintah untuk kembali dari prosedur (kembali ke program C/C++ yang memanggilnya).

  • Reverse endp dan End: Menandai akhir dari prosedur Reverse dan akhir dari file assembly.



         EXAMPLE 7-16



Kode ini adalah sebuah program C yang berfungsi sebagai "pembungkus" atau "pemanggil" untuk fungsi Reverse yang ditulis dalam bahasa assembly dari contoh sebelumnya.

Tujuan utama program C ini adalah untuk mendefinisikan sebuah string, menampilkannya, memanggil fungsi assembly untuk membalik string tersebut, lalu menampilkannya lagi untuk menunjukkan hasilnya.


## Penjelasan Kode Baris per Baris

  • /* ... */

    Ini adalah komentar yang menjelaskan tujuan program, yaitu untuk membalik urutan sebuah string karakter.

  • #include <stdio.h> dan #include <conio.h>

    Ini adalah direktif preprocessor untuk menyertakan file header dari pustaka standar C.

    • stdio.h diperlukan untuk fungsi input/output standar seperti printf.

    • conio.h diperlukan untuk fungsi konsol seperti getche.

  • extern "C" void Reverse(char *);

    Ini adalah deklarasi atau prototipe fungsi. Baris ini memberi tahu kompiler C tentang keberadaan sebuah fungsi bernama Reverse.

    • extern "C": Bagian ini sangat penting. Ini memberitahu kompiler bahwa fungsi Reverse menggunakan konvensi pemanggilan dari bahasa C. Ini memungkinkan program C ini untuk di-link dengan benar dengan fungsi Reverse yang telah kita tulis dan kompilasi dari file bahasa assembly terpisah.

    • void: Fungsi Reverse tidak mengembalikan nilai.

    • Reverse(char *): Nama fungsinya adalah Reverse dan ia menerima satu argumen, yaitu sebuah pointer ke char (sebuah string).

  • char chararray[17] = "So what is this?";

    Mendeklarasikan sebuah array karakter (string) bernama chararray dan menginisialisasinya dengan kalimat "So what is this?".

  • int main(...)

    Fungsi main, titik di mana eksekusi program dimulai.

  • printf("%s\n", chararray);

    Mencetak isi dari chararray ke layar dalam keadaan aslinya, diikuti dengan baris baru (\n). Outputnya adalah: So what is this?.

  • Reverse(chararray);

    Ini adalah baris inti dari program. Ia memanggil fungsi Reverse eksternal (yang ditulis dalam assembly) dan mengirimkan chararray sebagai argumennya. Fungsi assembly tersebut akan memodifikasi chararray secara langsung di memori dan membalik urutan karakternya.

  • printf("%s\n", chararray);

    Mencetak kembali isi chararray setelah dimodifikasi oleh fungsi Reverse. Sekarang, outputnya adalah string yang sudah terbalik: ?siht si tahw oS.

  • getche();

    Memanggil fungsi getche yang akan menjeda program dan menunggu pengguna menekan tombol apa pun. Ini dilakukan agar jendela konsol tidak langsung tertutup, sehingga pengguna bisa melihat hasil outputnya.

  • return 0;

    Mengakhiri fungsi main dan mengembalikan nilai 0, yang menandakan program selesai dengan sukses.



             FIGURE 7-7

Gambar ini menampilkan jendela "Property Pages" untuk sebuah file individual bernama 'Reverse.txt' di dalam sebuah proyek Visual C++. Pengguna telah mengonfigurasi sebuah "Custom Build Step", yang merupakan fitur untuk memberikan instruksi perakitan (build) khusus pada file tersebut. Pada bagian "Command Line", telah dimasukkan perintah ml /c /Cx /coff Reverse.txt, yang secara spesifik memanggil Microsoft Macro Assembler (ml.exe) untuk memproses file teks tersebut. Tujuan dari langkah ini adalah untuk meng-assemble (merakit) kode bahasa assembly yang tertulis di dalam Reverse.txt menjadi sebuah object file (Reverse.obj), yang nantinya dapat digabungkan (di-link) dengan sisa proyek C++ untuk menciptakan sebuah program aplikasi yang utuh. Ini adalah metode standar untuk mengintegrasikan sebuah modul yang ditulis murni dalam bahasa assembly ke dalam sebuah proyek C++ yang lebih besar.



             TABLE 7-2 


Tabel tersebut menunjukkan kode Morse internasional untuk setiap huruf abjad dari A sampai Z. Kode ini terdiri dari kombinasi sinyal pendek (disebut dit dan ditulis sebagai titik .) dan sinyal panjang (disebut dah dan ditulis sebagai strip -).
## Penjelasan Kode Morse per Huruf
  • A: . - (di-dah)
  • B: - . . . (dah-di-di-dit)
  • C: - . - . (dah-di-dah-dit)
  • D: - . . (dah-di-dit)
  • E: . (dit) - Kode termudah, karena 'E' adalah huruf yang paling umum digunakan dalam bahasa Inggris.

Fungsi utama kode Morse adalah sebagai metode pengkodean untuk mengirim pesan teks melalui media komunikasi yang hanya bisa mengirimkan sinyal sederhana (seperti "nyala/mati" atau "bunyi panjang/bunyi pendek"). Setiap huruf dan angka diwakili oleh kombinasi unik dari sinyal pendek (titik/dit) dan sinyal panjang (strip/dah).
Secara historis, fungsi utamanya adalah:
  • Komunikasi Jarak Jauh: Kode Morse menjadi revolusi dalam komunikasi pada abad ke-19 melalui telegraf, yang mengirimkan pulsa listrik melalui kabel. Ini memungkinkan pengiriman pesan antar kota atau bahkan antar benua dalam hitungan menit, bukan hari atau minggu. 
  • Komunikasi Maritim dan Darurat: Kode ini sangat vital untuk kapal di laut dan stasiun pantai. Sinyal darurat paling terkenal, SOS (... --- ...), adalah standar internasional yang mudah dikenali.
  • Komunikasi Militer: Karena kesederhanaan dan keandalannya, kode Morse banyak digunakan dalam dunia militer, baik melalui radio maupun sinyal cahaya.

        EXAMPLE 7-17



Kode ini adalah modul bahasa assembly (MASM) yang berisi dua fungsi, Scan dan Look, yang bekerja sama untuk mengubah sebuah karakter huruf menjadi representasi string kode Morse-nya.

Modul ini dirancang untuk dapat dihubungkan dan dipanggil dari program C/C++ (seperti pada contoh Moorse.cpp yang Anda berikan sebelumnya).


## Penjelasan Kode Baris per Baris

### Bagian 1: Segmen Data (.data)

Bagian ini mendefinisikan "kamus" atau tabel data yang digunakan oleh fungsi Scan.

  • table db 2,1,4,8,4,10,3,4 ...:

    Ini adalah sebuah tabel lookup. Setiap huruf dari A-Z memiliki pasangan data 2-byte di sini.

    • Byte pertama adalah panjang dari kode Morse.

    • Byte kedua adalah pola bit dari kode Morse, di mana bit 1 mewakili strip (-) dan bit 0 mewakili titik (.).

    • Contoh: Untuk huruf 'A' (.-), datanya adalah 2,1. Artinya, panjangnya 2 karakter, dan polanya adalah 1 (biner ...01). Untuk 'B' (-...), datanya adalah 4,8. Panjangnya 4 karakter, polanya 8 (biner ...1000).


### Bagian 2: Fungsi Scan

Fungsi ini menerima sebuah karakter, mengubahnya menjadi indeks, lalu menggunakan indeks itu untuk mencari data kode Morse yang terenkripsi dari table.

  • Scan proc uses ebx, \ char:dword:

    Mendefinisikan fungsi Scan yang menerima satu argumen char.

  • mov ebx, char:

    Memuat karakter input ke register ebx.

  • .if bl >= 'a' && bl <= 'z' ... .endif:

    Blok ini memeriksa apakah karakter adalah huruf kecil. Jika ya, sub bl, 20h akan mengubahnya menjadi huruf besar (misal: 'a' menjadi 'A').

  • sub bl, 41h:

    Mengurangi nilai karakter dengan 41h (nilai ASCII 'A'). Ini mengubah karakter menjadi indeks berbasis nol (A=0, B=1, C=2, dst.).

  • add bl, bl:

    Mengalikan indeks dengan 2 (indeks * 2), karena setiap entri di table berukuran 2 byte (sebuah word).

  • add ebx, offset table:

    Menambahkan offset yang sudah dihitung ke alamat awal table. Sekarang ebx menunjuk ke lokasi data yang tepat untuk karakter tersebut di dalam table.

  • mov ax, word ptr[ebx]:

    Mengambil data 2-byte (word) dari table pada lokasi yang ditunjuk ebx dan menyimpannya di register ax. ax sekarang berisi data terenkripsi (panjang dan pola bit).

  • ret:

    Kembali dari fungsi. Nilai yang dikembalikan (data terenkripsi) ada di ax.


### Bagian 3: Fungsi Look

Fungsi ini menerima data terenkripsi dari Scan dan sebuah pointer ke buffer, lalu ia "melukis" atau menulis string kode Morse ke dalam buffer tersebut.

  • Look proc uses ebx ecx, \ numb:dword, \ pntr:ptr:

    Mendefinisikan fungsi Look yang menerima numb (data terenkripsi dari Scan) dan pntr (pointer ke buffer tujuan).

  • mov ebx, pntr:

    Memuat alamat buffer tujuan ke ebx, yang akan digunakan sebagai penunjuk tulis.

  • mov eax, numb:

    Memuat data terenkripsi ke eax.

  • mov cl, al:

    Memindahkan byte rendah dari eax (yaitu panjang kode Morse) ke cl. Register cl akan digunakan sebagai penghitung loop.

  • .repeat ... .untilcxz:

    Memulai loop yang akan berjalan sebanyak cl kali.

  • shr ah, 1:

    Shift Right. Menggeser byte tinggi dari eax (ah, yang berisi pola bit) ke kanan sebanyak 1 bit. Bit yang tergeser keluar akan disimpan di Carry Flag.

  • .if carry?:

    Memeriksa Carry Flag.

  • mov byte ptr[ebx], '-':

    Jika Carry Flag aktif (bit yang tergeser adalah 1), tulis karakter strip (-) ke buffer.

  • .else ... mov byte ptr[ebx], '.':

    Jika Carry Flag mati (bit yang tergeser adalah 0), tulis karakter titik (.) ke buffer.

  • inc ebx:

    Menaikkan penunjuk ebx untuk menulis di posisi berikutnya dalam buffer.

  • mov byte ptr[ebx], 0:

    Setelah loop selesai, tulis karakter null (0) di akhir string untuk menandakan akhir dari string kode Morse.

  • ret:

    Kembali dari fungsi.


        EXAMPLE 7-18



Kode ini adalah program C++ yang berfungsi sebagai "pemanggil" atau "driver" untuk modul bahasa assembly Scan dan Look yang telah kita bahas sebelumnya.

Tujuan utama program ini adalah untuk mengambil sebuah kalimat, memprosesnya karakter per karakter, dan menggunakan fungsi assembly eksternal untuk mengubah setiap huruf menjadi kode Morse, lalu menampilkannya ke layar.


## Penjelasan Kode Baris per Baris

  • // Moorse.cpp ...

    Komentar yang menandakan nama file dan tujuannya sebagai titik masuk (entry point) aplikasi.

  • #include <iostream> dan using namespace std;

    Direktif standar C++ untuk menggunakan fungsionalitas input/output, seperti cout (untuk mencetak ke layar) dan cin (untuk membaca input).

  • extern "C" int Scan(int); dan extern "C" void Look(int, char *);

    Ini adalah deklarasi fungsi eksternal. Baris ini memberi tahu kompiler C++:

    1. Ada fungsi bernama Scan yang menerima int dan mengembalikan int.

    2. Ada fungsi bernama Look yang tidak mengembalikan nilai (void), menerima int dan char * (pointer ke karakter).

    3. extern "C" adalah bagian krusial yang memastikan fungsi ini dapat di-link dengan benar dengan modul assembly yang menggunakan konvensi pemanggilan bahasa C.

  • int main(...)

    Fungsi utama tempat eksekusi program dimulai.

  • int a = 0;:

    Mendeklarasikan variabel a sebagai 0. Variabel ini akan digunakan sebagai indeks untuk perulangan.

  • char chararray[] = "This, is the trick!\n";:

    Mendeklarasikan sebuah string (array karakter) yang akan dikonversi.

  • char chararray1[10];:

    Mendeklarasikan sebuah buffer atau wadah kosong bernama chararray1. Buffer ini akan digunakan oleh fungsi Look untuk menyimpan hasil string kode Morse dari satu karakter.

  • while ( chararray[a] != '\n' ):

    Memulai sebuah loop while yang akan terus berjalan selama karakter pada chararray yang sedang diperiksa bukanlah karakter baris baru (\n).

  • if ( chararray[a] < 'A' || chararray[a] > 'z' ):

    Di dalam loop, baris ini memeriksa apakah karakter saat ini bukan merupakan huruf (di luar jangkauan 'A' hingga 'z'). Ini adalah cara sederhana untuk menyaring tanda baca, spasi, dll.

    • cout << chararray[a] << '\n';: Jika bukan huruf, karakter tersebut langsung dicetak ke layar.

  • else { ... }:

    Jika karakter tersebut adalah huruf, blok ini akan dieksekusi.

    • Look( Scan( chararray[a] ), chararray1 );: Ini adalah baris inti dari program.

      1. Scan( chararray[a] ): Fungsi assembly Scan dipanggil dengan mengirimkan karakter saat ini. Scan akan mengembalikan sebuah nilai integer yang berisi data terenkripsi (panjang dan pola bit) dari kode Morse.

      2. Look( ... , chararray1 ): Fungsi assembly Look dipanggil. Ia menerima data terenkripsi dari Scan dan pointer ke chararray1. Look akan mendekode data tersebut dan menulis string kode Morse yang sudah jadi ke dalam buffer chararray1.

    • cout << chararray[a] << " = " << chararray1 << '\n';: Mencetak hasilnya ke layar dalam format: Huruf = KodeMorse. Contoh: T = -.

  • a++;:

    Menaikkan nilai indeks a untuk berpindah ke karakter berikutnya pada iterasi loop selanjutnya.

  • cout << "Type enter to quit!";:

    Setelah loop selesai, pesan ini dicetak.

  • cin.get();:

    Menjeda program dan menunggu pengguna menekan tombol Enter. Ini dilakukan agar jendela konsol tidak langsung tertutup.

  • return 0;:

    Mengakhiri program dan menandakan eksekusi berhasil.





Komentar

Postingan Populer