praegune kellaaeg 18.06.2025 21:33:41
|
Hinnavaatlus
:: Foorum
:: Uudised
:: Ärifoorumid
:: HV F1 ennustusvõistlus
:: Pangalink
:: Telekavad
:: HV toote otsing
|
|
autor |
|
kalvis
Kreisi kasutaja
liitunud: 20.10.2009
|
13.04.2012 12:39:21
c/c++ inline assembler |
|
|
edukalt valmis treinud 10-kond assembleri funktsiooni videotöötluseks ja funktsiooni kood töötab korrektselt.
Kuid tekkis küsimus kas ja kuidas saaks kõige parema kiirusega anda funktsiooni parameetreid üle registritele. Mul ei ole vaja ühtegi parameetrit salvestada pinusse vaid otse üldregistrisse, õigemini laen sinna viida(d) ja pikkuse ning edasi teeb assembler oma aritmeetilist tööd ekraanitäie mälu kallal. Ühtegi parameetrit tagastada vaja ei ole. C standardcall väidab, et kõik funktsiooni parameetrid salvestatakse pinusse. Võtmesõnaga fastcall salvestatakse registrisse, kuid ei ole kindel millisesse registrisse ja kas kõik. Justkui oleks see mis vaja. Kuid googles väitsid mõned, et fastcall salvestab ehk max 2 parameetrit ja teadmata mis registrisse, asm omakorda swapib need registrid lihtsalt niisama ümber ja kokkuvõtteks pole kasu ei miskit. Lisaks väideti, et inline käsuga fastcall ei tööta üldse.
Teine variant oleks fastcalli asemel kirjutada ette funktsiooni argumendile sõna register, kuid jälle registrite mõttetust swapimisest pääsu ei ole sest kompilaator arvab teisiti (et tegu ei ole ühe ja sama muutujaga). Leidsin vaid ühe jutu, kus keegi väitis, et vaid gcc saab asm käsu sees kompilaatorit õpetada, milliseid registreid võiks kompilaator ilma swappimata kasutada. Aga kuidas? (Siin ei mõtle : : "b" (muutuja) varianti, sest see laeb pinust registrisse)
Küsimus olekski et kuidas saaks siis inline assembleris funktsiooni argumente otse soovitud registritesse saada, ilma et neid kuhugi mujale salvestatakse või registris swapitakse? Kompilaatoriks praegu Codeblock windowsi keskkonnas.
Veidi sarnasem küsimus on struktuuriga. Praegu annan struktuuri aadressi funktsiooni kaasa viidana ja seal sees tuleb siis mõningaid kirjeid ja aadresse registritesse lugeda. Kui püüdsin googlega midagi leida inline asm ja struktuuri kasutamisest siis ausaltöeldes ei leidnud mitte midagi. Kas üldse saab C struktuuri muutujat asmi koodi sees kasutada (tavamuutujaid saab)? Struktuur on tüübina deklareeritud. huvitab just kirje->alam data lugemine, see võib olla nii aadress kui ka väärtus.
|
|
tagasi üles |
|
 |
Erti-Chris
HV vaatleja

liitunud: 23.07.2011
|
13.04.2012 18:12:17
Re: c/c++ inline assembler |
|
|
kalvis kirjutas: |
edukalt valmis treinud 10-kond assembleri funktsiooni videotöötluseks ja funktsiooni kood töötab korrektselt.
Kuid tekkis küsimus kas ja kuidas saaks kõige parema kiirusega anda funktsiooni parameetreid üle registritele. Mul ei ole vaja ühtegi parameetrit salvestada pinusse vaid otse üldregistrisse, õigemini laen sinna viida(d) ja pikkuse ning edasi teeb assembler oma aritmeetilist tööd ekraanitäie mälu kallal. Ühtegi parameetrit tagastada vaja ei ole. C standardcall väidab, et kõik funktsiooni parameetrid salvestatakse pinusse. Võtmesõnaga sfastcall alvestatakse registrisse, kuid ei ole kindel millisesse registrisse ja kas kõik. Justkui oleks see mis vaja. Kuid googles väitsid mõned, et fastcall salvestab ehk max 2 parameetrit ja teadmata mis registrisse, asm omakorda swapib need registrid lihtsalt niisama ümber ja kokkuvõtteks pole kasu ei miskit. Lisaks väideti, et inline käsuga fastcall ei tööta üldse.
Teine variant oleks fastcalli asemel kirjutada ette funktsiooni argumendile sõna register, kuid jälle registrite mõttetust swapimisest pääsu ei ole sest kompilaator arvab teisiti (et tegu ei ole ühe ja sama muutujaga). Leidsin vaid ühe jutu, kus keegi väitis, et vaid gcc saab asm käsu sees kompilaatorit õpetada, milliseid registreid võiks kompilaator ilma swappimata kasutada. Aga kuidas? (Siin ei mõtle : : "b" (muutuja) varianti, sest see laeb pinust registrisse)
Küsimus olekski et kuidas saaks siis inline assembleris funktsiooni argumente otse soovitud registritesse saada, ilma et neid kuhugi mujale salvestatakse või registris swapitakse? Kompilaatoriks praegu Codeblock windowsi keskkonnas.
Veidi sarnasem küsimus on struktuuriga. Praegu annan struktuuri aadressi funktsiooni kaasa viidana ja seal sees tuleb siis mõningaid kirjeid ja aadresse registritesse lugeda. Kui püüdsin googlega midagi leida inline asm ja struktuuri kasutamisest siis ausaltöeldes ei leidnud mitte midagi. Kas üldse saab C struktuuri muutujat asmi koodi sees kasutada (tavamuutujaid saab)? Struktuur on tüübina deklareeritud. huvitab just kirje->alam data lugemine, see võib olla nii aadress kui ka väärtus. |
ei saanud küsimusest täielikult aru, tõepoolest on olemas erinevad calling konventsioonid(cdecl,stdcall,fastcall), mis esiteks määravad ära parameetrite asukoha(pinu/registrid) ning mis järjekorras nad on, kui ka selle, kes hoolitseb selle eest, et funktsiooni töö oleks lõpetatud.
hetkel tundub selline mikrosekundi tagaajamine, aga kui tõesti vajalik, siis lase käia.
esiteks on olemas erinevad inline asmi syntaxid, MSVC toetab nt AT&T, kuidagi sai vist häkkida ka GCC inline asmi külge,(CodeBlocks on GCCiga enamvähem)
siin on olemas mingisugune reference/õpetus: http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
sa võid teha a'la:
asm ("movl %%eax, %0\n" :"=r"(myval));
asm ("movl %%ebx, %0\n" :"=r"(myval2));
call_C_function();
|
ning call_C_function() siis töötleb neid registreid(soovitan how-to täiesti läbi lugeda)
kuigi kui funktsiooni kutsud, siis on overhead kah olemas(alustades nt sellest, et return address läheb ikka pinusse, kui ka parameetrite offset aadress pinus(EBP)),
kui sa sellest kah lahti tahad saada, siis pead äkki oma asmi embeddia __asm{} tagide vahele, ehk,et funktsiooni kutsung jääks üldse ära.
või nt tegema uue funktsiooni kasutades __declspec(naked) - see tekitab olukorra, kus kompillaator ei genereeri mingit funktsiooni vaid ütleb, et sina hoolitsedkõige eest(kuidas parameetreid edasi anda, kuidas tagasi hüpata execution pointi jne. + kasutada tuleks siis __asm{} funktsiooni sees.)
http://www.unixwiz.net/techtips/win32-callconv-asm.html
noo struktuuri muutuja või 'tavamuutuja', tegelikult mingit vahet ju ei ole.(assembleri levelil), ehk, et ma ei näe, miks ei võiks töötada.(nt myval asemel lihtsalt mystruct->myval võiks küll pelada, kui ei tööta, siis peaks mingi syntax tal ikkagi olemas olema)
|
|
Kommentaarid: 1 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
0 :: |
1 |
|
tagasi üles |
|
 |
kalvis
Kreisi kasutaja
liitunud: 20.10.2009
|
13.04.2012 19:01:25
|
|
|
See üldine jutt oli läbi uuritud. Püüan täpsustada
praegu, ehk tavaoludes on foo (int *a, int *b, int count) lähevad *a , *b ja count kõik pinusse kus ma siis sinu näite järgi "r" (*a) ... laen nad registrisse %ebx, %ecx ja %edx. Tegu on tõesti põhimõttelise mikrosekundite mänguga, soov on jätta pinusse laadimine vahele (ehk sellejagu võimaldab ehk mikrosekundi aega), on ju C-s selline võimalus olemas
c on olemas võimalused otse registrisse:
1. fastcall. jutujärgi paneb ta kindlast *a mingisse registrisse ja *b mingisse teise registrisse, counti viskab pinusse (võibolla ka registrisse). Minu soov oleks nad kindlasti saada nii, et nad olleksid järgnevas assembleri koodis just õigetes registrites. Kahjuks fastcall ei ütle kompilaatorile, et ta pani need kindlasti registritesse %ebx=*a, %ecx=*b ja %edx=count, võibolla pani ta %eax=*a, %edx=*b ja %ecx=count. seega järgmine käsk swapitakse kõik kolm registrid omavahel ümber ja võimatu on saada ajalist võitu, pigem kaotust. Aga võibolla paneb ka õigesti, ma ei tea.
2. foo (register int *a, register int *b, register int count) teeb jämedalt sama mis fastcall, kuid gcc pidi saama õpetada kuhu registrisse ta paneks. ja järgnevas käsus : : "r" (*a) arvestab juba õpetuses toodud eeskirjaga, ehk funktsioon jätab lihtlabaselt vahele argumentide pinusse laadimise ja asendab selle otseselt registrisse laadimisega. Kuna gcc pidi seda oskama siis loodangi, et keegi on sellega kokku puutunud
Tegu on teoreetilise lähenemisega saada ajavõitu üleliigse asja ärajätmises. Aga kui see on olemas siis patt on jätta kasutamata.
Järgmine nädal proovin c struktuuri otse assembleris ära, kui toimib annan teada.
|
|
tagasi üles |
|
 |
Ho Ho
HV Guru

liitunud: 16.02.2002
|
13.04.2012 19:16:21
|
|
|
Millest sa järeldad, et toimub lisa kopeerimine? Lasid GCC'l peale optimisatsioone ASMi välja pritsida ja sealt oli näha või ise lihtsalt oletad, et ehk tehtakse nii? Samuti olukorras kus x86 prosedel on kordades rohkem rename registreid kui "päris" registreid siis see kopeerimine on raua tasemel väga suure tõenäosusega lihtsalt no-op.
Ehk siis vähem oletusi, rohkem reaalseid katseid ja profileerimist. Nii prose kui kompilaatorid on targemad kui sa arvatagi oskad
_________________ Teach a man to reason and he'll think for a lifetime
Common sense - so rare that it's a damn superpower
Vaadates paljude inimeste sõnavõtte siin ja mujal jääb üle ainult klassikuid tsiteerida - "I weep for humanity" |
|
Kommentaarid: 106 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
1 :: |
86 |
|
tagasi üles |
|
 |
Smith
HV veteran

liitunud: 25.08.2002
|
13.04.2012 19:22:42
|
|
|
Natuke arusaamatuks jääb, mis hirmus swap sul seal toimub. Mis registritesse lähevad parameetrid, see peaks ikka kindel järjekord olema. Ja see, mismoodi C struct mälus tegelt on peaks ju ilusti dokumenteeritud olema, seda ei laota sinna mingi randomiga. Ilusti järjest jookseb, alignment padding tuleb küll arvesse võtta (või likvideerida #pragma pack (1) abil).
Aga laias laastus, kui on mikrosekundite mäng, siis võiks ju kõik kohe assembleris teha. Asi on 100% oma kontrolli all, hunnik vahekihtide tekitatud pseudoprobleeme kaob otsekohe, ja kindlasti võidab siit-sealt nii mõnegi väärtusliku mikrosekundi.
_________________ Only the Central Computer knows the truth |
|
Kommentaarid: 158 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
1 :: |
145 |
|
tagasi üles |
|
 |
Ho Ho
HV Guru

liitunud: 16.02.2002
|
13.04.2012 19:32:22
|
|
|
Mikrosekund on tegelikult terve igavik. Viimase 10a jooksul välja lastud prosede puhul räägime ühe lisa registrist-registrisse kopeerimise puhul sisuliselt nanosekundi murdosast kuna rõhuvas enamuses juhtudes seda rauas ei tehta register renamingu tõttu.
_________________ Teach a man to reason and he'll think for a lifetime
Common sense - so rare that it's a damn superpower
Vaadates paljude inimeste sõnavõtte siin ja mujal jääb üle ainult klassikuid tsiteerida - "I weep for humanity" |
|
Kommentaarid: 106 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
1 :: |
86 |
|
tagasi üles |
|
 |
Bssldr
HV kasutaja
liitunud: 05.12.2009
|
14.04.2012 23:28:07
|
|
|
Kas oled kindel, et sinu käsitsi kirjutatud asm on kiirem, kui kompilaatori poolt optimiseeritud kood? Kas valdad kõiki uuemaid instruction set'e? Näiteks uus MSVC11 teeb nüüd auto-vectorization'i, keerab olemasoleva koodi kohe mitu korda kiiremaks, ilma et ise peaks midagi tegema.
|
|
Kommentaarid: 9 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
0 :: |
8 |
|
tagasi üles |
|
 |
Ho Ho
HV Guru

liitunud: 16.02.2002
|
15.04.2012 20:28:15
|
|
|
Bssldr kirjutas: |
Näiteks uus MSVC11 teeb nüüd auto-vectorization'i, keerab olemasoleva koodi kohe mitu korda kiiremaks, ilma et ise peaks midagi tegema. |
Teeb jah kuid selleks, et ta seda teha oskaks tuleb oma koodi üsnagi spetsiifiliselt kirjutada. Intrinsicuid pruukides on tulemus valdavalt oluliselt parem kui autovectorization ning ka käsitsi kirjutatud ASM.
_________________ Teach a man to reason and he'll think for a lifetime
Common sense - so rare that it's a damn superpower
Vaadates paljude inimeste sõnavõtte siin ja mujal jääb üle ainult klassikuid tsiteerida - "I weep for humanity" |
|
Kommentaarid: 106 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
1 :: |
86 |
|
tagasi üles |
|
 |
kalvis
Kreisi kasutaja
liitunud: 20.10.2009
|
16.04.2012 14:29:55
|
|
|
C-s ei saa otse kirjutada ROL ja bswap käske (neid on veel, mida ma vajan ja mis ühe-2 käsuga teevad kõik mis ma vajan).
Kõik käsud on lühimad ja ei kujuta ette, et veel lühemalt oleks võimalik teha. Samaväärselt küll.
Praegu registrisse viida aadres, data registrisse, 1-3 aritmeetilist tehet, data kas samale või teisele viidale tagasi. Eripära ongi, et mälublokid on suured ja töötavad real-times. Kui saaks veel op.süsteemi õpetada, et lae vahemälusse viitade mälublokid... ja pärast mittekasutamist võib ta vabastada.
Assemblerist pole võimalik mitte kunagi kirjutada (üheskis kõrgkeeles) veelgi lühemat või kiiremat programmi. Samakiiret ja sama lühikest saab masinkoodis. Käpardist programeerija muidugi see õnnestub, kuid ma olen mikrokontrollerites assembelis sina peal (non-Intel ja mõned vanad 8 bit protsessorid)
Registrite swappimisega sain alguses ise hakkama, kirjutasin data konkreetsele registrile (nii nagu intel soovitab count eax registrisse, viida aadress ebx, data eax, , kuid asm ::: tabelis määrasin kogenematuses vabad. Ja siis ta swapip alguses ühtpidi, pärast teistpidi. See on kompileerimise koodis näha (poleks teadnud, kui poleks viga asmis teinud ja läksin vaatama mis seal on).
Loodetavasti on neis kahes lingis rohkem selgitatud, mida ma soovin.
http://www.gamedev.net/topic/206122-using-__fastcall-amp-inline-at-the-same-time/
http://stackoverflow.com/questions/10068525/can-a-function-be-fastcall-inline-in-linux-kernel
|
|
tagasi üles |
|
 |
Fukiku
Kreisi kasutaja

liitunud: 06.11.2003
|
16.04.2012 14:41:08
|
|
|
Aga korrates taaskord küsimust - kas sellele paanilisel kiiruse tagaajamisel mingi objektiivne põhjendus ka on? Kas su rakendus ei jookse praegu piisavalt kiiresti?
Premature optimization is the root of all evil. - oled ehk kuulnud?
_________________ Foxic is just a simple fox
Enne kui sa küsid oma küsimuse - küsi seda vannipardilt! Rangelt soovitatav enne programmeerimise alafoorumisse uue teema tegemist. |
|
Kommentaarid: 2 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
0 :: |
2 |
|
tagasi üles |
|
 |
Ho Ho
HV Guru

liitunud: 16.02.2002
|
16.04.2012 14:48:43
|
|
|
kalvis kirjutas: |
Kui saaks veel op.süsteemi õpetada, et lae vahemälusse viitade mälublokid... ja pärast mittekasutamist võib ta vabastada. |
http://gcc.gnu.org/projects/prefetch.html#ia64
kalvis kirjutas: |
]Assemblerist pole võimalik mitte kunagi kirjutada (üheskis kõrgkeeles) veelgi lühemat või kiiremat programmi |
http://en.wikipedia.org/wiki/Intrinsic_function
http://people.sc.fsu.edu/~jburkardt/c_src/gcc_intrinsics/gcc_intrinsics.html
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
Jah, sa võid võtta intrinsicutega kirjutatud koodi, lasta kompilaatoril sellele n+1 optimisatsiooni teha ning ASM'i väljundit veel omakorda käsitsi parandada kuid jugen kahelda, kas sa ikka suudad sealt veel miskit asjalikumat teha (eeldusel, et kasutad vähe paremat kompilaatorit kui MSVC) ning veel vähem usun, et suudaksid ilma kompilaatori abita teha optimaalsema asja kui korralikult intrinsicutega kirjutatud asja kompilaator optimeerida oskab.
kalvis kirjutas: |
]Käpardist programeerija muidugi see õnnestub, kuid ma olen mikrokontrollerites assembelis sina peal (non-Intel ja mõned vanad 8 bit protsessorid) |
Mikrokontrollerid on üüratult palju lihtsama prosearhitektuuriga kui kaasaaegsed x86d ning arvestades, et sa pole kursis isegi prefetch funktsionaalsuse eksisteerimisega siis seda enam süveneb minus kindlus, et kompilaator oleks antud hetkel "targem" kuna teab kõvasti rohkem all oleva prose arhitektuurist ning kuidas see täpselt sisemiselt töötab
Fukiku kirjutas: |
Aga korrates taaskord küsimust - kas sellele paanilisel kiiruse tagaajamisel mingi objektiivne põhjendus ka on? |
Mind pigem huvitaks kui suur kiiruserinevus on selle käsitsi asmis kirjutatu ning naiivse C koodi vahel. Samuti uuriks huviga toda C koodi
_________________ Teach a man to reason and he'll think for a lifetime
Common sense - so rare that it's a damn superpower
Vaadates paljude inimeste sõnavõtte siin ja mujal jääb üle ainult klassikuid tsiteerida - "I weep for humanity" |
|
Kommentaarid: 106 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
1 :: |
86 |
|
tagasi üles |
|
 |
kalvis
Kreisi kasutaja
liitunud: 20.10.2009
|
19.04.2012 14:45:39
|
|
|
tsitaat: |
Aga korrates taaskord küsimust - kas sellele paanilisel kiiruse tagaajamisel mingi objektiivne põhjendus ka on? Kas su rakendus ei jookse praegu piisavalt kiiresti? |
Momendil otseselt vaja ei ole. Jookseb ka üle pinu piisavalt kiiresti.
Küsimus oli esitatud hariduslikel eesmärkidel, et kas on võimalik veelgi optimaalsemalt kirjutada. Teada on, et justkui oleks. Aga kuidas? Kui keegi teab kuidas siis edaspidi kasutaksin mitte vaid sellel konkreetsel juhtumil vaid tulevikuski.
HoHo antud linkide ja sealt leitud tarkuse laiendatud materjalide läbivaatamisel võib tõdeda:
1. Lühikest assembleri koodi pole mõtet kutsuda üle funktsiooni vaid kasutada kas otse koodis või siis instrinsc.
2. SIMD käskudega saan kas otse assembleris või pea samaväärsete c ja intrinsc käskudega ära tehtud, SIMD paralleelsuse tõttu kindlasti kiiremini. Kas just kohe kõik, kuid üksjagu kindlasti. Lihtsamad kirjutan esimesel võimalusel SIMD ringi.
3. Data Prefetch annab kindlasti rohkem ajavõitu kui algselt teemas püstitatud küsimus.
4. Leidsin Inteli intrinsc koos valmis C käskudega ja librariga SIMD ja intrinsc kasutamise kohta, et assemblerit polegi esialgu vaja kasutada. Arvatavasti kompileerub sealne C käsk 1:1 assembleri, aga ma ei pea niipalju võimlema. Antud teema on üsna mahukas, mõneks ajaks on õppimist oi kui palju.
|
|
tagasi üles |
|
 |
Ho Ho
HV Guru

liitunud: 16.02.2002
|
19.04.2012 15:39:59
|
|
|
kalvis kirjutas: |
Lühikest assembleri koodi pole mõtet kutsuda üle funktsiooni vaid kasutada kas otse koodis või siis instrinsc |
See kehtib absoluutselt iga funktsiooni väljakutse kohta. Kui funktsioon ise võtab mõnikümmend kuni mõnisada takti siis välja kutsumise overhead on juba täiesti tuntav. Eriti hulluks läheb asi veel siis, kui tegu on virtuaalfunktsiooniga.
kalvis kirjutas: |
SIMD käskudega saan kas otse assembleris või pea samaväärsete c ja intrinsc käskudega ära tehtud, SIMD paralleelsuse tõttu kindlasti kiiremini. Kas just kohe kõik, kuid üksjagu kindlasti. Lihtsamad kirjutan esimesel võimalusel SIMD ringi. |
SIMD'i juures ülioluline on oma andmestruktuurid õigesti mälus hoida. Googeldamise keywordid "structure of arrays" ja "memory alingment". Samuti tasub meeles pidada, et kui on tarvis FPU'd kasutada siis praktiliselt iga käsu puhul on vastava tehte SIMD variant kiirem kui x87 alternatiiv, isegi kui on tarvis ainult ühe väärtusega noid tehteid teha.
kalvis kirjutas: |
Data Prefetch annab kindlasti rohkem ajavõitu kui algselt teemas püstitatud küsimus |
Seda kindlasti. Viimase taseme cache miss tähendab nonde vanemate prosede puhul ooteaga suurusjärgus ~100-200ns. Ehk siis prefetchimise pead vastavalt umbes nii pikalt ette ära tegema. Kui aga hakkad liiga pikalt ette fetchima siis uputad cached üle ning pole ka erilist kasu. Sama lugu kui su rakendusega paralleelselt jookseb masinas veel miskit mis kõvasti datat cachesse tirib.
Intrinsicute peamine boonus on, et neid korralikult kasutades oskab kompilaator automaagiliselt registrite majandamise vägagi edukalt ise ära optimeerida ning ei pea hakkama vaevuma selle käsitööga.
_________________ Teach a man to reason and he'll think for a lifetime
Common sense - so rare that it's a damn superpower
Vaadates paljude inimeste sõnavõtte siin ja mujal jääb üle ainult klassikuid tsiteerida - "I weep for humanity" |
|
Kommentaarid: 106 loe/lisa |
Kasutajad arvavad: |
   |
:: |
0 :: |
1 :: |
86 |
|
tagasi üles |
|
 |
|
lisa lemmikuks |
|
|
sa ei või postitada uusi teemasid siia foorumisse sa ei või vastata selle foorumi teemadele sa ei või muuta oma postitusi selles foorumis sa ei või kustutada oma postitusi selles foorumis sa ei või vastata küsitlustele selles foorumis sa ei saa lisada manuseid selles foorumis sa võid manuseid alla laadida selles foorumis
|
|
Hinnavaatlus ei vastuta foorumis tehtud postituste eest.
|