Temel C Programlama -46- Bit Manipülasyonu ve Bitwise Operatörleri

Programcılığa yeni başlayan biri olsaydım C ile alakalı bir kitabı açıp okuduğumda bit bazlı işlemler ve operatörler kısmını gereksiz bir ayrıntı olarak görüp çok üzerinde durmazdım. Aslında üst seviye programlama ile uğraşanlar için de bir ayrıntıdan öte gitmemektedir. Fakat gömülü sistemler üzerinde çalışan biri olarak şimdi C dilinin en önemli konularından biri olarak görmekteyim.

Pek çoğunuz C dilini gömülü sistemlerde çalışmak için öğreniyorsunuz. Bu zamanda C dili ne Web programcılığında ne mobil programcılıkta kullanılıyor. Masaüstü programcılıkta ise aslında bakarsanız pek pratik bir kullanım alanına sahip değil. Fakat bütün bu alanlarda irdelenen bir dil gömülü sistemlerde bir numaralı dil olmayı başarabiliyor. Zamanında C dili bilgisayarlarda kullanılan bir numaralı dildi ( 90’ların başı) fakat günümüzde neredeyse hiç kullanılmamakta. Yani günümüzde C dilinin ait olduğu yer sistem programcılığı ve gömülü sistemlerdir.

C dilinin yaygın olarak uygulandığı gömülü sistemlere baktığımızda ise bit bazlı işlemlerin ve işaretçilerin aşırı derecede fazla kullanıldığını görüyoruz. Yani C dilinin alt seviye noktaları gömülü sistemlerde daha ön plana çıkmakta. Hatta gömülü sistemlerde “Merhaba Dünya!” anlamına gelen led yakma uygulamasında bile bit bazlı işlemler kullanılmakta. Yani bit bazlı işlemleri yapmadan bazen en basit programı bile yazmanız mümkün olmuyor.

Bir diğer konu da gömülü sistemlere yeni başlayan biri klasik C eğitimini görmüş olsa bile bit bazlı işlemleri gördüğünde kafa karıştırıcı tuhaf semboller olarak yorumlayacaktır. Çünkü eğitimde bit bazlı işlemlere yeterince ağırlık verilmemektedir. Biz bunun önüne geçmek ve gömülü sistemlerde zorluk yaşamamanız için en fazla önemi bu konuya vereceğiz.

Bitwise Operatörler

C dilinde bit bazlı işlem yapabilmek için bitwise operatörleri yani bit bazlı operatörler yer alır. Bu operatörlerin işlevi adından da anlayabileceğiniz gibi diğer operatörler gibi değişken veya değerler ile değil bitler ile işlem yapmalarıdır. Bu sayede bir değişkenin içine girebilir 1 ve 0 olmak üzere her bir biti istediğiniz gibi düzenleyebilirsiniz. Bu da size muhteşem bir güç verecektir!. İşaretçilerle bütün adreslere ve bit operatörleri ile de bütün bitlere hakim olduğunuz zaman artık donanım avcunuzun içinde demektir.

Şimdi sizi iyice meraklandırmadan bit operatörlerini gösterelim.

Operatör

Açıklama

&

Bitwise AND (AND işlemi)

|

Bitwise OR (OR işlemi)

^

Bitwise XOR (Ex-OR işlemi)

<<

Sola Kaydırma

>>

Sağa Kaydırma

~

Bir’in tümleyeni (Tersleme)

Burada operatörlerin işlevlerine baktığınız zaman eğer dijital mantık, dijital elektronik ve mikroişlemci mimarisi bilginiz yoksa bunların çok tuhaf olduğunu düşünebilirsiniz. Bunlar bizim bildiğimiz matematik operatörlerine pek benzemese de mikroişlemcilerin komut kümelerine bile eklenen özel komutlar olduğunu bilmeniz gerekir. Yani mikroişlemci tasarımcıları bu işlemlerin mikroişlemcinin sahip olması gereken en önemli yeteneklerden biri olarak görmekte ve doğrudan donanımsal olarak bunu mikroişlemciye eklemektedir. Bunlar Assembly dilinde olduğu gibi gördüğüm bütün programlama dillerinde de mevcuttur. Bu işin en temeline indiğinizde ise dijital mantık ve mantık kapılarını görürsünüz.

Öncelikle bu operatörlerin çalışma mantığını size tek tek açıkladıktan sonra gömülü sistemler üzerinde kullanımını yani uygulamalı olarak kullanımını sizlere göstereceğiz. Sonrasında ise örnek kodlarla bunu pekiştirmeye çalışacağız.

& – AND (VE) Operatörü

Bu operatör iki değeri alır ve bit bazlı VE işlemi uygular. Bu iki integer değer olsa da her birinin bitlerini birbiri ile karşılaştırır ve sonrasında sırasına göre bu bitleri sonuç olarak verir. Yani bu operatörün aslında değişkenin 200 mü 300 mü olduğu ile bir işi yoktur. Sadece her bir sıradaki bitin 1 veya 0 olup olmadığı ile ilgilenir. 1 & 1 = 1, 1 & 0 = 0, 0 & 0 = 0 diyerek her bir bit ayrı ayrı VE işlemine tabi tutulur. Bu VE işleminin ne olduğunu bilmiyorsanız dijital elektronik yazılarımıza göz atabilirsiniz. Bunu hakkıyla anlayabilmek için bu yönde de bilginiz olması lazımdır. Şimdi VE işleminin doğruluk tablosunu verelim.

A

B

C

0

0

0

0

1

0

1

0

0

1

1

1

Tablodan da göreceğiniz üzere ancak A ve B’nin 1 olması durumunda sonuç 1 olmaktadır. Bunu mantık kapılarında da anlattım ve çok tekrarlamak istemiyorum. Aşağıdaki bağlantıdan lütfen okuyunuz. Aksi halde yarım öğrenmiş olursunuz.

http://www.lojikprob.com/elektronik/dijital-elektronik-8-mantik-kapilari/

Şimdi C dilinde bir AND işleminin nasıl yapıldığını görelim.

char degisken1 = 0b00011100;
char degisken2 = 0b11011000;
sonuc = degisken1 & degisken2;

Burada degisken1 0b00011100 değerine degisken2 ise 0b11011000 değerine sahip. Bu durumda bu ikisine AND işlemi uyguladığımızda operatör her bir biti hanesine göre ele alacak ve AND işlemini uygulayıp sonuca yazacaktır. Bunu mikroişlemci yaparken her bir bite işlemi uygulamak için bir komut harcamamaktadır. Örneğin 64-bitlik bir mikroişlemci tek bir komutta iki 64 bitlik değişkene AND işlemi uygulayabilir. Fakat bu işlemin bağımsız bitler üzerinde yapıldığını unutmamak gerekir. Yani her zaman bit & bit = bit gibi bir işlem ortaya çıkmaktadır. En azından bizim bunu böyle anlamamız gerekli. Yukarıdaki tabloya göre işlemler şu şekilde yapılacaktır.

0

0

0

1

1

1

0

0

1

1

0

1

1

0

0

0

0

0

0

1

1

0

0

0

Görüldüğü gibi AND işlemi her bir bite ayrı olarak uygulanmakta ve sırasına göre bu sonuca yazılmaktadır. İlk satır degisken1, ikinci satır degisken2, üçüncü satır ise sonuc değişkeninin satırıdır.

| – OR (VEYA) Operatörü

Bu operatör yukarıda verdiğimiz AND operatörü gibi çalışmakta fakat operandları farklı bir işleme tabi tutmaktadır. O da mantıksal (VEYA) işlemidir. Bu mantıksal işlem yine bit bazında olmaktadır. Aşağıda mantıksal OR işleminin doğruluk tablosunu görebilirsiniz.

A

B

C

0

0

0

0

1

1

1

0

1

1

1

1

Gördüğünüz gibi A veya B sayılarından herhangi biri 1 ise sonuç 1 olmaktadır. Sonucun sıfır olması için bütün sayıların sıfır olma şartı vardır. Bu operatör de oldukça basit gibi görünse de asıl karmaşıklık uygulamada yer almaktadır. Bu operatörleri hiç ummadığınız bir iş için kullanabilirsiniz. Örneğin bir biti bir yapmak için maskeleme işlemi yapılır ve burada anahtar işlem OR işlemidir. Şimdi C dilinde iki değişkeni OR işlemine tabi tutalım ve sonuçlarını görelim.

char degisken1 = 0b00011100;
char degisken2 = 0b11011000;
sonuc = degisken1 | degisken2;

0

0

0

1

1

1

0

0

1

1

0

1

1

0

0

0

1

1

0

1

1

1

0

0

Yukarıdaki sonuçta göreceğiniz üzere OR işlemi bütün bitlere yukarıdaki doğruluk tablosuna göre uygulanmakta ve çıkan sonuç sonuc atlı değişkenin bitlerine yazılmaktadır. Bu işlemi C dilinde & operatörü ile x86 Assembly dilinde AND komutu ile dijital elektronikte mantık kapıları ile elektronikte ise transistörler vasıtasıyla yapabiliriz. Neden bunun alt seviye bir özellik olduğunu buradan anlayabilirsiniz.

^ – XOR Operatörü

XOR operatörü exclusive-OR anlamına gelmektedir. Bunu kolay yoldan anlamak için şöyle diyebiliriz. Operatörler birbirinden farklı mı değil mi operatörü denebilir. Yani operatörler karşılaştırılır farklıysa 1 değilse 0 çıkışı verilir. Bu durumda doğruluk tablosu şu şekilde olacaktır.

A

B

C

0

0

0

0

1

1

1

0

1

1

1

0

Bunu C dilinde uygulamak istersek şöyle bir program yazabiliriz.

char degisken1 = 0b00011100;
char degisken2 = 0b11011000;
sonuc = degisken1 ^ degisken2;

Bu durumda çıkışımız şu şekilde olacaktır.

0

0

0

1

1

1

0

0

1

1

0

1

1

0

0

0

1

1

0

0

0

1

0

0

NOT (Değil) ya da Bir’in tümleyeni (One’s Complement) Operatörü

Temel mantık işlerini yapan operatörlerin sonuncusu NOT (DEĞİL) operatörüdür. Bu operatörün prensibi oldukça basittir. 1 ise 0 yapar, 0 ise 1 yapar. Tekil bir operatör olduğu için sadece bir operand üzerinde işlem yapmaktadır. Bunun doğruluk tablosu şu şekildedir.

A

Sonuç

0

1

1

0

Şimdi NOT operatörünün nasıl işlediğini göstermek için bir program yazalım ve sonucuna bakalım.

char degisken1 = 0b00011100;
sonuc = ~degisken1;

0

0

0

1

1

1

0

0

1

1

1

0

0

0

1

1

Görüldüğü gibi birbirinin tam tersi olmakta. Aynı bir bütünün diğer yarısı gibi görünüyor. O yüzden birin tümleyeni adını aldığını görebilirsiniz. 1’in ve 2’nin tümleyeni işlemleri boolean cebrinde önemli bir yere sahiptir. Yine bunları hakkıyla anlayabilmek için temel bilginizin olması gerektiğini görüyorsunuz. O yüzden bilgisayar mühendisliği gibi bölümlerde dijital elektronik gibi dersler yer almaktadır. Ne kadar iyi programcı olursanız olun işin temelini bilemedikçe her zaman eksik anlamış olursunuz.

Bit Kaydırma Operatörleri

C dilinde yer alan << ve >> operatörleri değişkenlerin bitlerini sola ve sağa kaydırmak için kullanılır. Bu kaydırma işlemi gerçek manada uygulanmaktadır. Bu operatörler kaydırılacak veri ve kaç adım (bit) kaydırılacağına dair iki ayrı operand almaktadır. Bu bit kaydırma işlemleri için x86 Assembly dilinde SHR (Shift Right) ve SHL(Shift Left) komutu yer almaktadır. Yani bu işlemlerin C’de operatör olarak verilmesi gibi makine dilinde ayrı komut olarak karşılığı bulunmaktadır.

Şimdi 8 bitlik bir verimiz var diyelim. Bunu sola veya sağa kaydırdığımızda bitler bir bütün halinde yer değiştirecektir. Örneğin bir adım kaydırdığımızda en sağdaki bit kendi solunda yer alan bitin yerine geçecek. Kendi solunda yer alan bitte yine kendi solunda yer alan bitin yerine geçecektir. Böyle böyle en baştaki bite kadar gidecektir. En baştaki bite ne olacak derseniz artık o bit ortadan kalkacaktır. Bu sola kaydırma işlemi aynı matematikte 5050 sayısının ilk basamağını silip son basamağına ise bir 0 ekleyerek 0505 sayısını elde etmeye benzer. Şimdi bunun nasıl yapıldığına bakalım.

char degisken1 = 0b00011100;
sonuc = degisken1 << 1;

Burada sonucu bir adım kaydırdık. Buna göre bütün bitler bir adım sola kayacaktır. Değişkenin ilk değeri ve işlemden sonraki değeri şu şekilde olacaktır.

0

0

0

1

1

1

0

0

0

0

1

1

1

0

0

0

Şimdi aynı değişkeni bir adım sağa kaydırmak için ise şöyle bir kod yazarız.

char degisken1 = 0b00011100;
sonuc = degisken1 >> 1;

Bu durumda sonucumuz şöyle olacaktır.

0

0

0

1

1

1

0

0

0

0

0

0

1

1

1

0

Görüldüğü gibi oldukça basit değil mi? Kaç adım kaydırmak istiyorsak adım sayısını yazarak işlemimizi yapıyoruz. Bu bazen küçük veri hücrelerindeki büyük verileri düzenlemek için de kullanılabilir. Örneğin iki adet char (8-bit) değişkeninde 16 bitlik bir veriyi saklamak istiyorsak degerH ve degerL olmak üzere alçak ve yüksek bitleri saklayacağımız iki değişken tanımlamak zorundayız. Normalde 16-bitlik bir değeri 8 bitlik bir değişkene aktarmak istesek ilk sekiz bitini (burada bitler sağdan başlar) aktaracaktır. Soldan sekiz bitini aktarmak için bunu 8 bit sağa kaydırıp yazdırmamız gereklidir. Bu 8-bitlik gömülü sistemler üzerinde çalışırken sıkça yaptığımız uygulamalardan biridir.

Buraya kadar bit operatörlerinin tamamını anlattık. Fakat uygulamada kullanımını anlatmazsak yarım kalacaktır. Çünkü uygulamada oldukça farklı kullanım yöntemleri mevcuttur. Bunu bir sonraki başlıkta sizlere açıklayacağız.

Last updated