« Prethodna stranica Page — Sledeća stranica »
Korišćenje asemblera u objektnom Pascal-u II deo
18.05.2007
Sledi nastavak iz prethodnog priloga, i priča o primeni asemblera (Assembler Language) unutar Delphi-ja
C PU poseduje mogućnost manipulacije vrednostima iz registara, tako da bi dodali 10 na vrednost registra eax, trebali bi napisati sledeći heksadecimali operativni kod:
05/0a/00/00/00
Ovo je tzv. mašinski kod, kod koga za svaku ugrađenu funkciju u CPU-u imamo određeni broj (šifru za poziv). Kao što vidite pisanje programa u mašinskom kodu je jako naporno (dosadno), a otklanjanje bug-ova je još teže. Asemblerski jezik nam dopušta snagu mašinskog jezika na lakši način, a sam posao prevođenja (konvertovanja) u mašinski kod upravo vrši Asembler. U Delphi je ugrađen Borland-ov Turbo Assembler i ponekad je pravo zadovoljstvo koristiti ga. Ako se sada ponovo vratimo na dodavanje 10 registu eax, odgovarajuća asemblerska instrukcija bi izgledala na sledeći način:
add eax,10 {a := a + 10}
Slično ovome, oduzimanje vrednosti ebx od eax bi bilo:
sub eax,ebx {a := a – b }
Da bi privremeno sačuvali dobijenu vrednost, premestićemo je u drugi registar,
mov eax,ecx {a := c }
ili, još bolje, sačuvaćemo datu vrednost u nekoj od memorijskih adresa:
mov [1235],eax
{smestanje vrednosti registra eax na adresu 1235}
Naravno, moguće je kretanje vrednosti i u obrnutom smeru:
mov eax,[1235]
Kada vršite transfer u memorijski prostor, na umu uvek treba da vam bude veličina vrednosti koja se prebacuje. U našem primeru, imali smo instrukciju mov [1235],eax koja rezultira ne samo zauzećem memorijske adrese 1235, nego i 1236, 1237 i 1238, pošto premeštate 32-bitnu vrednost, tj. vrednost od 4 bajta. Memorijski prostor uvek adresiramo u bajtovima. ![]()
Korišćenje asemblera u objektnom Pascal-u I deo
18.05.2007
U ovom i narednom prilogu usredsredićemo se na upoznavanje primene asemblera (Assembler Language) unutar Delphi-ja
U ovom i ovom i narednom prilogu usredsredićemo se na upoznavanje primene asemblera (Assembler Language) unutar Delphi-ja, odnosno objektnog Pascal-a. Pored toga, u prolazu ćemo se pozabaviti i drugim aspektima programiranja. Radi jednostavnosti, u primerima ćemo koristiti Intel-ov podskup asemblerskih instrukcija, pošto on omogućava generalniji pristup, sa samo nekoliko specijalnih izuzetaka. Nadalje, svi dati asemblerski primeri biće smešteni u Pascal okruženje.
Zašto uopšte koristiti asembler? Svi znamo, da objektni Pascal proizvodi brz i efikasan programski kod, dodajući ovome Delphi-ijevo okruženje za rapidni razvoj alikacija, zaista postaje upitno zašto uopšte koristiti asembler. Govoreći iz iskustva, u radu sa Delphi-jem postoji nekoliko situacija kada je preporučljivo koristiti programiranje na “niskom nivou”, a to su:
- Obrada velike količine podataka
- Veoma brze grafičke rutine
Kasnije ćemo vam kroz primere plastičnije ilustrovati šta ovo znači.
Šta je zapravo asembler? Nadam se da vam je poznat princip rada centralne procesorske jedinice, u osnovi radi se o “običnom” brzom kalkulatoru sa velikom memorijom. Memorija je organizovana u sekvence binarnih cifri, tj. u blokove od osam bita, od kojih svaki formira jedan bajt. Prema tome, svaki bajt može da skladišti integer vrednost u intervalu od 0 do 255, i svaka pozicija bajta u delu memorije određena je jedinstvenom adresom koju sentralna procesorska jedinica (CPU) može da promeni ili da iščita njegovu vrednost. CPU poseduje i određeni broj registara (zamislite registre kao globalne varijable) kojima može da manipuliše. Na primer, eax,ebx,ecx i edx su opšti 32-bitni registri, koje ćemo koristiti u sledećim primerima. Iz ovoga možemo zaključiti da je najveći broj koji možemo da smestimo u registar eax 2 na 32 minus 1, ili tačnije 4.294.967.295. ![]()
Komponenta Notebook
18.05.2007
Kada vaše palete alatki broje veliki broj komponenti, onda vam od velike pomoći može biti Delphi-jeva kontrola Notebook
K ada za vam za vašu aplikaciju budu potrebne višestruke palete alatki, tj. ukoliko imate ogroman broj dugmića sa alatkama, nećete ih moći smestiti u jednu liniju. Tada ćete moći da iskoristite Delphi-jevu komponentu “Notebook” koja ide u paru sa komponentom “TabSet”. Da bi ste dobili program kao nalici uradite sledeće:
- Otvorite novi projekt i na praznu formu postavite komponentu “Notebook” koja se nalazi na paleti “Win 3.1″.
- Osobinu Align postavite na “alTop” i recimo neka visina bude “25″.
- Sada ubacite komponentu “TabSet” na formu, takođe sa palete “Win 3.1″. I osobinu poravnavanja postavite na alTop. Na ovaj način skup kartica postavljamo odmah ispod “Notebook”-a, u vrh prozora.
- Kliknite na dugmić(tri tačkice) osobine “Tabs”, da bi dobili “Stringlist Editor” u kome će te red po red unositi nazive kartica paleta.
- Pređite na komponentu “Notebook” i u osobinu “Pages”, pritiskom na dugme dobićete “Notebook Editor”. U ovom editoru ćemo izvršiti povezivanje kontrola, Notebook i TabSet. Svaka kartica-paleta treba da ima odgovarajuću oznaku komponente “TabSet”. Jednostavno preko dugmeta “Add” dodajte stranice za svaku karticu, i sa Edit preimenujte u odgovarajući naziv.
- Ako sada kliknete na osobinu “ActivePages” videćete izlistane sve stavke koje ste uneli u prethodnom koraku.
- Postavite sada na komopnentu “Notebook”, kontrolu “ToolBar” sa palete “Win32″. Paleta za buduće ikonice-alate će se raširiti preko celog Notebook-a. Sada kliknite desnim tasterom iznad Toolbar-a i dodajte dugmad za vaše alate (New Button).
Sada imate pravi toolbar sa više paleta alatki (koje se mogu razdvojiti po nekoj logici). Ukoliko imate više kartica nego što može da se prikaže odjednom, u desnom uglu će se pojaviti dva dugmenceta (levo-desno) za navigaciju i pomeranje u vidno polje kartica-paleta koje se ne vide.
![]()
Prvi pogled na Kylix
18.05.2007
Predstavljamo vam prvo visoko-preformansno Linux orijentisano aplikaciono razvojno okruženje – Kylix – tj. Delphi pod Linuxom
P rve reči o projektu Kylix pojavile su se 28. septembra 1999., kada je kompanija “Inprise/Borland” u svojim vestima najavila novi proizvod kao visoko-preformansno Linux orijentisano aplikaciono razvojno okruženje, koje će podržavati C, C++ i Delphi razvoj. A sve je poteklo od inicijative velikog broja Linux programera, tokom leta 1999. godine, koji su tražili Linux verziju Delphi-ja.
Do sada ste sigurno mislili da je razvoj ozbiljnih Linux aplikacija jedino moguć uz C kompajler. Bilo kako bilo, sada možete kreirati napredne Linux programe u deliću vremena, koje je vam je bilo ranije potrebno. Kylix je prva visoko-preformansna RAD alatka za Linux, koja omogućava i Windows programerima da izgrade “čiste” Linux aplikacije (pošto je prenos relativno lak). Uistinu, ovo nije jedna RAD alatka za Linux, pre toga imali smo “Omnis Studio”.
Kylix nam dolazi u dve verzije:
- Desktop developer edition
- Server developer edition
Serverska verzija sadrži sve i što Desktop, plus nekoliko dodatnih kontrola – komponenti, uključujući tu i NetCLX Internet i Apache web development kompnente. Kutija u kojoj se isporučuje jedno serversko izdanje Kylix (vidi sliku) sadrži sledeće:
- Kylix Server disk
- Disk sa dodatnim alatima
- Evaluation verziju distribucije SuSE v7.0
- Quick Start manual
- Manual za objektni Pascal
- Developer’s Guide manual
- Poster na kome se nalazi objektna hijerarhija
- Registraciona kartica
Što se tiče uputstava, priručnik “Quick Start” vam omogućava dobra pregled novog razvojnog okruženja i brz prelaz na samo kreiranje. Jedno od poglavlja u priručniku će vas provesti kroz kreiranje jednostavnog editora teksta. Iznedaniće vas što u njemu nema obješnjenja postupka instalacije Kylix-a. Priručnik “Object Pascal Language Guide” opisuje programski jezik Pascal u okruženjima i Windows, i Linux. Tamo gde je potrebno, ukazane su razlike u programiranju između ove dve platforme.
Treća knjiga je “Kylix Developer’s Guide” koja je vrlo iscrpna i pokriva praktične aspekte Kylix programiranja, a neke od obrađenih tema su: razvoj aplikacija za baze podataka, pisanje sopstvenih komponenti i kreiranje Web server aplikacija.
Da kažemo da postoji i verzija “Kylix Open Edition”, koja će moći slobodno da se “skine” sa Borland-ovog sajta www.borland.com , namenjena programerima koji će da koriste Kylix za Open Source razvoj. ![]()
Kako dobiti spisak svih instaliranih uređaja?
18.05.2007
Neke od aplikacija zahtevaju komunikaciju sa eksternim uređajima. Da bi uopšte uspostavili komunikaciju potrebno je da ih detektujemo
Potrebu za pregledom uređaja prikačenih na spoljne portove možemo rešiti korišćenjem funkcije QueryDosDevice. Da odmah naglasimo da je funkciju moguće koristiti samo u Windows NT okruženju (Win-32>). Ovom funkcijom obezbeđujemo aplikacijama informaciju o nazivima ugrađenih MS-DOS uređaja. Funkcija može mapirati samo određene MS-DOS uređaje ili sve postojeće uređaje. Nazivi MS-DOS uređaja čuvaju se u Windows NT kao simbolička imena. Sintaksa same funkcije je sledeća:
DWORD QueryDosDevice(
LPCTSTR lpDeviceName,
LPTSTR lpTargetPath,
DWORD ucchMax
);
Parametri predstavljaju sledeće:
- LPCTSTR – parametar predstavlja adresu stringa MS-DOS uređaja.
- LPTSTR – parametar predstavlja adresu bafera u kome se čuvaju rezultati upita za uređajima.
- DWORD – parametar predstavlja maksimalnu veličinu bafera.
Za primer ćemo napraviti mali programčić koji će izlistati sve MS-DOS uređaje na sistemu. Samo obratite pažnju da program pokrećete u Win-32 okruženju. Pokrenite Delphi i otvorite novi projekt, te na praznu formu postavite po jednu kontrolu: TMemo i TButton. Na kraju, kontroli TButton samo dodajte sledeći kod (u okviru događaja OnClick):
procedure TForm1.Button1Click(Sender: TObject);
var
naziv: string;
isize, i: dword;
begin
setlength(istr, 4000);
isize := QueryDosDevice(nil, @naziv[1], 4000);
for i := 1 to isize do
if naziv[i] = #0 then naziv[i] := #10;
memo1.lines.CommaText := naziv;
end;
![]()
Funkcija AutoComplete
18.05.2007
Funkcija mnogima poznata iz I.Explorera i sličnih programa. Zašto je ne bi Implementirali i u svoje aplikacije?
Uovom tekstu ćete pronaći veoma korisnu proceduru koja će vašim aplikacijama obezbediti “Autocompletion” mogućnost. Ova mogućnost ste sigurno iskusili uz Internet Explorer, kada ukucavate adresu neke stranice, a browser, zahvaljujući history listi, vrši “dokompletiranje” adrese. Tako će biti i u našem primeru, s tim što ćemo umesto URL-a, imati fontove. Vi možete i sami napraviti neku listu stavki da bi isprobali dokompletiranje. Postavite na praznu formu jedan Combobox, te za dobijanje svih fontova na sistemu, bilo gde dodajte sledeću liniju:
ComboBox1.Items := Screen.Fonts;
Ova linija će u combo polje dodati sve fontove (ovo će nam biti bitno za testiranje). Te, ostalo vam je da unutar događaja OnChange (combobox-a) dodate programski kod:
procedure TForm1.ComboBox1Change(Sender: TObject);
var
I, StartPoz: Integer;
begin
ComboBox1.Items := Screen.Fonts;
for I := 0 to ComboBox1.Items.Count -1 do
begin
with ComboBox1 do
begin
if (Text = ”) or (LowerCase(Items[I]) = LowerCase(Text)) then Exit;
if StrLComp (PChar (LowerCase (Items[I])),_ PChar(LowerCase(Text)), Length(Text)) = 0 then
begin
StartPoz := Length(Text);
Text := Text + Copy(Items[I], StartPoz + 1,_ Length(Items[I]));
SelStart := StartPoz;
SelLength := Length(Text) – StartPoz;
end;
end;
end;
end;
![]()
Pokretanje procesa i njegovo okončavanje
18.05.2007
Metoda kojom možete pokrenuti neki proces van vaše aplikacije, i zatim ispratiti njegovo okončavanje
Ako vam ikada bude potrebno da pokrećete neku spoljnu aplikaciju iz vašeg projekta, a treba da sačekate njen završetak rada, nemojte koristiti proceduru ShellExecute. Zaobićićemo ovu proceduru korišćenjem funkcija: CreateProcess, WaitForSingleObject i CloseHandle. Pokrenite novi projekt i na formu postavite jedno komandno dugme, te događaju ButtonClick dodajte sledeći programski kod:
procedure TForm1.Button1Click(Sender: TObject);
var
proc_info: TProcessInformation;
startni_info: TStartupInfo;
begin
// inicijalizacija
FillChar(proc_info, sizeof(TProcessInformation), 0);
FillChar(startni_info, sizeof(TStartupInfo), 0); startni_info.cb := sizeof(TStartupInfo);
// pokusaj kreiranja procesa
if CreateProcess(‘c:\windows\notepad.exe’, nil, nil, nil, false, NORMAL_PRIORITY_CLASS, nil, nil, startni_info, proc_info) <> False then
begin
// proces je uspesno kreiran i
//ceka se njegovo okoncanje…
WaitForSingleObject(proc_info.hProcess, INFINITE);
// Proces je zavrsen. Možemo ga zatvoriti
CloseHandle(proc_info.hProcess); Application.MessageBox(‘Notepad zavrsio rad!’, ‘Info’, MB_ICONINFORMATION);
end
else begin
// nemogućnost kreiranja procesa
Application.MessageBox(‘Nije moguce izvrsiti ‘ + ‘application’, ‘Error’, MB_ICONEXCLAMATION);
end;
end;
Kada pokrenete aplikaciju i kliknete dugme, pokrenuće se Windows editor “Notepad” (proverite samo putanju). Kada zatvorite “Notepad”, dobićete poruku o završetku pozvanog procesa. Eventualni problemi mogu da se jave kod funkcije WaitForSingleObjecti to u kombinaciji sa nekim aplikacijama. ![]()
Pretraživanje fajlova
18.05.2007
Funkcija kojom vršite pretraživanje drajvova u potrazi za određenim fajlovima. Vrlo koristan dodatak svakoj aplikaciji
Za pretraživanje fajlova određenog naziva fajla (kao na primer C:\WINDOWS\*.INI), možemo iskoristiti funkcije FindFirst i FindNext i proceduru FindClose. Da bi mogli da koristimo ove funkcije koristićemo tip zapisa (record) TSearchRec koji između ostalog sadrži i informacije o fajlu potrebne za pretraživanje. U sledećoj strukturi zapisa TSearchRec, možete videti koje informacije nosi ovaj zapis, i koje su potrebne funkcijama FindFirst i FindNext. Najvažniji podatak je Name (naziv fajla – string) koji sadrži dugačko ime fajla, bez putanje do fajla.
type
TSearchRec = record
Time: Integer;
Size: Integer;
Attr: Integer;
Name: TFileName;
ExcludeAttr: Integer;
FindHandle: THandle;
FindData: TWin32FindData; // Dodatne informacije
end;
Podatak Time predstavlja informaciju o DOS sistemskom vremenu, poslednje modifikacije fajla. Možete konvertovati ovu vrednost u tip podatka TDateTime koristeći funkciju FileDateToDateTime.
Za samo pretraživanje iskoristićemo sledeći programski kod:
var
SearchRec: TSearchRec;
begin
if FindFirst(‘C:\WINDOWS\*.INI’, attributes, SearchRec) = 0 then
begin
repeat
// Ovde obradjujemo svaki pronadjeni fajl.
// Informacije o svakom fajlu
// nalaze se u zapisu SearchRec.
until FindNext(SearchRec) <> 0;
FindClose(SearchRec);
end;
end;
Ukoliko funkcija FindFirst vrati nulu (0), to znači da je pronađen najmanje jedan fajl koji zadovoljava postavljeni kriterijum. Potom koristimo funkciju FindNext da bi dobili informacije o sledećim fajlovima koji takođe zadovoljavaju postavljeni kriterijum. Ova funkcija takođe vraća nulu ukoliko pronađe sledeći fajl. Kada pređemo sve fajlove u jednom folderu, potrebno je da zatvorimo pretraživanje pozivom procedure FindClose, kojom oslobađamo rezervisane resurse zapisa koje smo alocirali funkcijom FindFirst. Ukoliko je atribut nula (0), funkcije FindFirst i FindNext će pretraživati samo “normalne” fajlove, a ne i one koji su obeleženi kao: Archive, Read-only, Hidden, System, Directory, Volume. ![]()
Glasovno telefoniranje
18.05.2007
Neka vaš modem “izigrava” obični telefon. Modemom birajte obične “glasovne” telefonske brojeve
Usledećem primeru ćemo videti kako da iz naše Delphi aplikacije biramo telefonske brojeve za glasovnu komunikaciju, nešto slično Windows-ovom “Phone Dialer”-u. Sve se ovo odvija preko poziva funkcija u biblioteci TAPI32.dll. Pokrenite Delphi i kreirajte novi projekt, a zatim posle svih deklaracija dodajte sledeće konstante i funkcije:
{tapi Errors}
const TAPIERR_CONNECTED = 0;
const TAPIERR_DROPPED = -1;
const TAPIERR_NOREQUESTRECIPIENT = -2;
const TAPIERR_REQUESTQUEUEFULL = -3;
const TAPIERR_INVALDESTADDRESS = -4;
const TAPIERR_INVALWINDOWHANDLE = -5;
const TAPIERR_INVALDEVICECLASS = -6;
const TAPIERR_INVALDEVICEID = -7;
const TAPIERR_DEVICECLASSUNAVAIL = -8;
const TAPIERR_DEVICEIDUNAVAIL = -9;
const TAPIERR_DEVICEINUSE = -10;
const TAPIERR_DESTBUSY = -11;
const TAPIERR_DESTNOANSWER = -12;
const TAPIERR_DESTUNAVAIL = -13;
const TAPIERR_UNKNOWNWINHANDLE = -14;
const TAPIERR_UNKNOWNREQUESTID = -15;
const TAPIERR_REQUESTFAILED = -16;
const TAPIERR_REQUESTCANCELLED = -17;
const TAPIERR_INVALPOINTER = -18;
{tapi size constants}
const TAPIMAXTelBrojSIZE = 80;
const TAPIMAXAPPNAMESIZE = 40;
const TAPIMAXPozivUpucenSIZE = 40;
const TAPIMAXKomentarSIZE = 80;
const TAPIMAXDEVICECLASSSIZE = 40;
const TAPIMAXDEVICEIDSIZE = 40;
function tapiRequestMakeCallA(TelBroj : PAnsiChar;
AppName : PAnsiChar;
PozivUpucen : PAnsiChar;
Komentar : PAnsiChar) : LongInt;
stdcall; external ‘TAPI32.DLL’;
function tapiRequestMakeCallW(TelBroj : PWideChar;
AppName : PWideChar;
PozivUpucen : PWideChar;
Komentar : PWideChar) : LongInt;
stdcall; external ‘TAPI32.DLL’;
function tapiRequestMakeCall(TelBroj : PChar;
AppName : PChar;
PozivUpucen : PChar;
Komentar : PChar) : LongInt;
stdcall; external ‘TAPI32.DLL’;
Potom dodajte na formu jedno komandno dugme, i u događaj Button_Click smestite sledeći kod:
procedure TForm1.Button1Click(Sender: TObject);
var
TelBroj : string;
PozivUpucen : string;
Komentar : string;
begin
TelBroj := ’011-111111′; // broj telefona
PozivUpucen := ‘Ime’; // onaj koga pozivamo
Komentar := ‘Poziv upicen…’; // neki komentar
tapiRequestMakeCall(pChar(TelBroj),
PChar(Application.Title),
PChar(PozivUpucen),
PChar(Komentar));
end;
Kada pokrenete aplikaciju i kliknete na dugme, automatski će se birati broj naveden u varijabli “TelBroj”. Na ovaj način možete na napravite program – Telefonski imenik, koji će odmah birati upisane brojeve. ![]()
Upisivanje kontakata u MS Outlook
18.05.2007
Nakon upoznavanja sa postupkom čitanja podataka o kontaktima, videćemo i kao se isti podaci dodaju u Outlook-ov adresar
Nastavljajući se na prethodni prilog u kome smo vam prikazali kako da ičitate podatke o kontaktima iz Outlook-a, u ovom prilogu ćemo vam prikazati kako da upišete novi kontakt u Outlook. Sa ovom procedurom možete, na primer, kreirati aplikaciju za konverziju ili import-eksport aplikaciju. Radi primera kreiraćemo novi Delphi projekt sa formom na koju ćemo postaviti nekoliko polja sa podacima koje treba da upišete u Outlook-ov folder Contacts. Postavite elemente (kontrole) kao na slici i dodajte sledeći programski kod:
{$IFDEF SYN_COMPILER_6}
Uses ComObj, Outlook2000;
{$ELSE}
Uses ComObj, Outlook8;
{$ENDIF}
procedure UpisNovogKontakta;
var
OutlApp : OutlookApplication;
OutlNamespace : Namespace;
ContactFolder : MAPIFolder;
Contact : ContactItem;
begin
OutlApp:=CoOutlookApplication.Create;
OutlNamespace:=OutlApp.GetNameSpace(‘MAPI’);
ContactFolder:=OutlNamespace.GetDefaultFolder(olFolderContacts);
Contact:=OutlApp.createitem(olContactItem) as ContactItem;
Contact.FirstName:=Form1.Edit1.Text;
Contact.LastName:=Form1.Edit2.Text;
Contact.HomeAddressStreet:=Form1.Edit3.Text;
Contact.HomeAddressCountry:=Form1.Edit4.Text;
Contact.HomeAddressPostalCode:=Form1.Edit5.Text;
Contact.HomeAddressCity:=Form1.Edit6.Text;
Contact.HomeTelephoneNumber:=Form1.Edit7.Text;
Contact.HomeFaxNumber:=Form1.Edit8.Text;
Contact.Email1Address:=Form1.Edit9.Text;
Contact.save;
OutlApp:=nil;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
UpisNovogKontakta
end;
![]()


