Ohjelmointi

OH3NE

Loikkaa: valikkoon, hakuun

Sisällysluettelo

Ohjelmointi

Ohjelmointiin liittyviä kysymyksiä ja toivottavasti myös vastauksia. 

Katso myös keskusteluosuutta [1] PC ohjelmointia ohjelmointi Sulautetut järjestelmät[2]

Pieni ja yksinkertainen PC-tehtävä

== tehtävä #1 ==


-Tee pieni viiveohjelma jolle voi antaa parametrejä sekunteina.

Esim. Delay 10

Tätä voi käyttää lähettämään määrävälein kamerankuvaa ftp:llä internettiin .bat-komentojonossa.

Ympäristö esim W98/2k/XP

Lisäosa 1

jos parametrina on +S ohjelma voisi antaa äänimerkin kun tehtävä on tehty

ja -S jos ei haluta kuunnella ääniä

OH3GDO

Esimerkkivastaus

/**======================================================================== Projekti : esimerkkejä C-kielen harjoittelua varten OH3NE sivuille

Date: 2.2.2007

file: Viive.c

Name: OH2GDO Pekka Ritamäki

Compiler: Borlandc 5.02 , myös muut käyvät

Output viive.exe

Usage : viive 20 antaa 20 sekunin viiveen


Function: tee viiveohjelma xxxxx s ftp lähetystä varten

Ohjelmalle voi antaa parametriksi ajan sekunteina 0- 4000000000s

ja -S ( ei merkkiäääntä) tai +S ( merkkiäänet)

jos parametria ei anneta, ohjelma näyttää ohjeen 10 sekuntia ja demoaa toimintaa

Huomaa käytä Sleep(x) funktiota, älä sleep(x)

Merkiäänet : käytä windos perusääniä

MessageBeep(MB_ICONASTERISK);


MessageBeep(uType parametri):

Parameteri tyypit uType

registrysssä on [sounds] kohta

arvo Sound on :

0xFFFFFFFF vakioäni PC kaiuttimella

MB_ICONASTERISK SystemAsterisk

MB_ICONEXCLAMATION SystemExclamation

MB_ICONHAND SystemHand

MB_ICONQUESTION SystemQuestion

MB_OK SystemDefault

  • /
  1. include <windows.h> // Win32 console application
  1. include <stdio.h>

// ohjelmaan tarvitaan parametreja komentoriviltä tai .bat tiedostosta

void main ( int argc, char* argv[]) {

int i ;

int sound =1; // äänet ovat valittu perusarvoksi päälle

int sec=10; // viiveen peruasrvo

if ( argc>2) // jos ohjelman paramtereja on ainakin kaksi

if( argv[2][0] =='-') // ja toisen paramtrin enimmäinen merkki on -

sound =0; // ei ääntä

if (argc >1 ){ // jos vähintään yksi parametri

sec= atoi( argv[1]); // muuta paramtri merkkijono luvuksi

printf("\r\n Parameter =%ds\n\r",sec); // tulosta paramtrin arvo

}

else { // ei paramtreja, anna pieni help

printf("\r\nDelay for batch files by OH3GDO %s \n\r Cntrl/C break\n\r, -S no sound, +S default

sound at end",__DATE__);

printf("\r\n No parameters delay=%ds\n\r", sec);

}

//

printf("\rn\nSound=%d\r\n",sound); // tulosta äänimerkin tila

if( sound) // jos äänimerkki on valittu

MessageBeep(MB_ICONASTERISK); // tulosta perusääni

for (i=0; i<sec; i++) { // käy läpi viiveet

Sleep(1000) ;// huom ei sleep() , odota 1000ms

printf("\rDelay=%4ds",sec-i); // tulosta jäljellä oleva viive

}

if(sound) // tehdäänkö loppu ääni  ?

MessageBeep(0xFFFFFFFF); // Windows default ääni

}

/**********Loppu viive.c ********/

osoitin kysymys ( Oh3GMZ)

while (ch != EOF) /* Pyöritetään silmukkaa, kunnes tiedoston loppu tulee vastaan */

{

ch = getc(input); /* Lukee yhden kirjaimen kerrallaan */

  • cptr++= ch; /* print on screen */

luettu++; /* Lisää globaaliin muuttujaan yhden jokaisella kierroksella */

}

Mitä tekee rivi *cptr++ = ch  ?


Osoitin vastaus

ch on funktion sisäinen muuttuja "char ch;" luettu on globaali muuttuja.

  • cptr++ = ch

ch on luettu merkki ( char)

cptr 0n osoitin muistipaikka minne talletetaan ( tai mistä luetaan)

  • muuttujan edessä takoitaa sijoitusta eli ch sijoitetaan cptr osoittamaan muistipaikkan

++ tarkoittaa, että kun muutos on tehty osoitinta siirretään eteenpäin yhden

osoittimen tyypin mukaisen elementin verran.

Koska osoitin on varattu char *cptr merkinnällä se siirtyy

vain yhden byten verran eteen päin.


Osoittimista on hyötyä kun osoitetaan struktuureita, joissa on epämääräinen ( ainakin ohjemoijalle)

määrä muistipaikkoja. Osoitin kyllä tietä hypätä oikean määrän muistipaikkoja eteen tai taaksepäin.

esim.

struct helnkiloStruct {

char nimi[50];

float tuntipalkka;

int tyotunnit;

dateStruct syntymaAika;

dateStruct tullutPalvelukseen;

double kokonaisPalkka;

}; struct helnkiloStruct henkilokunta [ 200];

Kuka osaa sanoa miten monta muistipaikkaa yllä olevaan yhteen henkilään kuluu?

struct henkiloStruct *henkiloPtr, henkilö;


aluksi kiinnitettaan osoitin ensimmäiseen henkilöön

henkiloPtr = henkilokunta[0];

sitten siirretään henkilokunnan ensimmäisen henkilön tiedot kasittelyä varten.

henkilo =*henkiloPtr;

Nyt voidaan lisätä tämän henkilön palkkaa 10 e tunti

henkilo.tuntipalkka += 10.0;

ja lopuksi tehdään talletus tietokantaan takaisin

henkilokunta[0] = *henkiloPtr;

Osoittimia pitää hieman harjoitella

--Oh3gdo 9. helmikuuta 2007 kello 22.08 (EET)

Debug ohjelmointi

Jokaisessa DOS/Windows- tietokoneessa on ohjelma nimeltään Debug

Sitä voi käyttää tutkimaan tietokoneen rekistereitä ja tehdä pieniä apuohjelmia

Kokeile Debug-ohjelmaa

Kirjoita komenotoriville CMD ( run .. )ja sen jälkeen debug

Saat pienen viivan

Kirjoita ?

Saat kevyen helpin

Kuva:debugdisplay.jpg

Kokeile display- (Displa =näytä muisti) komentoa

d 40:0

Kuva:dispmenory.jpg

40 on muistin segmenttiosoite ja 0 on offset.

Tuloksesta näkyy, että tässä koneessa on neljä sarjaporttia, joiden osoitteet ovat

03F8

02F8

03E8

02E8

Seuraavan on rinnakkaisportit

03BC

0378

0278

9F80

Huomaa että Intelin tietokoneissa on käytössä [ http://en.wikipedia.org/wiki/Endianness#Big-endian Big Endian] osoitejärjestelmä. Siinä esitetään ensin hibyte ja sitten lobytet. Motorola käyttää toisenlaista järjestelmää Littel Endian.


Kokeile mitä portteja on omassa tietokoneessasi

Kokeile R komentoa


Kuva:registe.jpg

Tee debug ohjelma helposti

Kopio alla oleva linkin viive.txt

notepadin avulla viive.txt tiedostoksi.

Lopeta debug Q komenolla

Komentotilassa kirjoita

debug < viive.txt


N Viive.COM

A 100

MOV SI,0082

MOV AX,[SI]

XCHG AH,AL

XOR AX,3030

MOV BL,AL

MOV AL,0A

MUL AH

ADD AX,BX

MOV SI,AX

MOV AH,2C

INT 21

MOV BL,DH

MOV AX,SI

AAM

OR AX,3030

XCHG AH,AL

MOV [0160],AX

MOV AH,09

MOV DX,0160

INT 21

MOV AH,06

MOV DL,FF

INT 21

JZ 014C

OR AL,AL

JNZ 013F

MOV AH,08

INT 21

MOV AL,FF

MOV DX,016C

PUSH AX

MOV AH,09

INT 21

POP AX

MOV AH,4C

INT 21

MOV AH,2C

INT 21

CMP BL,DH

JZ 012D

MOV BL,DH

DEC SI

JNZ 011A

SUB AL,AL

MOV DX,016C

JMP 0142

DB "XX SECONDS", D, 24

DB " ", D, A, 24

RCX

79

W

Q

Ohjelma on valmiina viive.com nimisenä .

Kokeile sitä viive 10

10 tarkoittaa sekunnin viivettä

Katso ohjelman pituutta ja vertaa sitä aikasemmin tekemääsi viiveohjelmaa

Debug komennot

Käynnistä debug menemällä ensin komentotilaan Start/Run komennolla

Kuva:startCMD.jpg

Sen jälkeen kirjoita debug ja mahdollisesti tiedostonimi, jota haluat tarkastella tai muuttaa


D DISPLAY ja E Enter komennot

d tarkoittaa muistin katselua. Parametriksi annetaan segmenttiosoite:offsetosoite

Esim. D 40:0 näyttää muistia PC:n muistisegmentistä 40 ja sen offsetosoitteesta 0

Jos segmenttiosoitetta ei anneta käytetään oletussegmenttiä.

Esimerkki: Haluat tarkastaa onko koe.txt-tiedostossa tiedoston loppumerkin Cntrl/z =0x1A vai ei.

Kirjoita debug koe.txt - d 100

Tämä komento tulostaa tiedoston alusta merkit HEX muodossa. Merkit ovat 12345. Vsemmalla on osoite alkaen segmenttiosoitteesta 0c91 ja sen jälkeen offset osoiteet alkaen 100:sta. segmenttiosoiteessta 09c1 ei tässä tarvitse välittää, käyttöjärjestelmä latasi tiedoston seuraavaan vapaaseen muistipaikkaan joka tällä kerralla sattui olemaan 0x09c1. Offset osoite on 16 bitin luku joka pystyy liikkuman 16-bitin muistiavaruudessa ( 0-65535).

Offset ja segmentti rekisteri 

Segmenttiosoite ottaa käyttöön suurempia ryhmiä muista. Segmetti- ja offsetosoitteet menevät osittain päällekkäin. Offsetmuistilla voi muuttaa alempia muistipaikkoja, mutta ei ylempiä. Segmenttiosoitteella taas päinvastoin.

Offsetin neljää alinta bittiä ei voi muuttaa segmenttiosoitteella ja offset osoitteella ei voi muuttaa segmenttiosoitteen neljää ylintä bittiä.

Miksi näin monimutkainen asia? Intelin prosessorit ovat olleet aina ohjelmallisesti alaspäin yhteensopivia.

Kun muisti oli vain 16 bitin levyinen (tyyppi 8080 vuonna 1972), kaikki muistiosoitukset tehtiin pelkästään offset osoitteilla. Ohjelmoijan tai käyttöjärjestelmän pitää koko ajan huolehtia offset muistin rajoista. No tämähän on muutenkin ohjelmoijan tehtävä. Vain sovelluskehittimillä hiiriohjelmia tekevät voivat unohtaa muistin olemassaolon. Edelleen monissa sulautetuissa järjestelmissä muistia on vain muutaman tavu, ei sitä turhuuten tuhlata.


Kun muistiavaruus kasvoi 4 bittiä, vanhat ohjelmat toimivat edelleen uusissa prosessoreissa. Sama menetelmä on toiminut vaikka osoitebittejä on tullut lisää 30 vuotta. Motorola luotti siihen, että ohjelmoijat saavat tehdä kaikki ohjemat aina uudestaan kun sen prosessorien muistiavaruus kasvoi.

Palataan takaisin debug ohjelmointii

Muisti näytetään HEX merkkeinä 16 byten ryhminä kuvan keskellä ja oikeassa reunassa ASCII merkkeinä. Ei-näkyvät ASCII-merkit näytetään pisteinä.

Viiden merkin tiedostossa ei ole 1A eli CNTL/z merkkiä. Se pitää lisätä sinne debug ohjelman avaulla.

Kuva:debugtxt.jpg

Kuinka monta merkkiä on tässä tiedostossa? Näet sen RCX rekisteristä

Kirjoita R

Näet kaikki Intelin 16-bittiset perusrekisterit AX,BX, CX jne. Näiden merkitys riippuu ohjelmasta ja ohjelmoijasta. Microsoftin ( =Charles Simoni) käyttöjärjestelmässä on kuiten tarkkaan määritelty rekisterien käyttö kun levytiedosto on ladattu muistiin. Tiedoston pituus Microsofitilla on CX- rekisterissä. CS näyttää segmettiosoitteen. Sitä ei tarvitse muuttaa tällä kertaa.

Tiedoston pituus (CX=5) on aluksi 5 merkkiä. Kirjoita CX:n 6. RCX <ENTER> kuvan mukaan. Tiedoston pituus on nyt 6 merkkiä, mutta loppumerkki pitää vielä lisätä.

Kirjoita e 106 eli enter muistipaikka 106 (hex). Ohjelma näyttää muistipaikan 106 vanhan arvon ja voit nyt muuttaa sitä. Kirjoita 1A <ENTER>. Jos et anna enteriä vaan välilyönnin saat seuraavan merkin jota voit taas muuttaa.

Kohtuullisen helppoa ilman monimutkaista HEX-editoreia, eikö totta?

Tarkista tiedoston sisältö komennolla d 100 <Enter>. Lopuksi voit tallettaa muutokset levylle kirjoittamalla W <ENTER>

Lopeta debug ohjelma kirjoittamalla Q <Enter>


Avaa tiedosto tavallisella Notepad tai Word-editorilla. Näkyykö sinun laittamasi tiedoston loppumerkki?

Ei näy, etkä voi sitä lukea tai muuttaa tavallisella editorilla. Tiedoston loppumerkkiä ei enää tarvita monestikaan. Tämä oli vain esimerkki kuinka helppoa debugilla on muuttaa binäärimerkkejä tiedostoon.


I ja O komennot

I komennolla luetaan Intelin muistiavaruuden IO-portista byte. Esim. I 378 Debug ohjelma näyttää mitä kirjoitinportin rekisterissä on dataa - AA Kirjoita uusi data FF porttin 378H O eli output komennolla O 378 W Lue uudestaan portti I 378 - FF

Kuva:debug_inout.jpg

Sama asia assemblyllä tehdään näin

MOV DX,378

IN AL,DX

Tulos saadaan AL rekisteristä IO-porttia ei voi kutsua suoraan vaan DX rekisteriä käytetään apurekisterinä.

Vastaavasti IO-porttiin 378H kirjoitetaan data FF

MOV DX,378

MOV AL,FF

OUT DX,AL

Kirjoittamisessa pitää data ja osoite olla tallessa etukäteen

L Load N New ja W komennot

P proceed ja T trace komennot

--Oh3gdo 18. helmikuuta 2007 kello 14.00 (EET)


Uusi c-kielen harjoitustehtävä

Tee ohjelma joka lukee tiedoston muuttaa sen salatuksi ja tallettaa sen salattuna.

Kun ohjelma luetaan uudestaan, se purkaa tiedoston alkuperäiseksi. Käytä tasan 100*8 bitin salasanaa.

Käyttö

salaa.exe salasana infile outfile

Siis anna kolme parametria ohjelmalle salastiedosto muutettava ja muutettu tiedosto

ASSEMBLER ohjelmointi

    ; esimerkki WIN/DOS/PC assemblerohjelmasta.
    ;Kirjoita tämä oh3ne.asm tiedostoon
    ; Valmis ohjelma kirjoittaa kuvaruudun keskelle tekstiä CMD tilassa
    ; XP/WIN/DOS ympäristö 
    ; TASMin pisteet ovat helppokäyttöisiä pikaohjeita kääntäjälle
    ;  puolipiste on kommentin alku 
    ; käännä TASM /z oh3ne     BORLAND C assembler ohjelma -> oh3ne.obj
    ; linkkaa TLINK oh3ne    BORLAND C Linkkeri -> oh3ne.exe

.model small  ; pieni muistimalli: koodi, data ja pino samassa 64k

              ; muistisegmentissä

.stack 100h  ; pino alkaa kohdasta 100 hex segmentin alusta

.data  ;ohjelma data-alueen täyttö TXT on tunnus, jota käytetään ohjemassa

TXT db 'OH3NE ASSEMBLER TESTI by OH3GDO$'  ; loppuun aina $ merkki

.code  ; koodi alkaa

.startup  ; ohje kääntäjälle; laita tähän tarpeelliset aloitustiedot

MOV DH,12  ; kirjoita riville 12

MOV DL,30  ; alkaen sarakkeesta 30

MOV AH,2  ; kirjoita merkkijon BIOS funktio #2

INT 10h  ; käynnistä kursorin asetusfunktio INT10h

MOV DX, OFFSET TXT ; tekstin alku Data alueella laitetaan DX-rekisteriin

MOV AH,9  ; Tulostusfunktio 9 BIOS keskeytys

INT 21h  ; DOS funktiot ovat INT 21H on ohjelman loputusfunktio

.exit  ; Borlandc Tasm ohjelmalle tieto koodin loppumisesta END  ; lopeta asm-ohjelma, tieto kääntäjälle


linkin oh3ne.asm-tiedosto

linkin oh3ne.exe-tiedosto

--Oh3gdo 25. helmikuuta 2007 kello 09.59 (EET)


DSP ohjelmoinnista

  DSP tarkoittaa digitaalista signaalin käsittelyllä tapahtuvaa tiedon muokkausta.

Esimerkkejä radioamatööri laitteista: Analogista tietoa voidaan tuottaa digitaalisesti, esim. OH3NE toistimella olevat asematunnistusäänet ja vaihdettavat väliäänet on tehty suoraan prosessorin sisälle. Analogista tietoa voidaan lukea prosessorille ja käsitellä sitä digitaalisesti kuten aliäänitunnistimissa, jossa toistimen radion signaalia käsitellään DSP-tekniikalla ja tutkitaan onko signaalissa tukittava aliääni. Aliäänet ovat 52-250Hz alueella. Normaalisti aliääntä pitää olla 10% modulaatiosta.

Analogisesta tiedosta voidaan tunnistaa määrättyä taajuutta kuten esim. toistimien logiikoissa tunnistetaan 1750Hz ääni.

Mitä erikoista on DSP:ssä verrattuna tavalliseen ohjelmointiin? Teoreettisesti ei mitään, mutta käytännössä teoria ei ole sama kuin käytäntö. Tunnistettaessa kohinaisesta signaalista määräräittyä taajuutta kerrotaan mitattava tulosignaali, joka on saatu ADC:lta, tutkittavalla sini- ja kosinisignaalilla. Näiden signaalien nelilöiden summan neliöjuuri edustaa tutkittavaa taajuuskomponenttia tasavirtatasona. Tätä menetelmää kutsutaan DFT menetelmäksi eli Discrete Fourier Transfer. Toinen vastaava menetelmä on FFT eli Fast Fourier Trasfer. Matematiikasta kiinnostuneet voivat tukia kaavoja tästä kirjasta

Fast Fourier Transforms: Algorithms Elliot, D.F. and Rao, K.R. Academic Press, New York, 1982

Kaikki DPS-ohjelmointi voidaan tehdä tavallisellakin prosessorilla, mutta käytännössä jos mittaukset tehdään reaaliaikaisesti, tarvitaan pitkiä, monibittisiä kertolaskuja, yhteenlaskuja tiedon siirtoja muistipaikkojen välillä. Näissä laskuissa tapahtuu helposti ylivuotoja jos bittimäärä ei ole tarpeeksi suuri. Ja tärkein asia: aikaa kuluu liian paljon! DSP-prosessoreissa on tätä ns. rumpulaskentaa varten yksi tai useampi erikoinen monibittinen rekisteri ja siihen liittyvät käskyt. Yhdellä DSP käskyllä voidaan tehdä kerto- tai yhteenlasku jonka tulos menee 48-bittiseen rekisteriin. Laskujen parametrien osoitteet muuttuvat automaattisesti eteenpäin. Ylivuotoa ei helposti tapahdu pitkissä 48-bittisissä rekistereissä. DSP prosessoreita on kokonaislukutyyppisiä ja liukuvan pilkun laskentaan pystyviä. Useimmiten reaalimaailmassa riittää kokonaisluku laskenta. Fort-kielen luojalta Charles Moorelta kysyttiin miksi Fortissa ei ole liukuvan pilkun matematiikkarutiineja. Moore vastasi: Liukuvan pilkun matematiikkaa kuuluu matematiikkatieteen alaan. Minä teen laitteitta joilla ratkaistaan oikeita ongelmia kuten teleskooppien ohjauksia ja siellä ei missään esiinny liukuvanpilkun matematiikan tarpeita.


Texas Instruments väittää tehneensä ensimmäisen kaupallisen DSP-prosessorin vuonna 1987. Texas Intrumentsin DSP-prosessorit alkava TMS320-merkinnällä. Nykyään DSP-valmistajia on paljon. Motorola teki paljon erilaisia malleja 1990-luvulla. Nykyään Freescale-niminen yhtiö jatkaa tätä DSP 5680x- sarjaa.

Itse tunnen parhaiten Microchipin ja TI:n DSP prosessorit. TI:n TSM320C6211 toimii 1300 Mipsillä eikä se ole läheskään nopein. Sitä käytetään kuvan käsittelyssä ns. älykamerassa. Microchipin DSP mallit sisältävät myös kaikki tavallisten IO-prosessoreiden ominaisuudet kuten Flash datamuistit, laskurit, ADC ja PWM-muuntimet, UARTit jne. Näitä PIC30Fxxxx ja PIC33Fxxx malleja saa myös ilman DSP ominaisuuksia. Silloin ne ovat PIC24Fxxxx tyyppejä. DSP-rekisterien leveys on yleensä 16-32-bittiä. DSP-prosessorit eivät ole sen vaikeampia kuin muutkaan prosessorit, oikeastaan on helpompaa tehdä sama asia DSP:llä kuin ilman. Toinen asia on sitten matematiikka jota kuitenkin tarvitaan silloin kun DSP:llä tehdään sovelluksia. Se pitää hallita ensin ennen kuin voi tehdä mitään DSP-töitä.

Sovelluksia: -Modeemien modulointi ja demodulointi. -Laakerivikojen ennakointi. -Radioamatöörien Mars-luotaimen signaalin etsintä kohinan alta. -synteettisesti luodut äänet ravikilpailujen lähetyksessä. -FFT signaalin taajuuserittely -signaaligeneraattori puhelimen taajuusvasteen tutkimiseen -Rautatien maan kantavuuden tutkiminen -Hälyäänien vaimentaminen aktiivisesti autoissa -Särön mittaus GSM-puhelimissa


Kiinnostaako asia lisää? Kysy.

 OH3GDO


Directx ohjelmoinnista

Directx on ohjelmiston ja raudan välinen rajapinta Windows maailmassa. Sitä käytetään nopeuttamaan ohjelmia, jotka käsittelevät PC:n laitteitta erityisesti grafiikan, äänen ja peliohjaimien kanssa. Ilman tätä rajapintaa jokaisen ohjelmoijan pitäisi osata käyttää jokaista äänikorttia, grafiikkakorttia jne. suoraan. Tätä tehtiin DOS aikakaudella. Ei kai enää missään käyttöjärjestelmässä ole samoja ongelmia laitteiden asennuksessa? USB -ääni ja -grafiikkalaitteet liittyvät samalla periaatteella käyttöjärjestelmään kuin kiinteät laitteetkin. Nykyään on helppo lisätä hyvälaatuinen (Softrock40 varten) äänikortti PC:lle USB:n ja Firefiren kautta. Samoin useita näyttökortteja voidaan käyttää yhtä aikaa. Aikaisemmin vain paremmissa CAD-ohjelmissa oli tuki kahdelle monitorille. Nykyään se kuuluu jo käyttöjärjestelmään.

Itse olen kiinnostutut äänikortin käyttämisestä mittauksissa. Olenkin jo hieman edistynyt ja pystyn lukemaan kaksikanavaista dataa äänikortilta ja samanaikaisesti tuottamaan ääntä halutulla nopeudella, taajuudella, tarkkuudella, voimakkuudella ja kanavamäärällä. Samoin pystyn esittämään sitä graafisesti PC:llä kuten oskilloskoopilla. (OH3GDO 1.2.2008) Alla eräs testikuva. Kuva:lcr_mittari.jpg

Alla ohjelman laiteosuus:

Kuva:Rlc_meter.gif

Mistä pääsee alkuun? Microsoftin sivulta voit ladata ilmaiseksi 450 MB paketin DirectX SDK (November 2007 versio) [http://www.microsoft.com/downloads/details.aspx?familyid=4b78a58a-e672-4b83-a28e-72b5e93bd60a

http://www.microsoft.com/downloads/details.aspx?familyid=4b78a58a-e672-4b83-a28e-72b5e93bd60a]

Henkilökohtaiset työkalut