JJ AAAAAAAA KK KK II NN NN JJ AA AA KK KK II NNNN NN JJ AAAAAAAA KKKKKK II NN NN NN JJ AA AA KK KK II NN NNNN JJ JJ AA AA KK KK II NN NNN JJJJJJJJ AA AA KK KK II NN NN e z i n e ______________________________________________________________________ | 6. alea (Balioa: 81k) | |______________________________________________________________________| | 2005/01/19 | |______________________________________________________________________| | | | Segurtasun elektronikoari buruzko fanxina, euskera hutsez | | | |______________________________________________________________________| | | | Parte hartzaileak: edit,niuBAI, Regexp, Espoz&Mina, | | NapharHack, Assert eta KM | |______________________________________________________________________| | email helbidea: jakinezine@euskalerria.org | | jakin@kaixo.com | | jakinezine@gmail.com | |______________________________________________________________________| | Web helbidea: http://www.jakin.tk | | http://jakin.sf.net | | | |______________________________________________________________________| Ale honetan: Zb Artikulua Egilea ______________________________________________________ 0. Hitzaurrea edit 1. RFIDak Regexp 2. Unix sistema programazioa (III) Espoz&Mina 3. TCP/IP programazioa (VI) niuBAI 4. NASM mihiztadura lengoaia NapharHack 5. CLIPS inferentzi motorea Assert 6. Kultura km 7. Albisteak,Estekak,Agurrak edit ______________________________________________________ "ezagutza" iz. 1. Ezagutzeko ekintza eta horren ondorioa. Ezagutza osoz, ezagutza gabe egindako bekatua. 2. Aitortzea, onartzea. Norberaren hutsen ezagutza. 3. Ongiegilearenganako esker ona agertzea. Zureganako ezagutzaz bihotza betea. * ezagutzaren adierazpide. INFORM. Adimen artifizialaren alorretako bat, giza ezagutza, ideia eta pentsamenduaren egiturak aztertu eta programazio-lengoaia baten bidez adieraztea helburu duena. || ezagutzaren teoria. FIL. Pentsamendua eta kanpoko munduaren arteko harremanak azaltzea helburu duena. * (Norbaiten edo norbaitekin) EZAGUTZAK EGIN. (((((((((((((((((((((((((((((((((((( Jakin dezagun!! )))))))))))))))))))))))))))))))))))))) 0. Hitzaurrea __________________________ <0> 6 ale 6 Asko kostata ere, zuen aurrean seigarren Jakin ezinea daukazue. Azkeneko hiruhileko interesgarri bat pasa ostean (hackmeeting eta bestelako gertakizunak medio) berriro zuekin gaude edukin "berriekin". Komatxo artean jarriko dugu berria hitza, izan ere fanxin honen enborra berdin mantentzen baita: tcp/ip eta unix programazioa. 6 ale eta sei aldiz jaso dugu niuBAI-ren partetik tcp/ip programazio adibideak. Nafarroatik unix sistema munduan murgiltzen jarraitzen dugu. Regexp-en eskutik perl lengoaiaren erabilera zabala aurkezten da kasu honetan RFIDen kontrola lortzeko. Mihiztidaura lengoaiaren sekretuak argititzeko NH dator berriz, oraingo honetan NASM lengoaiaren oinarriak azalduz eta exekutagarrien arazketa pausuak erakusteko. Bestalde adimen artifiziala ez dugu bistatik galduko: seigarren ale honetan Assert sistema adituak eraikitzeko CLIPS tresnaz arituko baita. Kode mordoa beraz, baina Jakinen estilora atxekituz kode guztia ongi azalduta egotea saiatzen gara. Berriro ere dei eta dehiadar egiteko beharrean gaude zuen laguntza jasotzeko. Edukin gosea daukagu!!! Ez duzue zertan kode konplexurik bidali behar, ezta azken uneko teknologiari buruzko artikulurik. Kontaiguzue zer egiten duzue neguko gau hotzetan zeuen gelaren babesean :D, edo bidali UNDERCONaren kronika labur bat... Hitz berriak? Nahi gabe hitz tenkinkoen itzulpena egiten da askotan. Ekidiezina. Azkeneko aleetan (agian) ongi euskaratu gabe dauden hitz zenbait agertzen dira, besteak beste: Iratxoa = Daemon Usnatzailea = Sniffer Meta = Stack Zizarea = Worm Arazketa = Debug Egiteke = TODO Ez dakigu itzulpenak zuzenak izango ote diren; dena den euskeratuta ez baldinbadaude, hortxe geratzen dira proposamen bezala. Kasu honetan ere zeuen eritziak ongi etorriak izango dira. Oharra: azkeneko unean, PHP zizare bati buruzko idatzia jaso behar genuen, baina dagoeneko hispasec bitartez beste batetaz hitzegin denez egileak bertan behera uztea erabaki du. Hala ere saiatuko gara hurrengo aleari begira edukin hori gehitzea. Ahaztu baino lehen, posta zerrenda sortu dugu!!! (ikus albisteak) Lepokoa heldu, bagoaz: # make jakin -edit- 1. RFIDak __________________________ <1> RFID: Radio Frecuency IDentification [ez gara etorkizunaz ari, hau oraintxe gertatzen ari da] 1990 urte inguruan MITen erditutako proiektua da hau, hasiera batean errobotika arloan identifikazio arazoari konponbide bat emateko. Nola ezagutu dezake automata batek bere ingurune hurbila? hasierako hurbilpena errobotari zentzumenak gehitzea zen: ikusmen artifiziala kasu, baina bide zaila eta luzea da hori. Enpresek arazo bera daukate: gauzak identifikatu nahi dituzte, eta pertsona bat (bere 5 zentzuekin) erabili ordez kontrako egitea asmatu zuten; objektuak izango dira bere burua identifikatuko dutenak. Horretarako objektuek txip bat daramate bere identifikazioa adierazten duena, eta are gehiago identifikazio hori hedatzen dute. Txipak bere identifikazioa irrati seinale baten bitartez hedatzen du, aktiboki hala pasiboki (eskatzen zaionean). Tamaina: muki bat baino txikiagoak izan daitezke, urteak pasa ahala geroz eta txikiagoak izango dira: atentzioa dei dezakeena antena da: txipak seinaleak jaso eta bidali behar ditu derrigorrez, eta horretarako hari fin bat eduki dezake. Hala eta guztiz ere, ikustezinak izatera bideratuta daude. Enpresa handiek tekonologia honen garapenerako diru mordoa sartzen ari dira eta lankidetzan daude RFID erabilera bermatzeko. Zertarako RFIDa? aplikazioa argiena stocken kontrol zehatza da, denbora errealean eta inbentario luzerik gabe. Honek kriston abantailak dauzka baina beste teknologia asko bezala gure intimidadean kuxkuxeatzeko erabili daiteke. Objektu guztiek identifikazio txipa eramaten baldinbadute, nola dakigu objektua desaktibatuta dagoen ala ez? Are gehiago: nortasun agirietan ala pasaporteetan RFID jartzea erabakitzen bada AKABO! gure pribatasuna pikutara joango da, edozein unean jakin baitaiteke non gauden. Erosotasunaren aitzakiarekin salduko digute ziur asko. RFIDa kontrola dezakegu? Bai, euskalerrian RFIDeentzako aparailuak eros daitezke. Donostian bertan badago enpresa bat adibidez eskuan eraman daitezkeen RFID irakurleak saltzen dituena. http://www.tecnipesa.com adibidez; "identificacion" gunean aparailu mordoa aurkezten da, gehienak eskuan eramateko dira. Orokorrean ordenadore eta RFIDen mundua elkartzeko modu xinpleak daude: RFID irakurleak serie interfaze batekin konektatuz (RS-232), txartel irakurle bat erabiliz (pcmciak badira), hala RFID irakurle propioa eginez. Artikulu honetan serie interfazearen kasua ikusiko dugu. Perl lengoaia ------------- Erabateko kontrola nahi? perl lengoaia erreskatera dator!! CPAN gordailuan (perl moduluen bilduma nagusia), lau modulu jeitsi daitezke lanean hasteko. Egia esan ez dute urte bat baino gehiago eta garapen oso oso xinpleak dira, baina hasiera bat da. Hauexek dira moduluak: RFID-Base : oinarrizko irakurlea, abstraktoak. RFID-EPC : EPC motako etiketak irakurtzeko RFID-Matrics : Matrics etxeko irakurleekin erabiltzeko, serie ala TCP bitartez RFID-Alien : Alien etxeko irakurleekin erabiltzeko, serie ala TCP bitartez -----------------------8<----------------------------------------------------------------- #!/usr/bin/perl -w # Matrics RFID irakurlearekin datuak jasotzeko adibide tontoa # by Regexp - Jakin 6 # Dependentziak: RFID::Base # RFID::Matrics modulua : Scott Gifford adibide konplexuagoekin. # Informazio gehiago: http://www.eecs.umich.edu/~wherefid/code/rfid-perl # Liburutegiak use RFID::Matrics::Reader; use RFID::Matrics::Reader::Serial; # EGTK: jeitsi moduluak BEGIN { eval 'use Device::SerialPort'; } #use Device::SerialPort; # Aldagaiak my $com; my $irakurlea; my $debug = $ENV{MATRICS_DEBUG}; my $nodoa = 4; my %datuak; my $itxoitea = 0; my @antena = {}; $| = 1; # Kodea print "OK RFID adibidea - by Regexp - Jakin ezine 6\n"; print "Ea zer dagoen serie portu honetan: " . $ARGV[0] . "\n";; # Serie portua irekitzen saiatzen gara... if ($INC{'Device/SerialPort.pm'}) { $com = Device::SerialPort->new($ARGV[0]) or die "Ezin izan dut serie portua ireki: $! !\n"; } else { die "Ez dut Device/SerialPort.pm modulua aurkitu.\n"; } # Orain RFID irakurle objektua sortzen dugu!!! $irakurlea = RFID::Matrics::Reader::Serial->new(Port => $com, Node => $nodoa, Debug => $debug, Timeout => 15, @antena?(AntennaSequence => \@antena, Antenna => $antena[0]):(), ) or die "Putza! ezin izan dut RFID irakurle objektua sortu: $!\n"; # Antenaren balioak esleitzen ditugu $irakurlea->set(PowerLevel => 0xff, Environment => 4,) == 0 or die "Ezin izan ditut irakurlearen balioak esleitu: $!\n"; # Orain datu irakurketa hasten da, begizta amaigabean for(;;) { foreach my $etiketa ($irakurlea->readtags) { # Hona hemen irakurketa %datuak = $etiketa->get('ID','Type','Antenna'); # Datuak pantailaratzen ditugu print "DATUAK> Mota: $datuak{Type} - ID: $datuak{ID} - Antena: $nodoa.$datuak{Antenna} \n"; } # Itxoite denbora sartzen dugu sleep($itxoitea); } --------------------------8<-------------------------------------------------------------- Xinplea ezta? dena den, irakurle honen barne funtzionamenduan murgiltzeko Reader.pm modulua aztertzea gomendatzen dizuegu. Bertan inplementazio xehetasunak aurki daitezke. Eta zuen irakurle propioa sortzeko bidea RFID::Base moduluaren funtzioak jarraitzea da. Matrics eta Alien irakurleak Base-ren inplementazio zehatzak dira azken finean. Java lengoaian: RFDUMP ---------------------- Arraro xamarra egiten da RFIDak irakurtzeko beste softwarea goi mailako lengoai interpretatu batean (berriz!) egotea. Baina programa hau ezaguna egin da eta are gehiago: bere webgunea http://www.rf-dump.org/ RFID buruzko informazio hedapen gunea bilakatu da. Beraz, kodeaz gain asko ikas daiteke. Bertan rf-dump kodea jeitsi daiteke: javan egina dagoenez edozein lekutan egikaritu daiteke, beti ere alegiazkoa java makina edukita noski: JRE bakarrik programa egikaritzeko ala ingurune osoa (SDK garapen ing.) programan aldaketak sartzeko. RFDUMP programa bisual ikusgarria da, begirada bat botatzea pena merezi du. Bere "TODO" edo "egiteke" zerrendan RFIDen pasahitz apurketa dator :) Kontrol fisikoa --------------- Litekeena da RFID irakurle bat eskuraezina izatea. Ba al dago moduren bat txip hauek izorratzeko? Bai, bat baino gehiago: - Apurtuz (orratz batekin adibidez) - Antena konexio moztuz (txikia bada zaila) - Mikro-uhin labean sartuz (basati xamarra) - Produktu kimikoen bitartez - Irrati seinaleekin (zirkuitoa erretzeko) - Uretan sartuz (ez dabil beti, arropan jar daitezkeen RFID txipak badira) Printzipioz eroalea den edozein materialak RFID seinaleak blokeatzen ditu. Horregatik zail xamarra da (momentuz), RFIDak metalezko gauzetan sartzea. Badirudi berdin gertatzen dela likido eta plastikoekin. Elektronika jakinda, RFID irakurle bat eraiki daiteke: -Intel etxeak irakurle bat atera nahi du eta dokumentazioa eskeintzen dute jendeak proba dezan. Irakurle propioa egiteko ere balio dokumentazioak. Linux eta windowserako dago. http://seattleweb.intel-research.net/projects/HandheldRFIDReader/ -Gune honetan irakurle bat eskeintzen da eta bere eskema ere aurkezten da. http://www.zygo.btinternet.co.uk/offer011.html Garapenak azkar mugitzen ari dira. Nokiak bere mugikorretan RFID irakurleak sartu behar ditu adibidez http://www.mobilemag.com/content/100/104/C2607/ Gauza askoz gehiago esan daitezke, baina orokorrean adierazi nahi dudana hau da: kontrol teknologia honi buelta emateko aukera daukagu. Ezagutza banatu. Esker mila: Eskerrak eman nahi dizkiogu Metabolik-eko Txipiri informazioa bidaltzeagatik. Ziberkontrolari buruzko hitzaldiak musutruk ematen ditu (jajaja), eta hauetan RFID buruz hitzegiten du. Hitzaldia errepikatzen denan datu berriak sartzeko ahalegina egiten du gainera. Jasozu agur bero bat. END { warn("Argi ibili, eta burua erabili"); } -Regexp Angelorum- 2. Unix sistema programazioa (III) __________________________ <2> Kaixo lagunok! Unix sistema gure menpe hartzeko ahaleginari atxekituz gaurkoan funtsezko diren bi elementu ikusiko ditugu: batetik harien sorkuntza eta bestetik sarrera/irteera multiplexatua select funtzioaren bitartez. Biak oso baliogarriak izanen dira kode ona sortzeko garaian. Has gaitezen Goazen HARIRA ------------- Hariak, prozesuak ez bezala ez dute bere aitaren datuen kopiarik egiten eta prozesu arruntak baino askoz arinagoak dira. Aldagaiak ez dira kopiatuko hari bakoitzean, elkarbanatu eginen dira. Hariak sortzen direnean gure programarekin batera aldiberean egikaritzen dira. Beraien artean sinkronizazio, sorkuntza eta suntsiketa ekintzak burutu ahal izanen ditugu. Gaurkoan kode xinple batekin hasiko gara non prozesu batek hiru hari sortzen dituen. Hari bakoitza funtzio bati atxekituta sortzen da, hots, funtzioa hari bezala egikaritzen da. -------------------8<--------------------------------------------------------------- /** * $Id$ * * hariak.c thread edo hariak probatzeko programa * kasu honetan hariak etengabeko egikaripena daukate * by Espoz&Mina Jakin ezine 6 */ #include #include #include // hemen hari bezala egikarituko diren atazak izendatzen ditugu. void kontagailua(int *kont); void inprimatu_datuak(); void hartu_datuak(); // aldagai globalak int konta = 0; char testua[80]; int main (int argc, char *argv[]) { // Hona hemen harien definizioa pthread_t hari_bat, hari_bi, hari_hiru; printf("Hariak probatzeko kodea. Jakin ezine 6\n"); // Lehen haria sortzen dugu kontagailua funtzioari atxekituta if ( pthread_create(&hari_bat, NULL, (void *)kontagailua, (int *) &konta) ) { perror("Errorea haria sortzerakoan: kontagailua"); exit(EXIT_FAILURE); } // Bigarren haria sortzen dugu inprimatu_datuak funtzioarekin lotuta if ( pthread_create(&hari_bi, NULL, (void *)inprimatu_datuak, NULL) ) { perror("Errorea haria sortzerakoan: inprimatu_datuak"); exit(EXIT_FAILURE); } // Hirugarren haria sortzen dugu, hartu datuak funtzioari lotuta if ( pthread_create(&hari_hiru, NULL, (void *)hartu_datuak, NULL) ) { perror("Errorea haria sortzerakoan: hartu_datuak"); exit(EXIT_FAILURE); } // join batekin prozesu nagusia hari_bat bukatu harte blokeatuko da. begizta amaigabea // denez, prozesua ez da inoiz bukatuko. pthread_join(hari_bat,NULL); printf("Hariak probatzeko kodea.\n"); exit(EXIT_SUCCESS); } // programa nagusiaren amaiera // kontagailua: zenbaki bat inkrementatzen du void kontagailua (int *kont) { while(1) { sleep(2); printf("[Ataza-kontagailua] Kontatzen: kontagailua = %d\n",(*kont)++); } } //inprimatu_datuak datu batzuk pantailaratzen ditu void inprimatu_datuak () { while(1) { sleep(3); printf("[Ataza-inprimatzailea] Inprimatzen: kontagailua = %d\n",konta); sleep(2); printf("[Ataza-inprimatzailea] Inprimatzen: testua = %s\n",testua); } } //irakurri_datuak datuak teklatutik jasotzen ditu, eta blokeatuko da datuen zain // gainontzeko hariak ez dira blokeatuko, aldibereko egikaritzapena baita void hartu_datuak () { while(1) { sleep(5); printf("sartu testu bat: \n"); scanf("%s",&testua); } } -----------------8<----------------------------------------------------------------- Kode hau konpilatzeko pthread liburutegia zehaztu beharko da aukeretan -l bidez. jakin-0.1.2# gcc -o hariak -lpthread hariak.c Egikaritzapenean emaitza aldakorrak ikusiko ditugu, harien egikaritzapenaren arabera: jakin-0.1.2# ./hariak Hariak probatzeko kodea. Jakin ezine 6 [Ataza-kontagailua] Kontatzen: kontagailua = 0 [Ataza-inprimatzailea] Inprimatzen: kontagailua = 1 [Ataza-kontagailua] Kontatzen: kontagailua = 1 sartu testu bat: [Ataza-inprimatzailea] Inprimatzen: testua = [Ataza-kontagailua] Kontatzen: kontagailua = 2 [Ataza-inprimatzailea] Inprimatzen: kontagailua = 3 [Ataza-kontagailua] Kontatzen: kontagailua = 3 [Ataza-inprimatzailea] Inprimatzen: testua = [Ataza-kontagailua] Kontatzen: kontagailua = 4 sdf [Ataza-kontagailua] Kontatzen: kontagailua = 5 [Ataza-inprimatzailea] Inprimatzen: kontagailua = 6 [Ataza-kontagailua] Kontatzen: kontagailua = 6 [Ataza-inprimatzailea] Inprimatzen: testua = sdf sartu testu bat: [Ataza-kontagailua] Kontatzen: kontagailua = 7 Ctrl-C batekin egikaripena eten daiteke. SELECT funtzioa --------------- Demagun zenbait datu iturrietatik batera irakurri nahi dugula. Datuen zai blokeatuta geratu ordez datuak prest daudenean berehala irakurriko ditugu. Horretarako select funtzioa erabil dezakegu. Hauxe adibidea: -------------8<--------------------------------------------------------------------- /** * $Id$ * select.c * Fitxategien edo S/I orokorraren multiplexazioa * aldiberean irakurri/idazteko. Teknika oso erabilgarria S/Iren zain blokeatuta * ez geratzeko. * Kasu honetan hiru fitxategi erabiliko dira: sarrera fitxategi bat, irteera fitxategi bat, * eta tuberia bat. * Tuberia sortzeko egikaritu hauxe: mknod tuberia p * konprobatzeko ls -l egin eta fitxategi mota p dela ikusiko dugu * * by Espoz&Mina - Jakin ezine 6 * */ #include #include #include #include // programa nagusia. Argumentuak: testu_fitxategia1 testu_fitxategia2 int main (int argc, char *argv[]) { // lehenbizi fitxategi deskribatzaile arraia definitzen da. int fitxategi_desk[3]; // datuak erabiltzeko buffer bat char bufferra[80]; // select bat egiteko fitxategi_deskribatzaile taldea edo watchseta definitu behar da fd_set watchset; fd_set momentuko_watchset; // aldagai laguntzaileak int i = 0; int irakurritako_indizea = 0; int fd_maximoa = 0; // agurra... printf("hariak.c by Espoz&Mina - Jakin ezine 6\n"); // fitxategia edo pipe-a irekitzen dugu. if ( (fitxategi_desk[0] = open(argv[1], O_RDONLY | O_NONBLOCK)) < 0) { perror("Errorea 1 fitxategia irekitzerakoan "); exit(EXIT_FAILURE); } printf("OK, [%s] deskribatzailea irekia: %d\n",argv[1],fitxategi_desk[0]); // 2. fitxategia edo pipe-a irekitzen dugu. if ( (fitxategi_desk[1] = open(argv[2], O_APPEND | O_NONBLOCK)) < 0) { perror("Errorea fitxategia irekitzerakoan"); exit(EXIT_FAILURE); } printf("OK, [%s] deskribatzailea irekia: %d\n",argv[2],fitxategi_desk[1]); // 3. fitxategia edo pipe-a irekitzen dugu. if ( (fitxategi_desk[2] = open(argv[3], O_RDONLY | O_NONBLOCK)) < 0) { perror("Errorea fitxategia irekitzerakoan"); exit(EXIT_FAILURE); } printf("OK, [%s] deskribatzailea irekia: %d\n",argv[3],fitxategi_desk[2]); // watchsetak prestatzen dira FD_ZERO(&watchset); FD_SET(fitxategi_desk[0],&watchset); FD_SET(fitxategi_desk[1],&watchset); FD_SET(fitxategi_desk[2],&watchset); // maximoa ateratzen dugu fd_maximoa = (fitxategi_desk[1]>fitxategi_desk[2]?fitxategi_desk[1]:fitxategi_desk[2]); fd_maximoa = (fitxategi_desk[0]>fd_maximoa?fitxategi_desk[0]:fd_maximoa); printf("Maximoa: %d\n",fd_maximoa); // begiztarekin hasten gara. baldintzan zera begiratzen da: deskribatzaileek edukin berririk // duten ala ez irakurtzeko while (FD_ISSET(fitxategi_desk[0],&watchset) || FD_ISSET(fitxategi_desk[0],&watchset)) { momentuko_watchset = watchset; // orain select erabiltzen da if ( select(fd_maximoa + 1, &momentuko_watchset, NULL, NULL, NULL) < 0) { perror("Errorea select egiterakoan"); exit(EXIT_FAILURE); } for (i=0;i<3;i++) { if (FD_ISSET(fitxategi_desk[i], &momentuko_watchset)) { irakurritako_indizea = read(fitxategi_desk[i], bufferra, 80-1); // irakurri al da zerbait? ikusiko dugu if (irakurritako_indizea > 0 ) { // bai, ikusagun bufferra[irakurritako_indizea] = '\0'; //pantailatik atera printf("%d deskriptoretik irakurritakoa: %s\n",fitxategi_desk[i],bufferra); } else { if (irakurritako_indizea == 0) { // hau itxita dago, watchset-etik at atera close(fitxategi_desk[i]); FD_CLR(fitxategi_desk[i], &watchset); } else { perror("Errorea irakurtzerakoan"); exit(EXIT_FAILURE); } } } }// for } // while // fitxategi guztiak ixten ditugu for (i=0;i<3;i++) { close(fitxategi_desk[i]); } // eta bagoaz exit(EXIT_SUCCESS); } -----------------8<----------------------------------------------------------------- Konpilazioak ez dauka inongo misteriorik. jakin-0.1.2# gcc -o select select.c Ze fitxategiek proba dezakegu hau? erosoena eta adierazgarriena pipe-ak erabiltzea da. Horiek sortu eda idazteko hauxe besterik ez dugu egin behar: jakin-0.1.2# mknod tuberia1 p jakin-0.1.2# ls -l tuberia1 prw-r--r-- 1 root root 0 Oct 3 00:51 tuberia1 jakin-0.1.2# cat > tuberia1 (idazteko zai geratzen da) Hiru tuberia sortu (terminal bat bakoitzeko) eta kodea proba daiteke beste leiho batean_ jakin-0.1.2# ./select tuberia1 tuberia2 tuberia3 hariak.c by Espoz&Mina - Jakin ezine 6 OK, [tuberia1] deskribatzailea irekia: 3 OK, [tuberia2] deskribatzailea irekia: 4 OK, [tuberia3] deskribatzailea irekia: 5 Maximoa: 5 4 deskriptoretik irakurritakoa: epa 5 deskriptoretik irakurritakoa: hirugarrena naiz Tira, nahikoa. Kode hau baliogarria izatea espero dut esparru ezberdinetan (tcp/ip programazioa kasu). Hurrena artio! #define EXIT_SUCCESS 0 exit(EXIT_SUCCESS); -Espoz&Mina- 3. TCP/IP programazioa (V) __________________________ <3> Epa, gabon guztioi. Gaurkoan bi socket motekin jolastuko dugu: RAW socketak eta SOCK_PACKET socketak. RAWak ezagunak dituzue jada, izan ere icmp paketeak sortzen zituen kodea erakutsi baikenuen. Gogoratuko duzuenez RAW socketei eskerrak komunikazioaren parametro guztien kontrola gure esku dago. Gaurkoan UDP datagramak RAW socketen bitartez sortuko ditugu. Datagrama goitik behera eraiki behar da, beraz IP paketea eta bere gainean dagoen UDPa sortu beharko da. Hona hemen kodea, behar dituen azalpen guztiekin. ------------------------8<--------------------------------------------------- /** * $Id: udpsortzailea.c,v 1.6 2004/12/29 16:48:12 root Exp $ * UDP datagrama sortzailea, RAW socket_helbideak erabiliz. * Jakin 6 - http://jakin.sf.net - by niuBAI * * erabilera: udpsortzailea ip_jatorri portu_jatorri ip_helburu portu_helburu edukina */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define IPBERTSIOA 4 // ipv4 momentuz... #define BIZIRAUPENA 60 // Time to Live balioa, bueltaka ez ibiltzeko #define MEZULUZERA 12 #define ID 31337 // IP goiburuari jarriko diogun "marka" :) // goiburua egiaztatzeko funtzioa unsigned short ip_egiaztapena(unsigned short *helbidea, int luzera); /** * programa nagusia */ int main (int argc, char *argv[], char *envp[]) { // Helbideak: jatorri eta helburu struct in_addr jatorri_helb; struct in_addr helburu_helb; // Portuak: jatorri eta helburu unsigned short jatorri_portua; unsigned short helburu_portua; // Socket definizioa struct sockaddr_in socket_helbidea; // UDP goiburua struct udphdr *udpgoiburua; // IP goiburua struct ip *ipgoiburua; // SORTUKO DUGUN PAKETEA: ip_goiburua + udp_goiburua + datuak unsigned char paketea[ sizeof(struct ip) + sizeof(struct udphdr) + MEZULUZERA]; // Mezua unsigned char mezua[MEZULUZERA]; // Socket fitxategi deskribatzailea int socketa, aukerak = 1; // bidaliko ditugun paketeak int pakete_kopurua = 1, i = 0; // Agurra.. printf("UDPsortzailea, udp pakete sortzaile xinple bat. \nJakin ezine 6 - by niuBAI \n"); // Parametro kopuru desegokia pasatzen bada... if (argc < 6) { fprintf(stderr,"Erabilera: %s ip_jatorri portu_jatorri ip_helburu portu_helburu \"edukina\" kopurua\n", argv[0]); return(EXIT_FAILURE); } // Mezuaren luzera aztertzen dugu if (strlen(argv[5]) > MEZULUZERA) { fprintf(stderr,"Errorea, mezua luzeegia da\n"); return(EXIT_FAILURE); } // Balioen esleipena // // jatorri helbidea jatorri_helb.s_addr = inet_addr(argv[1]); // jatorri portua jatorri_portua = (unsigned short)atoi(argv[2]); // helburu helbidea helburu_helb.s_addr = inet_addr(argv[3]); // helburu portua helburu_portua = (unsigned short)atoi(argv[4]); // mezua strcpy(mezua,argv[5]); // pakete kopurua pakete_kopurua = atoi(argv[6]); // Socketa sortzen dugu orain: RAW motakoa!! if((socketa = socket(AF_INET,SOCK_RAW,IPPROTO_RAW)) < 0) { printf("Errorea socket_helbidea sortzerakoan: %s\n", strerror(errno)); return(EXIT_FAILURE); } // IP goiburua sartzeko agindua if(setsockopt(socketa,IPPROTO_IP,IP_HDRINCL,(char *)&aukerak,sizeof(aukerak)) < 0) { printf("Errorea socket aukerak ezartzerakoan: %s\n", strerror(errno)); return(EXIT_FAILURE); } /**** IP goiburua C programazioan : Jakin 3n azalduta ****** struct ipheader { unsigned char ip_hl:4, ip_v:4; // :4 honek esan nahi du bakoitza 4 biteko tam. duela unsigned char ip_tos; unsigned short int ip_len; unsigned short int ip_id; unsigned short int ip_off; unsigned char ip_ttl; unsigned char ip_p; unsigned short int ip_sum; unsigned int ip_src; unsinged int ip_dst; }; // ip goiburuaren luzera: 20 byte (=160 bit) */ // IP paketea sortzen dugu, UDP motakoa ipgoiburua = (struct ip *)paketea; memset((char *)ipgoiburua,'\0',sizeof(struct ip)); ipgoiburua->ip_id = htons(ID); ipgoiburua->ip_hl = 5; ipgoiburua->ip_v = IPBERTSIOA; ipgoiburua->ip_ttl = BIZIRAUPENA; ipgoiburua->ip_p = IPPROTO_UDP; ipgoiburua->ip_len = htons(sizeof(paketea)); ipgoiburua->ip_src = jatorri_helb; ipgoiburua->ip_dst = helburu_helb; // ip_sum: datuak ongi daudela argitzeko esleitzen den funtzioa ipgoiburua->ip_sum = (unsigned short)ip_egiaztapena((unsigned short *)ipgoiburua,sizeof(struct ip)); // UDP goiburua prestatzen dugu udpgoiburua = (struct udphdr *)(paketea + sizeof(struct ip)); printf("UDP goiburua sortuta. Goiburuaren tamaina: %d\n",sizeof( paketea + sizeof(struct ip) )); // Mezuaren edukina esleitzen diogu paketeari //memset((paketea+sizeof(struct udphdr)+sizeof(struct ip)),'0',MEZULUZERA); memcpy((paketea+sizeof(struct udphdr)+sizeof(struct ip)),mezua,MEZULUZERA); /**** UDP goiburua C programazioan : Jakin 3n azalduta ****** struct udpheader { unsigned short int uh_jatorri_portua; unsigned short int uh_helburu_portua; unsigned short int uh_len; unsigned short int uh_check; }; // UDP goiburuaren luzera: 8 byte (=64 bit) */ // UDP goiburuaren datuak esleitzen ditugu: UDP PORTUAK!!! udpgoiburua->source = htons(jatorri_portua); udpgoiburua->dest = htons(helburu_portua); udpgoiburua->len = htons(sizeof(struct udphdr) + MEZULUZERA); udpgoiburua->check = 0; // Socket helbidea egitura hasieratu... memset(&socket_helbidea,'\0',sizeof(socket_helbidea)); // eta balioak esleitzen dizkiogu socket_helbidea.sin_family = AF_INET; socket_helbidea.sin_port = htons(helburu_portua); socket_helbidea.sin_addr = helburu_helb; // To datagrama!! for (i = 0; i < pakete_kopurua; i++) { printf("UDPa bidalitzen [udp [%s:%s >> %s:%s]] ",argv[1],argv[2],argv[3],argv[4]); if(sendto(socketa,&paketea,sizeof(paketea),0x0,(struct sockaddr *)&socket_helbidea, sizeof(socket_helbidea)) != sizeof(paketea)) { printf("Errorea datagrama bidaltzerakoan: %s\n", strerror(errno)); perror("Errorea bidaltzerakoan"); return(EXIT_FAILURE); } printf(" %s--> Bidalita!! \n", mezua); } // Dena ongi, bagoaz return(EXIT_SUCCESS); } /** * ip_egiaztapena * IP goiburuentzako erabil daitekeen egiaztapen kodea. * erabilpena hautazkoa probak egiteko... */ unsigned short ip_egiaztapena(unsigned short *helbidea, int luzera) { register int batura = 0; u_short erantzuna = 0; register u_short *w = helbidea; // hasteko 16biteko hitz guztiak batutzen ditugu while (luzera > 1) { batura = batura + *w++; luzera = luzera - 2; } // carry bita baldinbadago, gehitu if (luzera == 1) { *(u_char *)(&erantzuna) = *(u_char *)w ; batura = batura + erantzuna; } // carrya gehitu berriz batura = (batura >> 16) + (batura & 0xffff); batura = batura + (batura >> 16); erantzuna = ~batura; return(erantzuna); } ----------------------8<----------------------------------------------------- jakin# ./udpsortzailea 64.5.4.34 534 127.0.0.2 1 "ku-ku" 3 UDPsortzailea, udp pakete sortzaile xinple bat. Jakin ezine 6 - by niuBAI UDP goiburua sortuta. Goiburuaren tamaina: 4 UDPa bidalitzen [udp [64.5.4.34:534 >> 127.0.0.2:1]] ku-ku--> Bidalita!! UDPa bidalitzen [udp [64.5.4.34:534 >> 127.0.0.2:1]] ku-ku--> Bidalita!! UDPa bidalitzen [udp [64.5.4.34:534 >> 127.0.0.2:1]] ku-ku--> Bidalita!! jakin# Interesgarria zalantzarik gabe. Kodearen jolas asko egin daitezke, horiek zeuen esku geratuko dira. Usnatzailea ----------- Ingeleraz sniffer deitzen dena "usnatzaile" hitzarekin itzultzea erabaki dugu. Bai adiskideok, SOCK_STREAM, SOCK_DGRAM, SOCK_RAW ezagutzen ditugu, baina SOCK_PACKET batekin usnatzailea garatu daiteke. Usnatzaile batek orokorrean zera egiten du: sare interfazea (eth0 kasu) modu promiskuoan ezartzen du, eta horrek ethernet ingurunearen trama guztiak jasotzea eragiten du. Beraz sarea lokal baten komunikazio guztiak bereganatzen ditu eta edukinak aztertzeko aukera ematen du. Sarean hub bat baldinbadago usnaketa erreza da, baina switch edo konmutadorea bada zailagoa izango da (kode hau ez du baliorik kasu horretan). Egun libpcap bezalako liburutegiarekin programa usnatzaileak egitea asko erreztu da, beste egunen batean azter daitezke. Baina Jakin ezinearen asmoa beti izan da gauzak sustraietik nola egiten diren erakustea beraz: Hona hemen usnatzaile oinarrizkoa. ------------------------8<--------------------------------------------------- /** * $Id: usnatzailea.c,v 1.10 2004/12/19 12:48:58 root Exp $ * usnatzaile minimoa * Jakin 6 - by niuBAI */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Programa nagusia */ main(int argc, char **argv) { int jasotakoa; int datuluzera = 0; char *datuak; int i=0; int segi = 0; int socketa; struct ifreq ifr; int stemp; // Ethernet paketea gordetzeko egitura struct etherpacket { struct ethhdr eth; struct iphdr ip; struct tcphdr tcp; char bufferra[8192]; } ethernet_paketea; struct { unsigned long saddr; unsigned long daddr; unsigned short sport; unsigned short dport; int bytes_read; char active; time_t start_time; } gixajoa; struct iphdr *ip; struct tcphdr *tcp; struct in_addr in_helb; printf("usnatzailea v1.0 - Jakin ezine 6 - by niuBAI\n"); // Lehenbizi, SOCK_PACKET motako socketa sortzen dugu if( ( socketa = socket(AF_INET, SOCK_PACKET, htons(0x800)) ) < 0) { perror("cant get SOCK_PACKET socket"); exit(EXIT_FAILURE); } // Ethernet interfaze usnatzailea ezartzen dugu, kasu honetan eth0 strcpy(ifr.ifr_name, "eth0"); // Ethernet interfazearen flag-ak ateratzen ditugu if( ( stemp=ioctl(socketa, SIOCGIFFLAGS, &ifr) ) < 0) { close(socketa); perror("Atx! ezin izan ditut flag-ak lortu"); exit(EXIT_FAILURE); } ifr.ifr_flags |= IFF_PROMISC; // Interfazea PROMISC moduan ezartzen dugu if((stemp=ioctl(socketa, SIOCSIFFLAGS, &ifr)) < 0) { perror("Atx! ezin izan dut promisc moduan jarri interfazea"); exit(EXIT_FAILURE); } printf("OK interfazea promisc jarrita, belarria ernai dago.\n"); // Aldagaiak hasieratzen ditugu // ip goiburuaren hasieraketa ip = (struct iphdr *)(((unsigned long)ðernet_paketea.ip)-2); // tcp goiburuaren hasieraketa tcp = (struct tcphdr *)(((unsigned long)ðernet_paketea.tcp)-2); gixajoa.saddr=0; gixajoa.daddr=0; gixajoa.sport=0; gixajoa.dport=0; gixajoa.active=0; gixajoa.bytes_read=0; gixajoa.start_time=0; // Hemen hasten gara irakurtzen... while(1) {// begizta amaigabea while(1) { jasotakoa = read(socketa, (struct etherpacket *)ðernet_paketea, sizeof(ethernet_paketea)); // Datuak badaude, ea ba if(jasotakoa > 1) { // bakarrik TCP protokoloa, hots: IPPROTO_TCP = 6 (ikus netinet/in.h) if(ip->protocol == 6) { // syn paketea, konexio baten hasiera, pantailatik atera if((!gixajoa.active) && (tcp->syn)) { gixajoa.saddr=ip->saddr; gixajoa.daddr=ip->daddr; gixajoa.active=1; gixajoa.sport=tcp->source; gixajoa.dport=tcp->dest; gixajoa.bytes_read=0; in_helb.s_addr = gixajoa.saddr; printf("[SYN][%s:%d] => ",inet_ntoa(in_helb),ntohs(tcp->source)); in_helb.s_addr = ip->saddr; printf("[%s:%d] [%d] (Konexio berria!!)\n",inet_ntoa(in_helb),ntohs(tcp->dest),jasotakoa); } if(tcp->dest != gixajoa.dport) segi = 0; if(tcp->source != gixajoa.sport) segi = 0; if(ip->saddr != gixajoa.saddr) segi = 0; if(ip->daddr != gixajoa.daddr) segi = 0; // reset paketea, konexioa mozten da, pantailatik atera if(tcp->rst && (!segi)) { gixajoa.saddr=ip->saddr; gixajoa.daddr=ip->daddr; gixajoa.sport=tcp->source; gixajoa.dport=tcp->dest; gixajoa.active=0; in_helb.s_addr = gixajoa.saddr; printf("\n[RST][%s:%d] =X= ",inet_ntoa(in_helb),ntohs(tcp->source)); in_helb.s_addr = ip->saddr; printf("[%s:%d] [%d] (Konexioa berrezarrita)\n",inet_ntoa(in_helb),ntohs(tcp->dest), jasotakoa); segi = 0; } // fin paketea, konexioa bukatu da, pantailatik atera if(tcp->fin && (!segi)) { gixajoa.saddr=ip->saddr; gixajoa.daddr=ip->daddr; gixajoa.sport=tcp->source; gixajoa.dport=tcp->dest; gixajoa.active=0; in_helb.s_addr = gixajoa.saddr; printf("\n[FIN][%s:%d] =X= ",inet_ntoa(in_helb),ntohs(tcp->source)); in_helb.s_addr = ip->saddr; printf("[%s:%d] [%d] (Konexioa amaitua)\n",inet_ntoa(in_helb),ntohs(tcp->dest), jasotakoa); segi = 0; } segi = 1; } if (segi == 0) continue; // luzera 0 edo gutxiagoan uzten dugu jasotakoa -= 54; if(jasotakoa < 1) continue; break; } // if }//while // goazen datuak irakurtzera if(gixajoa.active) { // lehenbizi, jasotakoaren luzera osoa ateratzen dugu, goiburuen luzera kenduta datuluzera = htons(ip->tot_len)-sizeof(ethernet_paketea.ip)-sizeof(ethernet_paketea.tcp); // gero datuen aldagaia esleitzen dugu datuak = ethernet_paketea.bufferra-2; gixajoa.bytes_read += datuluzera; // Datuak pantailatik ateratzen ditugu for(i=0; i != datuluzera; i++) { if(datuak[i] == 13) { printf("\n");} if(isprint(datuak[i])) {printf("%c", datuak[i]);} }//for }//if }// while }// main --------------------------8<------------------------------------------------- Konpilazioa: jakin# gcc -o usnatzailea usnatzailea.c Eta egikaripena, atzeko planoan utziaz: jakin# ./usnatzailea & usnatzailea[1301] jakin# Kodea xehetzen saiatu naiz. Dena den espero dut hurrengo aleetan edo Jakin Sistemaren bitartez eguneraketak sartu ahal izatea, gaitasun eta aukera gehiagorekin noski. -niuBAI- 4. NASM mihiztadura lengoaia __________________________ <4> Kaixo, agur bero jaso ezazue nh taldearen laborategitik. Aitzineko alean mihiztadura lengoaiaren sarrera eman genuen, eta nasm kodearen lehen adibidea ere atera zen: ohizko Kaixo Mundua. Gaurkoan lengoai horren azterketa eginen dugu eragiketak, kontrol egiturak, funtzio deiak, memoria atzipenak, e.a. ezagutzeko. Horrekin sintaxia eta lengoaiaren erabilera ikasi ahal izanen ditugu, sistema deietan burubelarri sartu baino lehen. Oinarrizko datu motak: zenbaki osoak ------------------------------------ -Zenbaki osoak: zeinuarekin ala zeinurik gabe izan daitezke, zeinua eukitzekotan bit batekin adierazten da, adibidez: 00011011 = 27 10011011 = -27 Beste teknikak badira, adibidez bit bakoitzaren aurkakoa erabiliz: 00011011 = 27 11100100 = -27 Eta teknika berriago bat, aitzinakoren berdina baina bit 1 gehituz 00011011 = 27 11100100 + 1 ----------- 11100101 = -27 Eragiketak zenbaki osoekin: -------------------------- Eragiketak erabiltzen diren iturrien arabera ondorio ezberdinak dituzte; ez ba berdina 8 bit (AH) ala 16 biteko (AX) iturriak erabiltzea, eta berdin 32 bitekin (EAX) mul iturria imul helburua, iturri1 imul helburua, iturri1, iturri2 Adibidez: mul BL ; AX = BL * AL mul BX ; EAX = BX * AX Orokorrean imul-ekin konbinazio hauek egin daitezke: helburua iturri1 iturri2 ekintza ------------------------------------------------------- erreg/mem8 AX = AL*iturri1 erreg/mem16 DX:AX = AX*iturri1 erreg/mem32 EDX:EAX = EAX*iturri1 erreg16 erreg/mem16 helb = helb*iturri1 erreg32 erreg/mem32 helb = helb*iturri1 erreg16 immed8 helb = helb*immed8 erreg32 immed8 helb = helb*immed8 erreg16 immed16 helb = helb*immed16 erreg32 immed32 helb = helb*immed32 erreg16 erreg/mem16 immed8 helb = iturri1*iturri2 erreg32 erreg/mem32 immed8 helb = iturri1*iturri2 erreg16 erreg/mem16 immed16 helb = iturri1*iturri2 erreg32 erreg/mem32 immed32 helb = iturri1*iturri2 div iturria Zatiketan, AX iturriarekin zatitzen da, emaitza ALn gorde eta ondarra AHn. Iturria 16 bitekoa bada DX:AX zatizen da emaitza AXen eta ondarra DXen gordez. 32 bitekin, EDX:EAX iturriarekin zatitzen dugu, emaitza EAX eta ondarra EDXen utziz. Ez dago idiv eragilerik. Goazen adibide batekin. Adibideak azalpen guztiak dauzka, eta zenbait eragiketa aritmetikoak egiten dira: --------------------------8<------------------------------------------------------- ; Mihiztadura lengoaiako adibidea eragiketa aritmetikoein. ; NASMrako egina. NHTaldea - Jakin 6 ; kodea tontakeri hutsa besterik ez da, baina GDB oinarriak erabiltzeko ; balio du. Kodean aldagaien izendapen aukerak erakusten dira. ; konpilazioa: ; nasm -f elf eragiketak.asm ; estekaketa: ; gcc -g -o eragiketak eragiketak.o ; arazketa pausuak (gdb sesio adibidea): ; jakin# gdb adibidea ; (gdb) break main (egikaripena main etiketan geldiarazteko) ; (gdb) run (egikaritzeko agindua. main-en geldituko da) ; (gdb) set disassembly-flavor intel (mihiztaketa intel moduan ezarri) ; (gdb) disassemble main (kode bitarra mihiztadura lengoaiara itzuli) ; (gdb) info registers (erregistroen balioak atera) ; (gdb) print/x $esi (si erregistroaren balio hamaseitarra pantailaratu) ; (gdb) print/x $eax (ax erregistroaren balio hamaseitarra pantailaratu) ; (gdb) nexti (hurrengo agindura pasa) ; hasteko glibc-ren printf funtzioa erabiliko dugu extern printf ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .data ; Datu segmentua, hasieratutako datuak ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; datuak: ; b = byte (byte 1 = 8 bit) ; w = hitza (word = 2 byte) ; d = hitz bikoitza (double word = 4 byte) ; q = hitza laukoitza (quad word = 8 byte) ; t = hamar byte (ten) ; ; sintaxi orokorra: ; izena: datu_tamaina datua msg1: db "Emaitza: %d",1,0 ; Mezu bat, printf-ri pasatzeko msg2: db "%s",1,0 ; Beste mezu bat, printf-ri pasatzeko karakterea: db 'N' ; N karakterea karakterea2: db "b" ; b karakterea katea: db "ASM adbd by nh Jakin Ezine 0x110",0 ; Karaktere katea kateluzera: equ $-katea ; Katearen luzera. $=oraingo datu gunearean posizioa. katea2: db "J","A","K","I","N" ; Karaktere katea kateluzera2: equ $-katea2 ; Katearen luzera. $=oraingo datu guneareanposizioa. osokoa: dd 313 ; Zenbaki osoa = 313 osokoa2: dd 14o ; Zenbaki osoa oinarri zortzitarran (12) erreala: dd 9.734e-30 ; 32-biteko zenbaki erreala erreala64: dq -123.456789e300 ; 64-biteko zenbaki erreala ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .bss ; bss segmentua, hasieratu GABE dauden datuak ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; sintaxi orokorra ; izena: res_tam zenbat emaitza: resd 1 ; emaitza aldagaia erreserbatzen da, hitz bikoitzeko tamainakin emaitza2: resd 1 ; emaitza2 aldagaia erreserbatzen da, hitz bikoitzeko tamainakin ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .text ; Kode segmentua ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; global main ; C kodearen main izendapena main: ; programa nagusiaren hasiera ;; Hasteko agurra pantailaratuko dugu push dword katea ; katearen helbidea push dword msg2 ; call printf ; glibc-ren printfri deitu add esp, 8 ; pilaren erakuslea 8 byte mugitu ;; Batuketa xinple baten adibidea mov al, 56 ; AL = 56 movzx eax,al ; EAX <= AL : AL erregistroa EAXn sartzen dugu mov ebx, 75 ; EBX = 75 add eax, ebx ; EAX = EAX + EBX mov [emaitza], eax ; OSOKOA = EAX ;; emaitza pantailaratzen dugu push dword [emaitza] ; printf-ri parametroa pasatzen diogu push dword msg1 ; printf-ri "Emaitza: %d" pasatzen diogu call printf ; glibc-ren printfri deitu add esp, 8 ; pilaren erakuslea 8 byte mugitu ;; Biderketa xinple baten adibidea mov eax, [osokoa] ; EAX = OSOKOA mov ebx, [osokoa2] ; EBX = OSOKOA2 imul eax, ebx ; EAX = EAX * EBX ;; emaitza pantailaratzen dugu, oinarria ezberdina bada ere emaitza ongi aterako da. push dword eax ; printf-ri parametroa pasatzen diogu push dword msg1 ; printf-ri "Emaitza: %d" pasatzen diogu call printf ; glibc-ren printfri deitu add esp, 8 ; pilaren erakuslea 8 byte mugitu ;; Zatiketa xinple baten adibidea. Kasu honetan byte bakarreko zatitzailea ;; Kontuz, orokorrean "idiv balio" egiten da, eta ondorioz AXen balioa bi zatitan ;; banatzen da: AL emaitza, eta AH ondarra. ;; Zatitzailea 2bytekoa baldinbada: emaitza AX eta hondarra DXen ;; Zatitzailea 4bytekoa balndinbada: emaitza EAXen eta hondarra EDXen mov bl, 6 ; BL = 6 mov ax, 66 ; AX = 66 idiv bl ; AL = AX / BL (AH = AX mod 6) mov [emaitza2], al ; EMAITZA = AL ;; emaitza pantailaratzen dugu push dword [emaitza2] ; printf-ri parametroa pasatzen diogu push dword msg1 ; printf-ri "Emaitza: %d" pasatzen diogu call printf ; glibc-ren printfri deitu add esp, 8 ; pilaren erakuslea 8 byte mugitu ;; Kenketa xinple baten adibidea mov eax, 670 ; EAX = 670 mov ebx, 4 ; EBX = 4 sub eax, ebx ; EAX = EAX - EBX ;; emaitza pantailaratzen dugu, oinarria ezberdina bada ere emaitza ongi aterako da. push dword eax ; printf-ri parametroa pasatzen diogu push dword msg1 ; printf-ri "Emaitza: %d" pasatzen diogu call printf ; glibc-ren printfri deitu add esp, 8 ; pilaren erakuslea 8 byte mugitu ;; Irteera ; exit sistema deia erabili ordez ; return 0 bat egiten dugu mov eax, 0 ; kodea esleitzen zaio AXi = 0 ret ; RETURN --------------------------8<------------------------------------------------------- Egikaritzeko pausu hauek jarraitu eta kitto: jakin# nasm -f elf eragiketak.asm jakin# gcc -g -o eragiketak eragiketa.o jakin# ./eragiketak ASM adbd by nh Jakin Ezine 0x110Emaitza: 131Emaitza: 3756Emaitza: 11Emaitza: 666jakin# Erregistroen balio aldaketak pausoz-pauso jarraitzeko gdb erabil daiteke eta kodean dauden pausuak jarraituz programa honen arazketa egin ahal izanen dugu. Komeni da gdb bezalako tresna batera ohitzea. Kontrol egiturak ---------------- Kode erabilgarria sortzeko kontrol egiturak ezinbestekoak dira: if-else egiturak begiztak. Mihiztadura lengoaian jauzi eta etiketen bitartez eraikitzen dira. Kode honetan behar diren azalpen guztiak daude: --------------------------8<-------------------------------------------------------- ; kontrolegiturak.asm ; $Id$ ; Mihiztadura lengoaiako adibide xinplea kontrol egiturak aztertzeko ; NASMrako egina. NHTaldea - Jakin 6 ; konpilazioa: ; nasm -f elf kontrolegiturak.asm ; estekaketa: ; gcc -g -o kontrolegiturak kontrolegiturak.o ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .data ; Datu segmentua, hasieratutako datuak ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; agurra: db 'NASM kodea - Jakin 6 - by nhtaldea ',10 ; agurra testua daraman aldagaia agurraLuz: equ $-agurra ; agurra aldagaiaren luzera daraman aldagai KONSTANTEA (equ) kontagailua: dd 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .bss ; bss segmentua, hasieratu GABE dauden datuak ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; emaitza: resd 1 ; emaitza aldagaia erreserbatzen da, hitz bikoitzeko tamainakin ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .text ; Kode segmentua ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .text global main ; Hasieran jarri behar den etiketa main: ;; Kontrol egiturak sortzeko JAUZIAK eta ETIKETAK erabiltzen dira ; JAUZIAK egiteko baldintzak FLAG balioen araberakoa da. ; CMP aginduarekin bi balio konparatzen dira ; cmp balio1, balio2 ; Honekin (balio1-balio2) eragiketa egiten da eta FLAGetan emaitzak gordetzen dira. ; emaitza = 0 bada orduan ZF = 1 , hots, zero-flag aktibatzen da eta CF = 0 ; emaitza < 0 (balio1 < balio2) bada orduan ZF = 0 eta CF = 1 ; emaitza > 0 (balio1 > balio2) bada orduan ZF = 0 eta CF = 0 ; KONTUZ, balioak zeinuarekin baldinbadatoz FLAG ezberdinaK erabiltzen dira ; emaitza = 0 bada orduan ZF = 1 , hots, zero-flag aktibatzen da eta CF = 0 ; emaitza < 0 (balio1 < balio2) bada orduan ZF = 0 eta SF =/= OF (Sign flag eta Overflow flag) ; emaitza > 0 (balio1 > balio2) bada orduan ZF = 0 eta SF = OF ; FLAG horien esleitu direnean erabakiak har ditzakegu ; JZ : jauzi baldin ZF=1 ; JNZ : jauzi baldin ZF=0 ; JO : jauzi baldin OF=1 ; JNO : jauzi baldin OF=0 ; JS : jauzi baldin SF=1 ; JNS : jauzi baldin SF=0 ; JC : jauzi baldin CF=1 (carry flag) ; JNC : jauzi baldin CF=0 ; JP : jauzi baldin PF=1 ; JNP : jauzi baldin PF=0 ; (ez dago zertan CMP agindurik derrigor erabili beharrik, azken finean FLAGak begiratuko dira) ; jauzien sintaxi orokorra ; [SHORT|NEAR|FAR] jauzi-agindua helbide-etiketa ; jauzi motak: - SHORT: gehienez ere 128 byteko jauzia memorian ; - NEAR: besterik ezekoa. Uneko kode segmentuko edoizen lekura heltzeko ; - FAR: beste kode segmenturara heltzeko ; if-then-else baten adibidea mov eax, 59 ; EAX = 59 mov ebx, 0 ; EBX = 0 mov ecx, eax ; ECX = 57 cmp eax, ecx ; EAX = EAX - ECX (kasu honetan ZF = 1) jnz else mov ebx, eax jmp segi else: mov ebx, 666 segi: mov [kontagailua], bx ; Konparaketa konplexuagoak sortzeko bestelako jauzi aginduak ere badauzkagu. ; (E equal, N non, L less, G greater konbinatzen dira) ; Hauexek balioak zeinudunak badira (SIGNED) ; JE balio1, balio2 balio1 = balio2 ; JNE balio1, balio2 balio1 =/= balio2 ; JL balio1, balio2 balio1 < balio2 (= JNGE) ; JLE balio1, balio2 balio1 =< balio2 (= JNG) ; JG balio1, balio2 balio1 > balio2 (= JNLE) ; JGE balio1, balio2 balio1 => balio2 (= JNL) ; UNSIGNED baldinbadira, bere baliokideak: ; JE balio1 = balio2 ; JNE balio1 =/= balio2 ; JB, JNAE balio1 < balio2 ; JBE, JNA balio1 =< balio2 ; JA, JNBE balio1 > balio2 ; JAE, JNB balio1 => balio2 ; beste adibide xinple bat (E) cmp ebx, 0x29A ; EBX-666 jle txberd ; EBX <= 666 mov ebx, 0 ; EBX = 0 jmp segi2 ; jauzi segi2 etiketara txberd: add ebx, eax ; EBX = EBX + EAX add ebx, ecx ; EBX = EBX + ECX segi2: mov [kontagailua], bx ; KONTAGAILUA = EBX ; WHILE begizta baten inplementazioa mov ecx, 0 ; ECX = 0 hasieraketa mov edx, 10 ; EDX = 10 hasieraketa while: cmp edx, ecx ; EDX = EDX - ECX jng atera ; EDX < ECX bada, atera inc ecx ; ECX++ jmp while atera: ;; FOR moduko begiztak egiteko LOOP aginduak dauzkagu ; LOOP bi gauza egiten ditu: ECX-- eta (ECX =/= 0) bada jarraitzen du ; LOOPE, LOOPZ: ECX-- eta baldin (ECX =/= 0) ta (ZF = 1) bada jarraitu ; LOOPNE, LOOPNZ: ECX-- eta baldin (ECX =/= 0) ta (ZF = 0) bada jarraitu mov ebx, 0 ; EBX = 0 mov ecx, 25 ; ECX = 25 begizta: add ebx, 4 ; EBX = EBX + 4 add ebx, ecx ; EBX = EBX + ECX loop begizta ; ECX--; baldin (ECX =/= 0) jauzi ;; Kasu honetan printf erabili ordez, sistema deia erabiliko dugu mov eax,4 ; sys_write sistema deia (kodea: 4) prestatzen da. ax erregistroan 4 balioagordetzen da. mov ebx,1 ; Fitxategi deskribatzailea 1 erabiltzen da (stdout). bx erregistroan 1 balioa gordetzen da. mov ecx,agurra ; Kaixo aldagaia. cx erregistroan agurra aldagaia gordetzen da. mov edx,agurraLuz ; agurraLuz konstante bat da ez dugu mov edx,[kaixoLuz] egin behar int 80h ; kernelari deitzen, eten sinkronoa ;; Irteera ; programa bukatzeko deia pasako dugu irteera kodea 0 pasatuz (c bezala) mov eax,1 ; exit sistema deia (kodea: 1) prestatzen da. ax erregistroan 1 balioa gordetzenda. mov ebx,0 ; 0 kodearen irtetzen gara. bx erregistroan 0 balioa gordetzen da. int 80h ; kernel deia, eten sinkronoa --------------------------8<-------------------------------------------------------- Funtzioak eta kanpo fitxategiak ------------------------------- Mihiztadura lengoaian guztiz erabilgarria eginen da kodea zatitan banatzea, eta horretarako ezinbesteko tresnak funtzioak eta liburutegiak dira. Adibide xinple honetan kanpo fitxategi baten inplementaturik dauden funtzioen erabilera ikusiko dugu. Pila edo metaren nondik-norakoak ere ikusiko dira. Programa nagusia ------------------------8<---------------------------------------------------------- ; funtzioprobak.asm ; $Id$ ; Mihiztadura lengoaiako adibide xinplea funtzioak eta liburutegien erabilpena ; erakusteko. ; NASMrako egina. NHTaldea - Jakin 6 ; ; konpilazioa: ; nasm -f elf funtzioprobak.asm ; estekaketa: ; gcc -g -o funtzioprobak funtzioprobak.o funtzioak.o ; arazketa: pena merezi du batuketan balio pasatzea egiaztatzea... ; gdb funtzioprobak ; ; (gdb) break batuketa ; (gdb) info stack ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;INCLUDE: kanpo fitxategiak gehitzeko ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %include "funtzioak.asm" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .data ; Datu segmentua, hasieratutako datuak ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ":" bi puntuak jarri gabe ere ongi dago. parametro1 dd 345 ; aldagai bat parametro2 dd 612 ; beste aldagai bat ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .bss ; bss segmentua, hasieratu GABE dauden datuak ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; emaitza: resd 1 ; emaitza aldagaia erreserbatzen da, hitz bikoitzeko tamainakin ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .text ; Kode segmentua ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .text global main ; Hasieran jarri behar den etiketa main: ; Funtzio deietarako CALL agindua erabiltzen da, eta itzultzeko ; RET agindua erabiltzen da. Funtzio deietan mihiztadura lengoaiako ; beste erregistro garrantzitsuek hartzen dute parte: SI (Instruction Pointer) ; funtzioaren helbidea hartuko du, eta itzultzeko helbidea PILAn gordeko da ; PILA = META = STACK ingeleraz. ; modu berean funtzioari pasatzen zaizkion parametroak (balioz ala erreferentziaz) ; pilaren bitartez ere pasatzen dira. Kasu honetan ESP (Stack Pointer) eta EBP (Base Pointer) ; sartzen dira jokoan ;; pantailaratu funtzioa erabiltzen dugu call pantailaratu ; Dei hori oso xinplea da. Baina ze itsura hartzen du metak parametroak pasatzen ditugunean? ; Honako hau: ; Pilako elementu bakoitza hitz bikoitzeko tamaina dauka. ;|-------------------| ;| Parametro1 | ; push bitartez pilaratutako balioa. ESP + 8 ;|-------------------| ;| Parametro2 | ; push bitartez pilaratutako balioa. ESP + 4 ;|-------------------| ;| Itzuli helb. | ; call egiten denean automatikoki pilaratzen da. ESP erregistroan gordeko da ;|___________________| ; Hauetaz gain azpi-programa edo funtzioak pila erabil dezake bere balioak gordetzeko. ; Pilaren erakuslea gal ez dadin EBP erregistroa gordeko dugu beti funtzio hasieran, eta bukaeran ; bere balioa berreskuratuko dugu. Ikusi funtzioak.asm kodean azaltzen den irudia eta azalpena. ;; batuketa funtzioa erabiltzen dugu. Parametroak pasa behar dizkiogu mov eax, [parametro1] ; EAX = PARAMETRO1 push eax ; PILARATU EAX mov eax, [parametro2] ; EAX = PARAMETRO2 push eax ; PILARATU EAX call batuketa ; BATUKETA funtzio deia pop eax ; parametroa kendu pilatik, hortxe emaitza dago nahi izanez gero pop eax ; parametroa kendu pilatik ; BESTE modu xinpleago bat balioak pilatik kentzeko... ;add esp, 8 ; pilaren erakuslea mugitu! ;; Irteera ; exit sistema deia erabili ordez ; return 0 bat egiten dugu mov eax, 0 ; kodea esleitzen zaio AXi = 0 ret ; RETURN ----------------------8<------------------------------------------------------------ Funtzioen fitxategia ------------------------8<---------------------------------------------------------- ; funtzioak.asm ; $Id$ ; Mihiztadura lengoaiako adibide xinplea funtzioak eta liburutegien erabilpena ; erakusteko ; NASMrako egina. NHTaldea - Jakin 6 ; ; konpilazioa: ; nasm -f elf funtzioak.asm ; estekaketa: liburutegi hau ez du balio zuzenean erabiltzeko. ; funtzio hauek beste kode batean erabili ahal izateko, objektu fitxategia ; adierazi beharko da estekaketan ; gcc -g -o bestebat bestebat.o funtzioak.o ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .data ; Datu segmentua, hasieratutako datuak ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; agurra1: db 'NASM kodea - Jakin 6 - by nhtaldea ',10 ; agurra testua daraman aldagaia agurraLuz1: equ $-agurra1 ; agurra aldagaiaren luzera daraman aldagai KONSTANTEA (equ) agurra2: db 'Batuketa funtzioa - Jakin 6',10 ; batuketa funtzioaren testua daraman aldagaia agurraLuz2: equ $-agurra2 ; agurra2 aldagaiaren luzera daraman aldagai KONSTANTEA (equ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .bss ; bss segmentua, hasieratu GABE dauden datuak ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; emaitza1: resd 1 ; emaitza aldagaia erreserbatzen da, hitz bikoitzeko tamainakin ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION .text ; Kode segmentua ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .text ;;;;;;;;;;;;;;;;;;;;; Funtzioa: pantailaratu ;;;;;;;;;;;;;;;;;;;;; pantailaratu: ;; Kasu honetan printf erabili ordez, sistema deia erabiliko dugu mov eax,4 ; sys_write sistema deia (kodea: 4) prestatzen da. ax erregistroan 4 balioagordetzen da. mov ebx,1 ; Fitxategi deskribatzailea 1 erabiltzen da (stdout). bx erregistroan 1 balioa gordetzen da. mov ecx,agurra1 ; Kaixo aldagaia. cx erregistroan agurra aldagaia gordetzen da. mov edx,agurraLuz1 ; agurraLuz konstante bat da ez dugu mov edx,[kaixoLuz] egin behar int 80h ; kernelari deitzen, eten sinkronoa ;; Irteera. ; funtzioetatik ret aginduekin aterako gara ret ;;;;;;;;;;;;;;;;;;;;; Funtzioa: batuketa ;;;;;;;;;;;;;;;;;;;;; batuketa: ; funtzioprobak.asm-n esaten den bezala, funtzioak pila erabil dezake bere balioak ; gordetzeko, horregatik komeni da EBP balioa gordetzea ;|-------------------| ;| Parametro1 | ; push bitartez pilaratutako balioa. ESP + 12 ;|-------------------| ;| Parametro2 | ; push bitartez pilaratutako balioa. ESP + 8 ;|-------------------| ;| Itzuli helb. | ; call egiten denean automatikoki pilaratzen da. ESP erregistroan gordeko da ;|-------------------| ;| funtzio ald. | ; funtzioaren aldagaiak ;|___________________| ; Hartaz, funtzio hasieran EBP balioa gordeko dugu!!! push ebp ; ebp-ren balioa pilan gorde mov ebp, esp ; oraingo balioa eman ;|-------------------| ;| Parametro1 | ; push bitartez pilaratutako balioa. ESP + 12 (EBP+12) ;|-------------------| ;| Parametro2 | ; push bitartez pilaratutako balioa. ESP + 8 (EBP+8) ;|-------------------| ;| Itzuli helb. | ; call egiten denean automatikoki pilaratzen da. ESP erregistroan gordeko da (EBP+4) ;|-------------------| ;| EBP | ; EBP, oinarri erakuslea, hala Base Pointer (EBP) ;|___________________| ; Orain EBP balio horri eskerrak edozein momentutan pasatutako parametroak atzitu ahal izanen ditugu ; pilan balio gehiago sartzen badira ere.. ;; Pantailatik mezutxo bat atera... mov eax,4 ; sys_write sistema deia (kodea: 4) prestatzen da. ax erregistroan 4 balioagordetzen da. mov ebx,1 ; Fitxategi deskribatzailea 1 erabiltzen da (stdout). bx erregistroan 1 balioa gordetzen da. mov ecx,agurra2 ; Kaixo aldagaia. cx erregistroan agurra aldagaia gordetzen da. mov edx,agurraLuz2 ; agurraLuz konstante bat da ez dugu mov edx,[kaixoLuz] egin behar int 80h ; kernelari deitzen, eten sinkronoa mov eax, [ebp+12] ; EAX = parametro1 esleitzen diogu mov ebx, [ebp+8] ; EBX = parametro2 esleitzen diogu add eax, ebx ; EAX = EAX + EBX ;mov [ebp+8], eax ; emaitza parametro2-ren posizioan gordetzen dugu... ;; Adi, atera baino lehen EBP balioa berreskuratu pop ebp ; pilaren lehen elementua atera eta ebp-n gorde ;; Irteera. ; funtzioetatik ret aginduekin aterako gara ret ----------------------8<------------------------------------------------------------ Ederki!! mihiztaduran lengoaiaren oinarriak ezagutuz goaz. Gauza aunitz geratzen da oraindik NASM goitik behera menperatzeko. Horretaz gain sistema deiak erebiltzen ikasi behar da lengoaiari etekina atera ahal izateko. Hurrengo alean lengoai honetan sakontzen jarraituko dugu. Ordura artio, txintxo ibili!! -NapharHack- 5. CLIPS inferentzi motorea __________________________ <5> Agur eta ohore, Euskalerria. XD Jakin ezinearen laugarren alean sistema adituei buruzko sarrera bat eman genuen. Gaurkoan orduantxe aipaturiko garapen tresna bati buruz jardungo gara: CLIPS. CLIPS inferentzi motore bat da, lengoai propioa erabiltzen duena. Programazio lengoaia LISPen antzekoa dela esan daiteke, baina sistema adituak garatzeko bideatuta dago. Windows eta linuxerako bertsioa badago, beraz ez daukazue aitzakirik probak egiteko. Zer topatuko dugu CLIPS ingurunea martxan jartzerakoan? shell bat. Bertan kodea sar daiteke zuzenean ala fitxategi batetik kargatu. Agian erosoena litzateke kode hori aparte idaztea eta gero ingurunean kargatzea... zeuek ikusi. jakin# clips CLIPS (V6.21 06/15/03) CLIPS> Zer nolako itsura dauka CLIPS sistema batek? Laburbilduta, hauxe => [egitateak + erregelak] Hau da, hasieran egitateak, gertaerak, gauzak, objetuak izendatzen dira, eta horiek erregela sistemarekin konparatzen dira; ondorioz egitateak sortzea, egitateak desagertzea, ekintzak egikaritzea e.a. eragingo da etengabe erregela gehiago aplikatu ezin diren arte. Zaila? Lasai adibide xinple-xinpleekin hasiko gara. ;-------------------------------[lehena.clp CLIPS kodea]-------------------------------; ;; lehena.clp - Jakin 6 - assert ;; Agurra pantailaretzen duen sistema aditua ;; deftemplate: honen bitartez entitate bat definitzen da, mota ezberdineko atributuak ;; dituen gauza bat da. (deftemplate Agurra "deskribapena: agurraren testua" (slot Testua (default "Hello Bot")(type STRING)) ; string motako atributua (slot Hizkuntza (default English)(allowed-values English Catala Euskara)) ; Enumerazioa ) ;; deffacts: lehen entitatearen definizioa eman dugu, orain EGITATEAK sortzen ditugu, ;; nolabait Agurrra entitatearen adibideak dira. ;; Kasu honetan hasierako egitate batzuk sortzen dira, baina sistemaren egikaripenaren zehar ;; egitate gehiago sor daitezke (deffacts AgurMultzoa "hauek egitateak dira" (Agurra (Testua "Hello Bot")(Hizkuntza English)) (Agurra (Testua "Bon dia tutom")(Hizkuntza Catala)) (Agurra (Testua "Kaixo mundua")(Hizkuntza Euskara)) ) ;; defrule: hona hemen erregelak! erregela hauek betetzen duten egitaterik baldinbadago ;; bere ekintzak egikarituko dira. ; Erregela xinplea: agurrak baldinbadaude => pantailatik atera (defrule Agurtu "agurrik baldinbadago pantailaratu" ; bete behar diren baldintzak sartzen dira orain ; balioak aldagaietan (?) esleituko dira (Agurra (Testua ?testu1)(Hizkuntza ?hizkuntza1)) ; ondorioz... => (printout t "Hona hemen agurra " ?testu1 " hizkuntza honetan:" ?hizkuntza1 crlf) ) ; Erregela: agur euskaldunik baldinbadago => pantailatik atera (defrule AgurEuskalduna "agurrik baldinbadago pantailaratu" ; bete behar diren baldintzak sartzen dira orain ; balioak aldagaietan (?) esleituko dira (Agurra (Testua ?testu1)(Hizkuntza Euskara)) ; ondorioz... => (printout t "Hona hemen agur euskalduna: " ?testu1 crlf) ) ;---------------------------------[lehena.clp amaiera]---------------------------------; OK nola proba dezakegu kode hau? Demagun kodea lehena.clp izeneko fitxategian daukagula. Horrela kargatukoeta egikarituko genuke: CLIPS> (load "lehena.clp") Defining deftemplate: Agurra Defining deffacts: AgurMultzoa Defining defrule: Agurtu +j Defining defrule: AgurEuskalduna +j TRUE CLIPS> (reset) CLIPS> (run) Hona hemen agurra Kaixo mundua hizkuntza honetan:Euskara Hona hemen agur euskalduna: Kaixo mundua Hona hemen agurra Bon dia tutom hizkuntza honetan:Catala Hona hemen agurra Hello Bot hizkuntza honetan:English CLIPS> (exit) Erreza dirudi ezta? DEFTEMPLATE batekin egitateak defini ditzakegu eta mota ezberdineko atributuak dauzkagu, adibide honekin ikusiko duguna: ;-------------------------------[Pertsona.clp CLIPS kodea]-------------------------------; ;; Pertsona baten definizioa (deftemplate Pertsona "pertsona baten definizioa" (slot Adina (type INTEGER) (default 5)) ; Adina, defektuzko balio batekin (slot Izena (type STRING) (default ?NONE)) ; izena, derrigorrez balio bat eduki behar du (slot Pisua (type FLOAT) (default 76.4)) ; zenbakia hamartarrekin (slot Lanbidea (type SYMBOL) (default Harakina)) ; sinboloa (slot Soldata (type FLOAT) (default ?DERIVE)) ; balio hau, murriztapenen arabera esleituko zaio ; multislotek, balio bat baino gehiago onartuko du. (multislot Janaria (allowed-values Denetarik Haragizalea Belarzalea Arrainzalea)(default Denetarik)) ) ;; Orain zenbait egitate... (deffacts PertsonaTaldea "pertsona egitateak" (Pertsona (Adina 18)(Izena "Txipi")(Pisua 73.2)(Lanbidea HitzaldiakDoan)(Janaria Belarzalea Arrainzalea)) (Pertsona (Adina 24)(Izena "Patxangas")(Pisua 79.0)(Lanbidea Idazlea)(Janaria Denetarik)) (Pertsona (Adina 23)(Izena "Osoitz")(Pisua 72.9)(Lanbidea Librezalea)(Janaria Haragizalea Arrainzalea)) (Pertsona (Adina 27)(Izena "Bixen")(Pisua 75.8)(Lanbidea BSDeabrua)(Janaria Haragizalea)) ) ;;;;; FUNTZIOAK ;;;;;; ;; funtzio honekin soldata kalkulatzen da (deffunction Soldata "soldata kalkulatzeko funtzioa" (?Izena ?Lanbidea) (printout t ?Izena " pertsonaren soldata kalkulatzen..." ) (printout t ?Lanbidea " lanbidea badu... " ) (return (random 500 1445)) ) ;;;;; ERREGELAK ;;;;;; ;; Erregela xinple bat, pertsona bakoitzeko aktibatuko dena (defrule PertsonaBadago "Pertsona egitateak baldinbadaude egikarituko da" (Pertsona (Izena ?izena1)(Lanbidea ?lanbide1)) => (printout t "Pertsona: " ?izena1 ", eta bere lanbidea: " ?lanbide1 crlf) (printout t "Soldata: " (Soldata ?izena1 ?lanbide1) " euro." crlf) ; hona hemen funtzion deia ) ;---------------------------------[Pertsona.clp amaiera]---------------------------------; Ok, proba dezagun kodea: jakin# clips CLIPS (V6.21 06/15/03) CLIPS> (load "Pertsonak.clp") Defining deftemplate: Pertsona Defining deffacts: PertsonaTaldea Defining deffunction: Soldata Defining defrule: PertsonaBadago +j TRUE CLIPS> (reset) CLIPS> (run) Pertsona: Bixen, eta bere lanbidea: BSDeabrua Soldata: Bixen pertsonaren soldata kalkulatzen...BSDeabrua lanbidea badu... 1293 euro. Pertsona: Osoitz, eta bere lanbidea: Librezalea Soldata: Osoitz pertsonaren soldata kalkulatzen...Librezalea lanbidea badu... 1351 euro. Pertsona: Patxangas, eta bere lanbidea: Idazlea Soldata: Patxangas pertsonaren soldata kalkulatzen...Idazlea lanbidea badu... 698 euro. Pertsona: Txipi, eta bere lanbidea: HitzaldiakDoan Soldata: Txipi pertsonaren soldata kalkulatzen...HitzaldiakDoan lanbidea badu... 1320 euro. CLIPS> (exit) jakin# CLIPS + C --------- Ziur asko CLIPS kodearen adibide hauekin nazkatuta zaudete, beste lengoai didaktiko baina erabilgarritasunik gabeko baten aurrean zautela pentsatuko duzue. Ez horixe!! Ongi da, egitateak eta erregelez osaturiko sistema sor dezakegu. Baina nola elikatu dezakegu CLIPS kodea kanpotik? Fitxategien bitartez, eta baita C FUNTZIOEI DEI EGINEZ!! bai jauna, CLIPSetik C funtzioak erabil daitezke, horrek suposatzen duen abantail guztiekin: gure kodeak ez du limiterik edukiko orain. Are gehiago: CLIPSekin kode egikarigarria sor daiteke, ingurune berezien dependentzia kenduz! Eta are gehiago: c lengoaian CLIPS inferentzi motorea kudeatzeko behar diren funtzio guztiak dauzkagu. * CLIPS kodea c programa nagusi batekin egikaritzen. Hona hemen adibidea, non pertsona.clp kargatzen den: -------------8<--------------------------------------------------------------- /* * $Id$ * pertsonak.c * pertsonak.clp clips inguruean kargatu eta egikaritzen du. * by assert - Jakin ezine 6 */ #include #include "setup.h" #include "sysdep.h" #include "envrnmnt.h" #include "extnfunc.h" #include "commline.h" int main(int,char *[]); void UserFunctions(void); void EnvUserFunctions(void *); // Funtzio nagusia int main(int argc, char *argv[]) { void *ingurunea; // CLIPS ingurunea kargatzen dugu ingurunea = CreateEnvironment(); // argumentuak pasatzen ditugu RerouteStdin(ingurunea,argc,argv); // agurra... printf("CLIPS ingurune eraldatua - by assert - Jakin ezine 6\n"); // Jarraian, inguruean egiten ditugun ohizko pausuak: // load, reset eta run EnvLoad(ingurunea, "Pertsonak.clp"); EnvReset(ingurunea); EnvRun(ingurunea, -1L); return(-1); } // Erabiltzaileak bere funtzio propioak definitzeko void UserFunctions() { } void EnvUserFunctions(void *ingurunea) { } -----------8<----------------------------------------------------------------- Fitxategi hau makefilean sartu behar da nolabait. Adibidez, main.c agertzen den lekutan pertsonak.c jar daiteke, ala sarrera berri bat sor daiteke gero "make pertsonak" egiteko. Programa honekin clips zuzenean egikarituko dugu: jakin# ./pertsonak CLIPS ingurune eraldatua - by assert - Jakin ezine 6 Pertsona: Bixen, eta bere lanbidea: BSDeabrua Soldata: Bixen pertsonaren soldata kalkulatzen...BSDeabrua lanbidea badu... 1293 euro. Pertsona: Osoitz, eta bere lanbidea: Librezalea Soldata: Osoitz pertsonaren soldata kalkulatzen...Librezalea lanbidea badu... 1351 euro. Pertsona: Patxangas, eta bere lanbidea: Idazlea Soldata: Patxangas pertsonaren soldata kalkulatzen...Idazlea lanbidea badu... 698 euro. Pertsona: Txipi, eta bere lanbidea: HitzaldiakDoan Soldata: Txipi pertsonaren soldata kalkulatzen...HitzaldiakDoan lanbidea badu... 1320 euro. jakin# * C funtzio propioak definitzen. CLIPS inguruneari gure funtzio propioak gehitzea posible da. Beti bezala adibide xinple bat jartzen da baina pentsa ezazue c kodea nahi bezain konplexua izan daitekela, eta funtzionalidade ikaragarriak bilatu daitezke: DB atzipena, tcp/ip sareak, e.a... azken finean Ckin egin daitekeen edozer. Adibidea: batuketa funtzioa. Funtzion hau martxan jartzeko bi gauza egin behar dira: 1- funtzio honen kodea idatzi CLIPSen funtzio lagungarriak erabiliz (parametro jasotzea) 2- CLIPSen funtzio nagusian (main.c), gure funtzioen izendapena egin behar da, inguruneak gure funtzioen berri eduki dezan. -----------8<----------------------------------------------------------------- /* * $Id$ * * batuketa funtzioa clips ingurunerako. * by assert jakin ezine 6 */ #include #include "clips.h" // erabiltzaileak definituriko batuketa funtziona long batuketa() { DATA_OBJECT temp; long balio1, balio2; // Honekin adierazten da espero diren argumentu kopurua if (ArgCountCheck("batuketa", EXACTLY, 2) == -1) { return(1L); } // Lehen parametroa jasotzen dugu if (ArgTypeCheck("batuketa", 1, INTEGER, &temp) == 0) { return(1L); } // datu mota balioztatu, integer ez bada atera if (GetType(temp) == INTEGER) { balio1 = DOToLong(temp); } else { return(1L); } // Bigarren argumentua if (ArgTypeCheck("batuketa", 2, INTEGER, &temp) == 0) { return(1L); } // datu mota balioztatu, integer ez bada atera if (GetType(temp) == INTEGER) { balio2 = DOToLong(temp); } else { return(1L); } // agur bat pantailatik... printf("\nbatuketa by assert - jakin ezine 6\n"); // eta batuketa egiten da. return (balio1 + balio2); } -------------8<--------------------------------------------------------------- Esan bezala, CLIPS iturrien main.c fitxategian, gure funtzioaren berri eman behar dugu, UserFunctions funtzioan hain zuzen ere: -------------8<--------------------------------------------------------------- void UserFunctions() { extern void batuketa(); DefineFunction2("batuketa",'l',PTIF batuketa, batuketa, "22n"); } -------------8<--------------------------------------------------------------- Ondoren ingurune guztia konpilatu beharko da, horretarako CLIPS webgunean makefile bat badago. Makefileari gure funtzioa gehitzen zaio eta kitto! Hona hemen kodearen erabilpena: jakin# ./clips CLIPS (V6.22 06/15/04) CLIPS> (batuketa 4) [ARGACCES4] Function batuketa expected exactly 2 argument(s) CLIPS> (batuketa e r) [ARGACCES5] Function batuketa expected argument #1 to be of type integer or float CLIPS> (batuketa 512 154) batuketa by assert - jakin ezine 6 666 CLIPS> Ikusten denez, CLIPS ingurunearen funtzio laguntzaileekin parametro kopuru eta mota kontrola egin daiteke. php tik ere CLIPS ingurunuea atzitu daiteke, proiektu honi eskerrak http://phlips.sourceforge.net/ baina hori agian beste egun batean. CLIPS> (exit) -Assert- 6. Kultura __________________________ <6> Titulua: Wyrm Egilea: Mark Fabi Liburu ezezagun xamarra hauxe, baina friki hutsa zalantza izpirik gabe. Milurtekoaren bukaera hurbiltzen den heinean munduaren paranoiak areagotzen dira apokalipsiaren beldurrez. Egoera horretan adimentsu dirudien birus informatiko bat sarean mugitzen hasten da korporazio handien sistemak infektatuz. Protagonista birusetan aditu den freelance bat da, Michael Archangelo (Mikel gurea txo!) izen aproposa duena. Ordenagailuzko Xake dema batean wyrm birusaren lehen aztarna topatuko du eta hortik aurrera honen atzetik aterako da birusa geroz eta adimentsuago egiten den bitartean. Birusa geroz eta interesgarriagoa egiten da MUD bat sortuz. Michael, beste MUD zale batzuekin batera jokuan sartuko da birusa ikertzen saiatzeko. MUD (Multi User DUngeon) internet bidez jokatzen diren rol jokuak dira, erabiltzaile- anitzak eta orokorrean fantasiazko munduetan oinarritzen direnak; Wyrm birusak mundu propio sortuko du. wyrm-en arduraduna nor da? Roger Dworkin izeneko hacker bat dela susmatuko dute, desagertuta dagoena. Wyrm ez da literatura ona (inondik ere) baina gutxienez entretenigarria egiten da. Adimen artifizialaz hitzegiten denean oso interesgarri jartzen da eta zati handi batean MUD jokuaren gora-beheretan murgilduta ibiliko gara. Teknikoki ez da guztiz txarra, baina asko hobetu daiteke; egilea gai askoren gainetik pasatzen da. Alde batetik liburuak huts egiten du: protagonistak kriston neska dauka, birus-etan aditua bera ere, eta txortan pasatzen dituzte hasierako kapituluak. Fantasia ikaragarria! ;-) Agian atzeratuta geratu da: MUDak (oraindik badaude), BBSak (badaude), modemak (badaude) agertzen baitira nonnahi. Zu zeu. -km- 7. Albisteak,Estekak,Agurrak __________________________ <7> [jakin] jakin-ezine@lists.sourceforge.net Posta zerrenda estrenatu dugu!!! Hona hemen ezineak estrenatu berri duen komunikazio tresna, berriz ere Sourceforge-ri eskerrak. Zerrendan partu hartu nahi izanez gero, hauxe helbidea: https://lists.sourceforge.net/lists/listinfo/jakin-ezine Albiste izan dira ----------------- Hauek, laburbilduz, aipagarri izan diren gertakizunak. *HACKMEETING: aurtengoa Sevillan ospatu zen, berriz ere arrakastarekin (horren lekuko izan ginen). *HACKRESI: Iruņeako Hacklab-ak gaztetxearen hustuketa bideoz beteriko live-CDa kaleratu du kriston arrakastarekin. Izan ere beste 500 ateratzko erabakia hartu dute. *HACKRESI: berriz ere albiste. webgunea hobetu dute, beraiek programaturiko berri-emailea eta eztabaidagunea, eta aurreko wikia mantenduz. Bota begirada: http://www.hackresi.net *LIBREZALE: "marrapuntu" sortzeko ideia eztabaidatzen hasi da. *ANTENAK eta HACKLABen bilkura: Bilbon ospaturiko jardunalditan euskalerriko hacklaben lehen asanblada egin zen. Zenbait gai eztabaidatu ziren eta lehen ondorioa ASKE izeneko korreo zerrenda izan zen. *UNDERCON: Barrapunton argitaratu da deialdia aurten, norbait egon bada kronikatxo bat egin al digu... arren. *HL-DONOSTI: berreskuratzen hasi dela dirudi. Ikus wikia: http://www.hacklabs.org/wiki.pl?Donostia *METABOLIK: urteari tailer berriekin eman diote hasiera http://www.sindominio.net/metabolik Gehiago izanez gero, kontaiguzue. Bueno ba, azkenaldi honetan proiektua geldirik egon da baina urte honen hasieran bultzada berria emateko asmo trinkoa daukagu. Urteberria beti intentzio ikaragarriekin hasi behar dira! Agian zuetariko askok pentsatzen zenuten Jakin ezinea etorkizunik gabeko proiektua izango zela, baina konturatu orduko seigarren alean gaude. Beste horrenbeste gerta daiteke Jakin sistemarekin. Sistema badaukagu, oinarrizkoa bada ere, orain instalazio programa garatu nahi dugu. Hala eginda dagoen bat moldatzea gomendatzen duzue? Zuen proposamenak proiektuaren orrira bidal ditzakezue (jakin.sf.net). Ez ahaztu hauexek direla ezinearen helbideak: http://www.jakin.tk/ http://jakin.sourceforge.net/ http://jakinezine.galeon.com/ Eta email helbideak: jakinezine@euskalerria.org jakinezine@gmail.com jakin@kaixo.com CALL FOR PAPERS!!! Zeren zain zaude? gai asko dauzkagu hitzegiteko: ASM, aribako sareak, spectrum :), algoritmo genetikoak, matematikak, gai sozialak, hacktibismoa, hacker taldeak, istorioak, albisteak, proiektuak... Anima zaitezte! Ez du garrantzirik gaiak errepikatzen badira, jasotzen duguna ongi-etorria izango da beti. Jakin ezinea ez da irakurleek bere kodeaz egiten duten erabileraren arduradun. Fanxinaren helburu bakarra informatika teknikak erakustea da, dokumentaziotan, interneten, edonon dagoen informazioa modu ulerkor batean laburtzea azken finean. Ohar tipiko hau sartzea beharrezkoa EZ dela deritzogu, baina badazpada hemen da. __ __ _ _ __ / /__ _/ /__ (_)__ ___ ___ (_)__ ___ / // / _ `/ '_// / _ \ / -_)_ // / _ \/ -_) \___/\_,_/_/\_\/_/_//_/ \__//__/_/_//_/\__/ Hasiberriak betiko -edit-