Bilgisayar bilimi sınıfımda derleme öğrenmeye yeni başlıyorum ve belirli bir yuvarlama modunu kullanarak kayan nokta değerini yuvarlamak için bir atamam var . Bunu fstcw
, fldcw
ve frndint
kullanarak uygulamaya çalıştım. Yuvarlama kontrol bitlerini değiştiriyorum, sayıyı yuvarlayın ve önceki kontrol bitlerini (atama gereksinimi) geri yükleyin.Satır içi derlemede (GCC, IA-32) çift kesinlikli sayılarla çalışma
Geçerli önemli sorun, fld %1
yönergesinin st(0)
kayan nokta kaydına yanlış değer yüklediği anlaşılıyor (örneğin, işlevi 2.6207 değeriyle çağırırsam, sayı -1.9427 (...) e-29 kayıtlara yüklenir). Bu, gcc
satır içi asm()
'un yanlış kullanımından veya başka bir nedenden dolayı olabilir, ancak bunun neden olduğundan emin değilim.
İşte ne var:
double roundD (double n, RoundingMode roundingMode)
{
// control word storage (2 bytes for previous, 2 for current)
char *cw = malloc(4*sizeof(char));
char *cw2 = cw + 2;
asm("fstcw %3;" // store control word in cw
"mov %3,%4;" // copy control word into cw2
"and $0xF3FF,%4;" // zero out rounding control bits
"or %2,%4;" // put new mode into rounding control bits
"fldcw %5;" // load the modified control word
"fld %1;" // load n into st(0)
"frndint;" // round n
"fstp %0;" // load st(0) back into n
"fldcw %3;" // load the old control word from cw
: "=m" (n)
: "m" (n), "m" (roundingMode),
"m" (cw), "r" (cw2), "m" (cw2) // mov requires one argument in a register
);
free(cw);
return n;
}
Özellikle fld %1
hat ve asm
girişlerine/çıkışlar ile ilgili, bu kodu nesi herhangi işaretçiler takdir ediyorum. (Elbette, başka problemler bulabilirseniz, onları da bana bildirmekten çekinmeyin.) Kimsenin benim için ödevimi yapmasını istemiyorum, sadece doğru yöne doğrult. Teşekkürler!
Vay, bu oldukça badass. Keşke yardımcı olabilirdim ama yapamam! :) –
bize bu işlevin montaj çıktısını gösterebilir misin? ve kod baytları da çok fazla sorun değil. –
@John: Montajı yapılacak kod sürpriz değil; hepsi bir dev opak (gcc) asm bloğunda. :-P Birçok küçük asm deyimine (postum gibi) bölünürken, gcc daha farklı bir şey yapmak için daha fazla enlem verir. –