Delphillä assemblerin+merkkijonojen käyttö helppoa !

Delphillä myös assemblerin käyttö koodissa on helppoa, kuten (myös binääristen) merkkijonojenkin !

Seuraava funktio esimerkiksi palauttaa merkkojonon, jonka arvo on prosessoristasi riippuen esim.

'genuineIntel'
'AuthenticAmd' jne ...

function CpuBrandID:String;
begin
SetLength(Result, 12);
asm
push EBX
push EDI
mov EAX,Result
mov EDI,[eax]
xor EAX,EAX
CPUID
cld
mov [edi], ebx
mov [edi 4], edx
mov [edi 8], ecx
pop EDI
pop EBX
end;
end;

Samalla paljastuu se asia, että vaikka objectpascalissa voikin tehdä tyyppimuunnoksen tähän tapaan:

var
St1 : String;
P : PChar;

begin
St1 := CpuBrandID;
P := PChar(St1);
end;

niin konekielikoodin kannalta tuo string onkin enemmänkin PPChar kuin PChar !

C-koodaajille siis:

enemmänkin char ** kuin char * !

Kuitenkin, jos Delphi -koodi ja C -koodi pitää saada keskustelemaan keskenään, niin yleensä homma kuitenkin hoidetaan näin:

### jokudll.c tai jokudll.cpp:

#ifdef CPP
extern "C" {
#endif

void omafunktio(char * Value) {

}

#ifdef CPP
}
#endif

...

ja sitten delphissä näin:

### jokudllimpu.pas:

unit jokudllimpu;

procedure omafunktio(Value:PChar); cdecl; external 'jokudll.dll';

tämän jälkeen kun kutsut delphissä omafunktio(PChar(St1));

niin se kutsuu jokudll.dll:ssä olevaa C:llä koodattua omafunktio -funktiota välittäen sille St1:String -muuttujan, mutta PChar:ksi muunnettuna.

huomaa: C -koodissa ei ole syytä muuttaa merkkijonoa, varsinkaan sen pituutta !

Ja jos sen arvoakaan muutetaan C-koodissa, olisi Delphissä ennen ko. funktiokutsua suoritettava:

UniqueString(St1);

Tuon UniqueString:n ansiosta C -koodi voi muuttaa muuttujan St1 arvoa, kuitenkin siten, että sen pituus ei muutu.

Jos pituutta on tarpee muuttaa C:llä, silloin pitäisi C:ssä määritellä:

int omafunktio(char * Value);

ja vastaavasti Delphissä:

function omafunktio(Value:PChar):Integer; cdecl; external 'jokudll.dll';

tällöin annetaan C -funktion palauttaa uusi pituus (joka ei saa siltikään ylittää alkuperäistä pituutta!)

ja omafunktio -kutsu delphissä pitäisi tällöin tehdä näin:

UniqueString(St1);
SetLength(St1, omafunktio(PChar(St1)));

Näin siis C:ssä voi muuttaa merkkijonon sisältöä ja/tai lyhentää sitä, mutta EI pidentää.

Delphin String EI siis oikeasti ole PChar, mutta on suunniteltu siten, että sitä voi tietyin rajoituksin kohdella PChar:na, kunhan:

a) merkkijonoa ei muuteta PChar -viittauksen kautta

tai

b) UniqueString -kutsulla varmistetaan, että merkkijonon viitteiden määrä=1, tällöin sisältöä voi muuttaa, pituutta ei.

Pituutta ei siis tule milloinkaan suoraan muuttaa PChar -viittauksen kautta, mutta toki PChar -viittauksen saava funktio voi palauttaa uuden (saman tai lyhyemmän pituuden kuin alkuper. pituus) pituuden, joka sitten Delphillä asetetaan voimaan SetLength -proseduurilla.

Huomaa myös:

St1 := 'abc'#0'def';

nyt:

length(St1) = 7,

mutta:

strlen(PChar(St1)) = 3

!!!

strlen(PChar(St1)) on yleensä sama kuin length(St1), mutta JOS St1 sisältää NULL -merkkejä eli #0 = chr(0) ( basicissa chr$(0) )

niin tällöin strlen ilmoittaa merkkien määrän ennen ensimmäistä null -merkkiä, mutta length merkkijonon koko pituuden null -merkkeineen.

Jos merkkijono voi sisältää NULL -merkkejä, tulee mahd. C -koodille välittää erikseen merkkijonon pituus kokonaislukuna, koska muuten C:ssä oletusarvoisesti ensimmäinen NULL katkaisee merkkijonon, Delphissä taas ei.

Huomaa: monet I/O -aliohjelmat (kuten windows MessageBox ja delphin omakin ShowMessage) tulkitsevat merkkijonon päättyvän NULL -merkkiin.

Näppärä toki koodaa tarvittaessa oman apufunktion, joka esim tekee merkkijonosta kopion siten, että NULL -merkin tilalle tuleekin merkkijono '' ...
0349
Äänestä

Muut lukivat myös

Vastaukset

Vanhimmat

Ei vielä vastauksia

Aloittaja odottaa vastauksia. Kerro oma näkemyksesi ensimmäisenä.

Kommentoi aloitusta


Delphifani80 kirjoitti:

Delphillä myös assemblerin käyttö koodissa on helppoa, kuten (myös binääristen) merkkijonojenkin !

Seuraava funktio esimerkiksi palauttaa merkkojonon, jonka arvo on prosessoristasi riippuen esim.

'genuineIntel'
'AuthenticAmd' jne ...

function CpuBrandID:String;
begin
SetLength(Result, 12);
asm
push EBX
push EDI
mov EAX,Result
mov EDI,[eax]
xor EAX,EAX
CPUID
cld
mov [edi], ebx
mov [edi 4], edx
mov [edi 8], ecx
pop EDI
pop EBX
end;
end;

Samalla paljastuu se asia, että vaikka objectpascalissa voikin tehdä tyyppimuunnoksen tähän tapaan:

var
St1 : String;
P : PChar;

begin
St1 := CpuBrandID;
P := PChar(St1);
end;

niin konekielikoodin kannalta tuo string onkin enemmänkin PPChar kuin PChar !

C-koodaajille siis:

enemmänkin char ** kuin char * !

Kuitenkin, jos Delphi -koodi ja C -koodi pitää saada keskustelemaan keskenään, niin yleensä homma kuitenkin hoidetaan näin:

### jokudll.c tai jokudll.cpp:

#ifdef CPP
extern "C" {
#endif

void omafunktio(char * Value) {

}

#ifdef CPP
}
#endif

...

ja sitten delphissä näin:

### jokudllimpu.pas:

unit jokudllimpu;

procedure omafunktio(Value:PChar); cdecl; external 'jokudll.dll';

tämän jälkeen kun kutsut delphissä omafunktio(PChar(St1));

niin se kutsuu jokudll.dll:ssä olevaa C:llä koodattua omafunktio -funktiota välittäen sille St1:String -muuttujan, mutta PChar:ksi muunnettuna.

huomaa: C -koodissa ei ole syytä muuttaa merkkijonoa, varsinkaan sen pituutta !

Ja jos sen arvoakaan muutetaan C-koodissa, olisi Delphissä ennen ko. funktiokutsua suoritettava:

UniqueString(St1);

Tuon UniqueString:n ansiosta C -koodi voi muuttaa muuttujan St1 arvoa, kuitenkin siten, että sen pituus ei muutu.

Jos pituutta on tarpee muuttaa C:llä, silloin pitäisi C:ssä määritellä:

int omafunktio(char * Value);

ja vastaavasti Delphissä:

function omafunktio(Value:PChar):Integer; cdecl; external 'jokudll.dll';

tällöin annetaan C -funktion palauttaa uusi pituus (joka ei saa siltikään ylittää alkuperäistä pituutta!)

ja omafunktio -kutsu delphissä pitäisi tällöin tehdä näin:

UniqueString(St1);
SetLength(St1, omafunktio(PChar(St1)));

Näin siis C:ssä voi muuttaa merkkijonon sisältöä ja/tai lyhentää sitä, mutta EI pidentää.

Delphin String EI siis oikeasti ole PChar, mutta on suunniteltu siten, että sitä voi tietyin rajoituksin kohdella PChar:na, kunhan:

a) merkkijonoa ei muuteta PChar -viittauksen kautta

tai

b) UniqueString -kutsulla varmistetaan, että merkkijonon viitteiden määrä=1, tällöin sisältöä voi muuttaa, pituutta ei.

Pituutta ei siis tule milloinkaan suoraan muuttaa PChar -viittauksen kautta, mutta toki PChar -viittauksen saava funktio voi palauttaa uuden (saman tai lyhyemmän pituuden kuin alkuper. pituus) pituuden, joka sitten Delphillä asetetaan voimaan SetLength -proseduurilla.

Huomaa myös:

St1 := 'abc'#0'def';

nyt:

length(St1) = 7,

mutta:

strlen(PChar(St1)) = 3

!!!

strlen(PChar(St1)) on yleensä sama kuin length(St1), mutta JOS St1 sisältää NULL -merkkejä eli #0 = chr(0) ( basicissa chr$(0) )

niin tällöin strlen ilmoittaa merkkien määrän ennen ensimmäistä null -merkkiä, mutta length merkkijonon koko pituuden null -merkkeineen.

Jos merkkijono voi sisältää NULL -merkkejä, tulee mahd. C -koodille välittää erikseen merkkijonon pituus kokonaislukuna, koska muuten C:ssä oletusarvoisesti ensimmäinen NULL katkaisee merkkijonon, Delphissä taas ei.

Huomaa: monet I/O -aliohjelmat (kuten windows MessageBox ja delphin omakin ShowMessage) tulkitsevat merkkijonon päättyvän NULL -merkkiin.

Näppärä toki koodaa tarvittaessa oman apufunktion, joka esim tekee merkkijonosta kopion siten, että NULL -merkin tilalle tuleekin merkkijono '' ...

Anonyymi
5000

Ilmoita asiaton sisältö

  • Sisältää materiaalia, joka on loukkaavaa, herjaavaa, rasistista, uhkailevaa tai ahdistelevaa.

  • Materiaali sisältää nimiä, yhteystietoja tai muita henkilökohtaisia tietoja. Julkisuuden henkilöistä, julkisissa viroissa toimivista ihmisistä sekä yritysten vastuuhenkilöistä saa keskustella työhön liittyen. Myös yksityiselämään liittyvistä asioista voi keskustella siltä osin, kuin niistä on julkisesti kerrottu.

  • Sisältää lapsille haitallista tai heiltä kiellettyä materiaalia. Seksuaalinen sisältö on sallittua aiheeseen tarkoitetuilla palstoilla, joiden ikäraja on 18 vuotta.

  • Lainvastaista sisältöä voi olla mm. yksityiselämää loukkaavan tiedon levitys, kiihottaminen kansanryhmää vastaan, laiton uhkaaminen, alaikäisiin liittyvä seksuaalinen sisältö/grooming, petokset, identiteettivarkaudet, kunnianloukkaukset ja tekijänoikeusrikkomukset.

  • Sisältö ei liity palstan tai keskusteluketjun aiheeseen.

  • Viesti ei ole suomea tai ruotsia (pl. International Forums), se sisältää mainontaa, se sisältää tekijänoikeuksin suojattua materiaalia, se on massapostitus tai jokin muu syy.

Jaa keskustelu