İmzalı ve imzasız sayılar


17

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?


3
İlgili sorunun cevabına bakın: cs.stackexchange.com/a/30047/28999 . Bu arada, imzalı -7 1111 olarak temsil edilmiyor. -1. Daha sonra hem imzalı hem de imzasız davada örneğin 1111 - 0001 = 1110 (-2'ye 14)
Albert Hendriks

2
@AlbertHendriks Adil olmak gerekirse, bazı eski bilgisayarlar "işaret-büyüklük gösterimi" (bir işaret biti ve genişlik biti) kullanır ve biz hala bu stili örneğin IEEE şamandıraları için kullanırız. İkisinin tamamlayıcısıyla karşılaştırıldığında sadece yetersiz ve çalışmak zordur. n-1
Draconis

1
Temel fark, daha büyükThan / lessThan operatörlerinin nasıl davrandığı ve sağ kaydırmanın en yüksek bitle doldurulup doldurulmadığıdır. Aslında çarpıp bölündüğünüzde sonuç aynıdır.
Rob


2
@Rob Bu tamamen doğru değil. Toplama, çıkarma ve çarpma imzasız ve iki tamamlayıcı arasında aynıdır - girişlerinizin ve çıkışlarınızın aynı boyutta olduğu varsayılarak. Bölme aynı değildir 6/2 3'tür, ancak -2/2 -1'dir. Ve birçok CPU'nun, iki girişin aynı boyutta olduğu çarpma talimatları vardır, ancak çıkış iki kat büyüklüğündedir, bu durumda imzasız ve ikişer tamamlayıcı aynı değildir.
kasperd

Yanıtlar:


14

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, XORBoolean 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ı.


Java bayt kodunun da ISA olarak sayıldığını unutmayın. Ve veri türlerini önemsiyor ...
John Dvorak

Java bayt kodu, silikonda uygulandığı anlamıyla bir ISA olarak sayılır. Bununla birlikte, bu tür temel tip kontrolü sınıf yükleyici tarafından yapılan kontroldür, bu nedenle tipler çoğunlukla çalışma zamanında göz ardı edilebilir. Ve elbette Java bayt kodunun ilk başta imzasız türleri yoktur.
Takma isim

@Pseudonym: Eh, teknik olarak, bu mu var char16-bit işaretsiz türü olan. Elbette, Java bayt kodunda hala imzasız aritmetik talimatlar yoktur, çünkü herhangi bir chardeğer otomatik olarak intaritmetik için (32 bit imzalı) olarak yükseltilir .
Ilmari Karonen

42

Kısa versiyon: bilmiyor. Söylemenin bir yolu yok.

-7'yi 1111temsil 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 SADDve bir UADDopcode'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.


Ah, yakaladım. Bunun için teşekkürler :)
noorav

10
İkinin tamamlayıcı gösterimlerinde üç aritmetik işlem imza-agnostiktir: toplama, çıkarma ve çarpma (işlenenlerle aynı uzunlukta ürünle). İmzalı işlenenler için yalnızca bölüm farklı şekilde ele alınmalıdır.
Ruslan

4
Ayrıca karşılaştırma var: < <= >= >imzalı ve imzasız işlenenler için farklıdır ==ve !=imzadan bağımsızdır.
Daniel Schepler

Çarpma genellikle imzalı ve imzasız çeşitlere sahiptir: 0xFFFFFFFF * 0xFFFFFFFF imzasızsa 0xFFFFFFFE00000001 ve imzalanmışsa 0x0000000000000001'dir. Intel gibi işlemciler sonucu 2 kayıt olarak döndürür ve üst kayıt imzalı ve imzasız olarak farklılık gösterir. Her iki durumda da alt kayıt 1'dir.
Rudy Velthuis

9

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 JBZı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.


1
Sonuçtan girdilerden daha fazla bite sahip olmanız gerekmediği sürece çarpma bile imzasız ve imzalı (ikisinin tamamlayıcısı) tamsayılar için aynıdır . Bununla birlikte, 8 × 8 → 16 bit (veya 16 × 16 → 32 bit, vb.) Çarpma gibi bir şey yapıyorsanız, girişleri (veya ara sonuçları) genişletmek için imzalamanız gerekir .
Ilmari Karonen

@IlmariKaronen Bu doğrudur; / A64 ARM A32 oturum agnostik sadece alt sıra bitlerini yazıyor çarpma-eklenti, aynı zamanda da dahil olmak üzere çoklu talimat birçok formlarının bulunduğu talimat setleri olan smulhve umulhsadece ç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.
Davislor

6

Ö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.


charDonanı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.
Solomon Slow

3

Ö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 divimzasız bir bölüm yapmak için adlandırılmış bir talimatı ve idivimzalı 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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.