Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

APPELER UNE API EN ASM AVEC DELPHI


Information sur la source

Description

Ce code permet d'appeler n'importe quelle api (stdCall) sans avoir à connaitre ses paramètres. Il n'est pas si compliqué. Il y a encore quelques problèmes à résoudre comme comment faire fonctionner iFlags pour la msgbox ... mais c ma première source en ASM.
 

Source

  • //FAIT PAR DEADLYPREDATOR LE 3 MAI 2005 - À UTILISER À VOS RISQUES
  • unit frmMain;
  • interface
  • uses
  • Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  • Dialogs, StdCtrls;
  • type
  • TForm1 = class(TForm)
  • txtGetTickCount: TEdit;
  • btnGetTickCount: TButton;
  • Label1: TLabel;
  • GroupBox1: TGroupBox;
  • btnMsgBox: TButton;
  • Label2: TLabel;
  • txtMsg: TEdit;
  • Label3: TLabel;
  • txtTitle: TEdit;
  • optMsgInfo: TRadioButton;
  • optMsgAlerte: TRadioButton;
  • chkMsgYesNo: TCheckBox;
  • lMsgRep: TLabel;
  • optMsgCritique: TRadioButton;
  • optMsgNormal: TRadioButton;
  • procedure FormCreate(Sender: TObject);
  • procedure FormDestroy(Sender: TObject);
  • procedure btnGetTickCountClick(Sender: TObject);
  • procedure btnMsgBoxClick(Sender: TObject);
  • private
  • { Private declarations }
  • public
  • { Public declarations }
  • end;
  • var
  • Form1: TForm1;
  • // Variables qui vont contenir le handle des DLLs, jusqu'à leur déchargement
  • iKernel32,iUser32: Cardinal;
  • // -----
  • // Variables qui vont contenir l'adresse des APIs, jusqu'au déchargement des DLLs
  • pGetTickCount,pMessageBox: Pointer;
  • // -----
  • implementation
  • {$R *.dfm}
  • procedure TForm1.FormCreate(Sender: TObject);
  • begin
  • //Chargement des DLLs
  • iKernel32:=LoadLibrary('Kernel32.dll');// La variable stoke le handle de la DLL, on va en avoir besoin
  • iUser32:=LoadLibrary('User32.dll'); // ^^^^
  • //Recherche de l'adresse des APIs
  • pGetTickCount:=GetProcAddress(iKernel32,'GetTickCount');// Voilà à quoi sert le handle. Si l'API n'est pas trouvée, le pointer est nul (=nil)
  • pMessageBox:=GetProcAddress(iUser32,'MessageBoxA'); // ^^^^
  • end;
  • procedure TForm1.FormDestroy(Sender: TObject);
  • begin
  • //Déchargement des DLLs
  • FreeLibrary(iKernel32);// Libération de la dll
  • FreeLibrary(iUser32); // ^^^^
  • end;
  • procedure TForm1.btnGetTickCountClick(Sender: TObject);
  • var
  • iRetVal: Cardinal;//Pour plus tard
  • begin
  • {Appel de GetTickCount
  • Dans delphi : function GetTickCount () : Integer; stdcall; external 'kernel32' name 'GetTickCount'
  • Bon, on a la DLL chargée et l'adresse de l'API voulue, le plus difficile reste à venir ...
  • Je ne vous ferez pas un cours ASM 101 car moi même je n'y connait RIEN presque
  • Vous ne comprenez ce que vous écrivez, pas grave.
  • }
  • asm//Dit à Delphi qu'on commence un bloc d'instructions ASM
  • CALL pGetTickCount //On appel le pointeur de l'API, obtenu par GetProcAddress
  • MOV iRetVal,EAX //En gros, on met le résultat de l'API dans la variable Delphi "iRetVal", pour des types complexes, cela sera peut-être un pointeur
  • end;//Dit à Delphi que le bloc d'instructions ASM est fini
  • //Maintenant, on a le résultat de GetTickCount. Sauf que c'était trop facile.
  • //GetTickCount ne requiert aucun paramètre. Donc pas vraiment de problèmes
  • txtGetTickCount.Text:=IntToStr(iRetVal);//Conversion en string et affichage dans la textbox
  • end;
  • procedure TForm1.btnMsgBoxClick(Sender: TObject);
  • var
  • iRetVal: Cardinal;//Pour plus tard
  • iFlags: Cardinal;//Options d'apparence de la msgbox
  • sTexte, sTitre:PChar;//Pour plus tard
  • begin
  • lMsgRep.Caption:='';//on efface la réponse ...
  • if(optMsgAlerte.Checked=true) then iFlags:=MB_ICONEXCLAMATION;//préparation des paramètres de l'apparence de la msgbox
  • if(optMsgCritique.Checked=true) then iFlags:=MB_ICONASTERISK; //^^^^
  • if(optMsgInfo.Checked=true) then iFlags:=MB_ICONQUESTION; //^^^^
  • if(chkMsgYesNo.Checked=true) then iFlags:=+MB_YESNO; //^^^^
  • sTexte:=PChar(txtMsg.Text); //Il faut convertir le texte en pchar avant
  • sTitre:=PChar(txtTitle.Text); //^^^^
  • {Appel de MessageBoxA
  • Dans delphi : function GetTickCount () : Integer; stdcall; external 'kernel32' name 'GetTickCount'
  • Maintenant, c'est une fonction plus complexe avec des paramètres.
  • On place chaque paramètre avec PUSH
  • ATTENTION!!!! LES PARAMÈTRES DOIVENT ÊTRE DONNÉ À L'INVERSE, DE DROITE À GAUCHE!!!
  • SI PAR EXEMPLE function x(a;b;c;d)
  • on push dans cette ordre d, c, b, a
  • Cette méthode ne permet que de fonctionner avec les api qui utilise la convention d'appel appelée stdcall, soit toutes les APIs de windows et la grande majoritée des autres
  • }
  • asm//Dit à Delphi qu'on commence un bloc d'instructions ASM
  • PUSH 0//Tout les paramètres pusher dans l'ordre inverse
  • PUSH sTitre//^^^^
  • PUSH sTexte//^^^^
  • PUSH 0//iFlags//^^^^ --> iFlags ne fonctionne pas encore, je ne sais pas pourquoi mais la valeur doit être convertie avant mais en quoi?
  • CALL pMessageBox //On appel le pointeur de l'API, obtenu par GetProcAddress
  • MOV iRetVal,EAX //En gros, on met le résultat de l'API dans la variable Delphi "iRetVal", pour des types complexes, cela sera peut-être un pointeur
  • end;//Dit à Delphi que le bloc d'instructions ASM est fini
  • if(iRetVal=7) then lMsgRep.Caption:='vous avez répondu non';//^va fonctionner quand iFlag va fonctionner
  • if(iRetVal=6) then lMsgRep.Caption:='vous avez répondu oui';//^^^^
  • end;
  • end.
//FAIT PAR DEADLYPREDATOR LE 3 MAI 2005 - À UTILISER À VOS RISQUES
unit frmMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    txtGetTickCount: TEdit;
    btnGetTickCount: TButton;
    Label1: TLabel;
    GroupBox1: TGroupBox;
    btnMsgBox: TButton;
    Label2: TLabel;
    txtMsg: TEdit;
    Label3: TLabel;
    txtTitle: TEdit;
    optMsgInfo: TRadioButton;
    optMsgAlerte: TRadioButton;
    chkMsgYesNo: TCheckBox;
    lMsgRep: TLabel;
    optMsgCritique: TRadioButton;
    optMsgNormal: TRadioButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnGetTickCountClick(Sender: TObject);
    procedure btnMsgBoxClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

// Variables qui vont contenir le handle des DLLs, jusqu'à leur déchargement
iKernel32,iUser32: Cardinal;
// -----

// Variables qui vont contenir l'adresse des APIs, jusqu'au déchargement des DLLs
pGetTickCount,pMessageBox: Pointer;
// -----

implementation

{$R *.dfm}


procedure TForm1.FormCreate(Sender: TObject);
begin
//Chargement des DLLs
iKernel32:=LoadLibrary('Kernel32.dll');// La variable stoke le handle de la DLL, on va en avoir besoin
iUser32:=LoadLibrary('User32.dll');    // ^^^^
//Recherche de l'adresse des APIs
pGetTickCount:=GetProcAddress(iKernel32,'GetTickCount');// Voilà à quoi sert le handle. Si l'API n'est pas trouvée, le pointer est nul (=nil)
pMessageBox:=GetProcAddress(iUser32,'MessageBoxA');     // ^^^^
end;


procedure TForm1.FormDestroy(Sender: TObject);
begin
//Déchargement des DLLs
FreeLibrary(iKernel32);// Libération de la dll
FreeLibrary(iUser32);  // ^^^^
end;

procedure TForm1.btnGetTickCountClick(Sender: TObject);
var
iRetVal: Cardinal;//Pour plus tard
begin
{Appel de GetTickCount

Dans delphi : function GetTickCount () : Integer; stdcall; external 'kernel32' name 'GetTickCount'

Bon, on a la DLL chargée et l'adresse de l'API voulue, le plus difficile reste à venir ...
Je ne vous ferez pas un cours ASM 101 car moi même je n'y connait RIEN presque
Vous ne comprenez ce que vous écrivez, pas grave.
}
  asm//Dit à Delphi qu'on commence un bloc d'instructions ASM

  CALL pGetTickCount //On appel le pointeur de l'API, obtenu par GetProcAddress
  MOV iRetVal,EAX //En gros, on met le résultat de l'API dans la variable Delphi "iRetVal", pour des types complexes, cela sera peut-être un pointeur

  end;//Dit à Delphi que le bloc d'instructions ASM est fini

//Maintenant, on a le résultat de GetTickCount. Sauf que c'était trop facile.
//GetTickCount ne requiert aucun paramètre. Donc pas vraiment de problèmes
txtGetTickCount.Text:=IntToStr(iRetVal);//Conversion en string et affichage dans la textbox

end;

procedure TForm1.btnMsgBoxClick(Sender: TObject);
var
iRetVal: Cardinal;//Pour plus tard
iFlags: Cardinal;//Options d'apparence de la msgbox
sTexte, sTitre:PChar;//Pour plus tard
begin
lMsgRep.Caption:='';//on efface la réponse ...
if(optMsgAlerte.Checked=true) then iFlags:=MB_ICONEXCLAMATION;//préparation des paramètres de l'apparence de la msgbox
if(optMsgCritique.Checked=true) then iFlags:=MB_ICONASTERISK; //^^^^
if(optMsgInfo.Checked=true) then iFlags:=MB_ICONQUESTION;     //^^^^
if(chkMsgYesNo.Checked=true) then iFlags:=+MB_YESNO;          //^^^^

sTexte:=PChar(txtMsg.Text);    //Il faut convertir le texte en pchar avant
sTitre:=PChar(txtTitle.Text);  //^^^^

{Appel de MessageBoxA

Dans delphi : function GetTickCount () : Integer; stdcall; external 'kernel32' name 'GetTickCount'

Maintenant, c'est une fonction plus complexe avec des paramètres.
On place chaque paramètre avec PUSH
ATTENTION!!!! LES PARAMÈTRES DOIVENT ÊTRE DONNÉ À L'INVERSE, DE DROITE À GAUCHE!!!
SI PAR EXEMPLE function x(a;b;c;d)
on push dans cette ordre d, c, b, a
Cette méthode ne permet que de fonctionner avec les api qui utilise la convention d'appel appelée stdcall, soit toutes les APIs de windows et la grande majoritée des autres
}
  asm//Dit à Delphi qu'on commence un bloc d'instructions ASM

  PUSH 0//Tout les paramètres pusher dans l'ordre inverse
  PUSH sTitre//^^^^
  PUSH sTexte//^^^^
  PUSH 0//iFlags//^^^^ --> iFlags ne fonctionne pas encore, je ne sais pas pourquoi mais la valeur doit être convertie avant mais en quoi?

  CALL pMessageBox //On appel le pointeur de l'API, obtenu par GetProcAddress
  MOV iRetVal,EAX //En gros, on met le résultat de l'API dans la variable Delphi "iRetVal", pour des types complexes, cela sera peut-être un pointeur

  end;//Dit à Delphi que le bloc d'instructions ASM est fini

if(iRetVal=7) then lMsgRep.Caption:='vous avez répondu non';//^va fonctionner quand iFlag va fonctionner
if(iRetVal=6) then lMsgRep.Caption:='vous avez répondu oui';//^^^^
end;

end.

Conclusion

Merci. J'aimerais en faire une API qu'on pourrais utiliser pour appeler d'autres API. Ça pourrait servir.
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  •   asm api
    • frmMain.~ddpTélécharger ce fichier [Réservé aux membres club]51 octets
    • frmMain.~dfmTélécharger ce fichier [Réservé aux membres club]2 804 octets
    • frmMain.~pasTélécharger ce fichier [Réservé aux membres club]5 004 octets
    • frmMain.dcuTélécharger ce fichier [Réservé aux membres club]5 943 octets
    • frmMain.ddpTélécharger ce fichier [Réservé aux membres club]51 octets
    • frmMain.dfmTélécharger ce fichier [Réservé aux membres club]2 804 octets
    • frmMain.pasTélécharger ce fichier [Réservé aux membres club]Voir ce fichier5 004 octets
    • prjAPI.cfgTélécharger ce fichier [Réservé aux membres club]Voir ce fichier444 octets
    • prjAPI.dofTélécharger ce fichier [Réservé aux membres club]Voir ce fichier2 015 octets
    • prjAPI.dprTélécharger ce fichier [Réservé aux membres club]Voir ce fichier190 octets
    • prjAPI.exeTélécharger ce fichier [Réservé aux membres club]397 312 octets
    • prjAPI.resTélécharger ce fichier [Réservé aux membres club]876 octets

Télécharger le zip

Commentaires et avis

signaler à un administrateur
Commentaire de grandvizir le 31/08/2006 10:09:24

Salut DeadlyPredator. J'ai une petite remarque.

Sachant que Kernel et compagnie sont déjà chargés automatiquement par l'application, je ne pense pas qu'il soit nécessaire de les recharger. Autant utiliser directement l'opérateur Arobase pour récupérer l'adresse de la procédure désirée.

Exemple:

program Project1;
uses Windows, SysUtils, Dialogs;
{$R *.res}

var TickAsm, TickPascal : integer;
    Address             : Pointer;
begin
//APPEL EN ASSEMBLEUR
  Address:=@GetTickCount;
  asm
    CALL  Address
    MOV   TickAsm, EAX
  end;

//APPEL EN PASCAL
  TickPascal:=GetTickCount;

//LES DEUX RESULTATS SONT PAREILS
  ShowMessage(Format('%d = %d',[TickAsm, TickPascal]));
end.

Cela dit le code est bon. C'est juste une autre manière de faire.

signaler à un administrateur
Commentaire de sarko le 14/09/2007 14:31:48

Bonjour ,
a propos du non fonctionnement de iflags ,cette
variable doit etre sur le premier push.
Le 4eme push serait le numero de fenetre /??
N'oublie pas le probleme des icones et attention aux codes
interdits .
Bon courage

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version


HTC G1

Entre 449€ et 449€


Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,218 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.