2016-04-07 30 views
2

Bir kelime ve bir çift kelimeyi bir dört kelimeye dönüştürmeyi anlamamış tek soruyla ilgili bir test yaptım.Ne zaman ve neden cc/mul/div ile cdq kullanıyoruz?

Düşünmeme neden oldu, neden/çarpma veya bölme için ne zaman uzanıyoruz? Ek olarak, cdq gibi talimatları ne zaman kullanırız?

cevap

7

Eğer insn ref kılavuzuna ( etiket wiki bağlantı) görebileceğiniz gibi:

  • tek işlenen mul/imul: edx:eax = eax * src
  • iki işlenen imul: dst *= src

  • div/idiv: src tarafından edx:eax böler. eax'da bölüm, kalan kısım edx. Girişte edx göz ardı eden div/idiv biçimi yoktur.
  • cdq yani edx her bit içine eax işareti bit yayınlar, edx:eax içine eax oturum uzanır. cdqe, movsx rax, eax, daha az insn bayt ile 64 bit komut ile karıştırılmamalıdır.

    Başlangıçta (8086), sadece cbw (ax = sign_extend(al)) ve cwd (dx:ax = sign_extend(ax)) oldu. X86 ile 32bit ve 64bit arasındaki uzantılar, anımsatıcıları biraz belirsiz hale getirdi (ancak, cbw dışında, içten çıkışlı sürümlerin her zaman Extend için bir e ile biteceğini unutmayın). 8 bit mul ve div özel olduğundan ve dl:al yerine ax kullanın dl = sign_bit (al) komutu yoktur. [i]mul için girişler yana

bir multiply önce edx ile bir şey yapmanıza gerek asla tek kayıtlarıdır.

Girişiniz imzalanırsa, çoğaltdığınız girdi olarak kullanmak için kaydı genişletin, örn. movsx veya cwde ile (eax = sign_extend(ax)). Girişiniz imzalanmamışsa, sıfırlanırsınız. (Istisna ile sadece örneğin çarpma sonucu düşük 16 bit ihtiyaçları olursa, it doesn't matter if the upper 16 bits of either or both inputs contain garbage.) Bir ayrımın için


, her zaman sıfıra ihtiyaç veya edx içine eax uzatmak imzalarlar. Sıfır genişletme, koşulsuz sıfırlama edx ile aynıdır, dolayısıyla özel bir talimat yoktur. Sadece xor edx,edx. cdq, edx'teki her bit için eax işaret biti yayınlamak için mov edx, eax/sar edx, 31'dan çok daha kısa olduğu için vardır. Ayrıca,> 1 ile kaymalar 286'ya kadar devam etmedi, yani 8086'da, cwd yoksa (cdq'un 16bit sürümü) bir döngüye ihtiyacınız olacaktır.


64bit modunda, 32 bit değerlerini 64 bit olarak işaretlemek ve sıfırlamak yaygındır. ABI bir 32bit değeri tutan bir 64bit kayıt yüksek 32bits çöp sağlar, bu yüzden eğer işlevin sadece edi düşük 32bits bakmak gerekiyorsa, dizi endekslemek için sadece [array + rdi] kullanamazsınız.

Yani (oturum uzatmak) veya mov eax, edimovsx rdi, edi bir sürü (bkz, sıfır uzatmak ve Intel mov-eleme mov same,same ile çalışmıyor çünkü evet, farklı bir hedef kayıt kullanmak için daha verimlidir)

+0

Üzgünüm - Meclis'teki bölünmeyle her zaman karışıyor, çünkü sicillerle kafam karışıyor. Temettemin her zaman eax/axe olarak yerleştirildiğini ve tek-operand talimatının sadece div/idiv ebx (ya da herhangi bir kayıt) olduğunu düşündüm. Hangi eax/ebx etkin bir şekilde eax ve geri kalanında edx ile gerçekleştirir. Sınava girmemizden önce, EAX'in 71'ini içeren ve bir -4 içeren başka bir register üzerinde idiv'i çağırmadan önce cdq kullanmamızı sağladı. Bu neden? Her yazmacının bütününü kullanıyorduk, neden bir dördüncüsüne ihtiyacımız olduğunu anlamıyorum. – Koronakesh

+0

@Koronakesh: Cevabımın ilk satırını ve/veya Intel'in tasarım kılavuzunu okuyun. 'yiv ebx'' eax = (edx: eax)/ebx' ve 'eax = (edx: eax)% ebx' yapar. “edx” her zaman temettünün yüksek yarısıdır ve açık işlenen her zaman bölmedir. 'Imul' 2 ve 3-operand formları sadece tek kayıt sonucu üretir şekilde edx' yok sayan bir 'div' /' idiv' biçimi yoktur. –

+0

Tamam - bu şimdi mantıklı. Bölünücünün büyüklüğüne göre bölenin büyüklüğüne dair şartlar var mı? Ayrıca, cdq gibi komutlar sadece 1 bayt alt edx, edx gibi bir şeyden daha az maliyetli olduğu için var mı? – Koronakesh

İlgili konular