L'assembleur en ligne x86

PureBasic permet d'inclure toute commande assembleur x86 (y compris les instructions MMX et FPU) directement dans le code source comme dans un vrai source assembleur. Vous pouvez également utiliser directement les variables ou pointeurs avec les instructions assembleur et pouvez intégrer plusieurs commandes assembleur sur une même ligne.

Sous Windows et Linux, PureBasic utilise fasm ( http://flatassembler.net), alors pour plus d'information à propos de la syntaxe, lire le guide fasm.
Sous OS X, PureBasic utilise yasm ( http://yasm.tortall.net/), alors pour plus d'information à propos de la syntaxe, lire le guide yasm.

Pour utiliser l'assembleur en ligne, utiliser les directives du compilateur EnableASM ou DisableASM.

Il est possible d'activer la coloration syntaxique ASM dans l'IDE avec "Activer la coloration des mots clés assembleur" compiler option.

Règles

Vous devez respecter plusieurs règles précises pour inclure de l'assembleur dans du code PureBasic:

- Les variables et les pointeurs doivent être déclarés préalablement à leur utilisation dans un contexte assembleur.
- Concernant les étiquettes (labels): Les labels référencés en assembleur sont toujours en minuscule. Par exemple, le label 'ETIquette:' sera transformé en 'l_etiquette' dans le code assembleur.
Lorsque vous faites référence à un label purebasic dans le corps du programme (en dehors des procedures et des modules) avec des fonctions assembleurs, vous devez précéder son nom par un L minuscule et d'un caractère de soulignement comme ceci 'l_'.
Si le label est défini dans une procédure, alors son préfixe est 'll_nomprocedure_', en minuscules (ll comme local label) mais il n'est accessible qu'à l'intérieur de la procédure.
Pour accéder à un label dans un module avec des fonctions assembleurs, vous devez ajouter devant le label le préfixe 'nomdumodule.l_nomprocedure_' écrit tout en minuscule.
Et enfin un label défini dans une procédure elle-même dans un module s'écrira 'nomdumodule.ll_nomprocedure_' - Pour info, les listes commencent par 't_nomlist', les map par 'm_nommap' et les tableaux par 'a_nomtableau' est toujours en minuscule.

Exemple

  DeclareModule MonModule
    LabelDeclareModule: ;Son nom assembleur est monmodule.l_labeldeclaremodule:
    Declare Init()
  EndDeclareModule

  Module MonModule
    Procedure Init() 
      LabelModuleProcedure: ; Son nom assembleur est monmodule.ll_init_labelmoduleprocedure: 
      Debug "InitFerrari()"  
    EndProcedure
  
    LabelModule1: ;Son nom assembleur est monmodule.l_labelmodule1:
  EndModule

   Procedure Test (*Pointer, Variable)
    TokiSTART:  ;Son nom assembleur est ll_test_tokistart:
  
    ! MOV dword [p.p_Pointer], 20
    ! MOV dword [p.v_Variable], 30
    Debug *Pointer  ;Son nom assembleur est p.p_Pointer
    Debug Variable  ;Son nom assembleur est p.v_Variable
  EndProcedure
  
  VAR=1                       ;Son nom assembleur est v_VAR
  *Pointt=AllocateMemory(10)  ;Son nom assembleur est p_Pointt
  
  MonModule::Init()
  Test(0,0) 
  
  Label1: ;Son nom assembleur est l_label1:  
  !jmp l_labelend ; Une instruction en assembler doit suivre les règles ci-dessus. Ici c'est l_nomelabel
  ;...
  LabelEnd: ;Son nom assembleur est l_labelend:
- Les erreurs dans une section asm ne sont pas reportées par PureBasic mais par Fasm. Vérifiez votre code si une telle erreur survient.
- Avec l'assembleur en ligne activé, vous ne pouvez pas utiliser les mots clés ASM pour les étiquettes (label).
- Sur les processeurs x86, les registres volatiles sont: eax, ecx, edx, xmm0, xmm1, xmm2 et xmm3. Tous les autres doivent être préservés.
- Sur les processeurs x64, les registres volatiles sont: rax, rcx, rdx, r8, r9, xmm0, xmm1, xmm2 et xmm3. Tous les autres doivent être préservés.
- Windows: un fichier aide-ASM peut être téléchargé ici. Si vous déplacez le fichier 'ASM.HLP' dans le dossier 'Help/' de PureBasic, vous aurez accès à l'aide sur les mots clés assembleur en appuyant sur F1. (Note: Ne fonctionne que si l'option 'assembleur en ligne' est activé).

Quand on utilise l'assembleur dans une procédure, il est utile de connaître les points suivants:

- Pour renvoyer directement la valeur du registre 'eax' (ou 'rax' sur x64) comme valeur de retour, il suffit d'utiliser ProcedureReturn, sans paramètre. Le contenu du registre 'eax' (ou 'rax' sur x64) restera inchangé et sera utilisé comme valeur de retour.

Exemple

  Procedure.l MonTest()
    !MOV eax, 45
    ProcedureReturn  ; La valeur de retour sera 45
  EndProcedure
  Debug MonTest() 
- Les variables locales en PureBasic sont directement indexées par rapport au registre de la pile (ESP) ce qui implique qu'un changement de la valeur de ce registre par une instruction assembleur (tel que PUSH, POP etc..) implique que la référence vers la variable ne sera plus correcte.

- Il est possible de passer directement une ligne complète à l'assembleur sans aucune modification en utilisant le caractère '!' en début de ligne. Ceci permet d'avoir un accès total aux fonctionnalités de l'assembleur. Pour faciliter l'accès aux variables locales, une notation a été mise en place: 'p.v_NomVariable' pour une variable standard et 'p.p_NomPointeur' pour un pointeur.

Exemple

  Procedure Test(*Pointer, Variable)
    ! MOV dword [p.p_Pointer], 20
    ! MOV dword [p.v_Variable], 30
    Debug *Pointer
    Debug Variable
  EndProcedure
  
  Test(0, 0)

Exemple

AsmInline.pb