Bir mikroişlemcideki ALU, 1111 ile gösterilen işaretli bir sayı olan 7 ile 1111 ile gösterilen işaretsiz bir sayı 15 arasında nasıl farklılık gösterir?
Bir mikroişlemcideki ALU, 1111 ile gösterilen işaretli bir sayı olan 7 ile 1111 ile gösterilen işaretsiz bir sayı 15 arasında nasıl farklılık gösterir?
Yanıtlar:
Kısa ve basit cevap: öyle değil. Hiçbir modern ana CPU ISA düşündüğünüz gibi çalışmaz.
CPU için, sadece biraz desen. Bu bit deseninin ne anlama geldiğini takip etmek programcıya bağlı.
Genel olarak, ISA'lar depolama alanı söz konusu olduğunda farklı veri türleri arasında ayrım yapmaz. (FPU'daki kayan kayıtlar gibi özel amaçlı kayıtları yok saymak.) CPU için anlamsız bir bit kalıbı. Ancak, ISA'lar yapmak farklı şekillerde bit deseni yorumlayabilir talimatların farklı tür var. Örneğin, aritmetik talimatları gibi MUL
, DIV
, ADD
, SUB
, sayısının bir tür olarak bit modelini yorumlamak gibi mantıklı talimatlar ise AND
, OR
, XOR
Boolean bir dizi olarak yorumlar. Bu nedenle, doğru talimatları seçmek programcıya (veya daha üst düzey bir dil kullanıyorsanız tercüman veya derleyicinin yazarına) bağlıdır.
Örneğin, imzalı ve imzasız numaralar için ayrı talimatlar olabilir. Bazı ISA'ların ikili kodlu ondalık sayılarla aritmetik talimatları da vardır.
Ancak, yukarıda "modern ana akım ISA" yazdığımı unutmayın. Aslında farklı çalışan ana akım olmayan veya tarihi ISA'lar vardır. Örneğin, hem IBM AS / 400'ün orijinal 48 bit CISC ISA'sı hem de şimdi IBM i olarak adlandırılan sistemin geçerli POWER tabanlı 64 bit RISC ISA'sı, işaretçiler ve diğer değerleri birbirinden ayırır. İşaretçiler her zaman etiketlenir ve tür bilgisi ve hak yönetimi içerir. CPU, bir değerin bir işaretçi olup olmadığını bilir ve yalnızca ayrıcalıklı i / OS çekirdeğinin işaretçileri serbestçe değiştirmesine izin verilir. Kullanıcı uygulamaları, sahip oldukları işaretçileri yalnızca az sayıda güvenli talimat kullanarak sahip oldukları belleğe yönlendirmek için kullanabilirler.
Ayrıca, en azından sınırlı tip farkındalık içeren bazı tarihi ISA tasarımları da vardı.
char
16-bit işaretsiz türü olan. Elbette, Java bayt kodunda hala imzasız aritmetik talimatlar yoktur, çünkü herhangi bir char
değer otomatik olarak int
aritmetik için (32 bit imzalı) olarak yükseltilir .
Kısa versiyon: bilmiyor. Söylemenin bir yolu yok.
-7'yi 1111
temsil ediyorsa , ilk bitin işareti ve geri kalan bitlerin büyüklüğü olduğu bir işaret-büyüklük temsiliniz vardır. Bu durumda, aritmetik biraz karmaşıktır, çünkü imzasız bir ekleme ve imzalı bir ekleme farklı mantık kullanır. Yani muhtemelen bir SADD
ve bir UADD
opcode'unuz olur ve yanlış olanı seçerseniz saçma sonuçlar elde edersiniz.
Bununla birlikte, daha sık, ikinin tamamlayıcı gösterimi olarak1111
adlandırılan -1'i temsil eder . Bu durumda, ALU sayıların imzalanıp imzalanmadığını umursamaz! Örneğin, işleyelim 1110 + 0001
. İmzalı aritmetikte bu "-2 + 1" anlamına gelir ve sonuç -1 ( 1111
) olmalıdır . İmzasız aritmetikte bu, "14 + 1" anlamına gelir ve sonuç 15 ( 1111
) olmalıdır . Dolayısıyla ALU imzalı veya imzasız bir sonuç isteyip istemediğinizi bilmiyor ve umursamıyor. Eklemeyi imzasız gibi yapar ve bunu daha sonra imzalı bir tamsayı olarak ele almak istiyorsanız, bu size bağlıdır.
DÜZENLEME: Ruslan ve Daniel Schepler'in yorumlarda oldukça haklı olarak işaret ettikleri gibi, bazı işlenenlerin hala ikisinin tamamlayıcı makinesinde bile ayrı imzalı ve imzasız sürümlere ihtiyaçları vardır. Toplama, çıkarma, çarpma, eşitlik vb. Sayıların imzalı olup olmadığını bilmeden sorunsuz çalışır. Ancak bölme ve daha büyük / daha küçük karşılaştırmaların ayrı sürümleri olmalıdır.
DÜZENLEME DÜZENLEME: Kişinin tamamlayıcısı gibi başka temsiller de vardır, ancak bunlar artık daha fazla kullanılmamaktadır, bu yüzden onlar hakkında endişelenmenize gerek yoktur.
<
<=
>=
>
imzalı ve imzasız işlenenler için farklıdır ==
ve !=
imzadan bağımsızdır.
Tüm modern mimarilerin kullandığı ikinin tamamlayıcı matematiğinin en büyük avantajlarından biri, toplama ve çıkarma talimatlarının hem imzalı hem de imzasız işlenenler için tamamen aynı olmasıdır.
Birçok CPU'nun çarpma, bölme veya modül talimatları bile yoktur. Eğer öyleyse, talimatın ayrı imzalı ve imzasız formlarına sahip olmalıdırlar ve derleyici (veya montaj dili programcısı) uygun olanı seçer.
İşlemciler ayrıca genellikle imzalı veya imzasız karşılaştırmalar için farklı talimatlara sahiptir. Örneğin , karşılaştırma işleminin imzalanması gerekiyorsa x86 CMP
, JL
(İmzalanmadıysa JB
Zıpla) veya karşılaştırma imzasız olması gerekiyorsa (Aşağıdaysa Zıpla) ile takip edebilir. Yine, derleyici veya programcı veri türü için doğru talimatı seçer.
Diğer birkaç yönerge, sağa kaydırma veya işaret genişletmeli veya işaretsiz daha geniş bir kayıt defterine bir değer yükleme gibi imzalı ve imzasız varyantlarda gelir.
smulh
ve umulh
sadece çarpma üst bit ve imzalı ve imzasız talimatlar bunun iade olduğunu sonucu kaynak işlenenden iki kat daha geniş bir kayıtta döndürür.
Öyle değil. İşlemci, ne tür verilere baktığını ve nereye göndereceğini söylemek için talimat setine güvenir. Operandın kendisinde, verilerin bir char, float, int, işaretli int, vb. Olup olmadığını doğal olarak ALU'ya işaret edebilecek hiçbir şey yoktur. 2s tamamlayıcısı olarak yorumlanacak.
char
Donanım düzeyinde bir şey yoktur . Belki bir zamanlar, mekanik ışınlayıcıların günlerinde. Ancak bugün a char
, donanım açısından sadece bir sayıdır. Farklı sayıların ekranınızdaki farklı harf şekillerine karşılık gelmesinin nedeni, bu sayıların büyük bir tablodan (yani, "yazı tipinden") farklı bitmap'leri veya farklı çizim rutinlerini seçmek için kullanılmasıdır.
Önceden yapılmış cevaplara bir ek vermek istiyorum:
Diğer cevapların çoğunda, iki tamamlayıcı aritmetik işlemde sonucun imzalı ve imzasız sayılar için aynı olduğu belirtilmektedir:
-2 + 1 = -1 1110 + 0001 = 1111
14 + 1 = 15 1110 + 0001 = 1111
Ancak , istisnalar vardır:
Division:
-2 / 2 = -1 1110 / 0010 = 1111
14 / 2 = 7 1110 / 0010 = 0111
Comparison:
-2 < 2 = TRUE 1110 < 0010 = TRUE
14 < 2 = FALSE 1110 < 0010 = FALSE
"Typical" (*) multiplication:
-2 * 2 = -4 1110 * 0010 = 11111100
14 * 2 = 28 1110 * 0010 = 00011100
(*) Birçok CPU'da iki n-bit sayının çarpımının sonucu (2 * n) bit genişliğindedir.
Bu tür işlemler için CPU'ların imzalı ve imzasız aritmetik için farklı talimatları vardır.
Bu, programcının (veya derleyicinin) imzalı ve imzasız aritmetik için diğer talimatları kullanması gerektiği anlamına gelir.
Örneğin, x86 CPU'nun div
imzasız bir bölüm yapmak için adlandırılmış bir talimatı ve idiv
imzalı bir bölüm yapmak için adlandırılmış bir talimatı vardır .
İmzalı ve imzasız aritmetik için farklı "koşullu" talimatlar (koşullu atlama, koşullu set-bit) ve çarpma talimatları da vardır.