Article     Discussion     Modifier     Historique     Forums     Salon IRC

Tutorial 7 : Les instructions asm les plus courantes et le corps d'un programme FASM pour les librairies

Un article de Games Creators Network.


PureBasic

<< Précédent | Sommaire | Suivant >>



PATIENCE : IL MANQUE DES IMAGES ET LA MISE EN PAGE EST EN COURS ...

Tutorial 7 : Les instructions asm les plus courantes et le corps d'un programme FASM pour les librairies

Les instructions asm les plus courantes

A) Instruction MOV

(page 498 du manuel d'Intel: Jeu d'instructions volume 2A (A-M))

C'est certainement l'instruction la plus utilisée ou une des plus utilisée.

L'instruction MOV permet de déplacer, d'affecter des valeurs à un registre, une mémoire. MOV est composé d'une opérande source et d'une opérande de destination. L'opérande source est copiée dans l'opérante destination. La valeur copiée dépend du type de la source. Le format est le suivant

MOV Destination, source

L'opérande destination de cette instruction peut être :

  • Un registre (8, 16 ou 32 bits)
  • Une mémoire (8,16 ou 32 bits)
  • Un registre de segment (16 bits)

L'opérande source de cette instruction peut être :

  • Un registre (8, 16 ou 32 bits)
  • Une mémoire (8,16 ou 32 bits)
  • Un registre de segment (16 bits)
  • Une valeur immédiate (un nombre)

Toutes les possibilités sont données dans la doc Intel.

Voici quelques exemples :

MOV EAX, 10 Charge le registre EAX avec la valeur décimale 10, format 32 bits puisque EAX est un registre 32 bits
MOV 10, EAX Cette instruction est illégale car il n'est pas possible d'attribuer la valeur d'un registre à une valeur, ça n'a pas de sens.
MOV AX, 7 Charge le registre AX avec la valeur décimale 7, format 16 bits puisque AX est un registre 16 bits
MOV BL, 3 Charge le registre BL avec la valeur décimale 3, format 8 bits puisque BL est un registre 8 bits
MOV EDX, EAX Charge le registre EDX avec la valeur contenue dans le registre EAX format 32 bits puisque EDX et EAX sont des registres 32 bits
MOV EDX, AX Cette instruction est illégale car la destination et la source n'ont pas la même taille (EDX = 32 bits et AX = 16 bits)
MOV DX, SI Charge le registre DX avec la valeur contenue dans le registre SI format 16 bits puisque DX et SI sont des registres 16 bits
MOV dword [10010], EAX Copie le contenu du registre EAX à l'adresse 10010. La valeur de EAX est une valeur 32 bits On peut très bien écrire cette instruction comme ceci MOV [10010], EAX car la source (EAX) est une valeur 32 bits.

FASM va interpréter cette 2e écriture sans problème. Ce sont les crochets qui indiquent que c'est une adresse.
Par contre, MOV byte [10010], EAX est une instruction illégale

MOV byte [10010], DL Copie le contenu du registre DL à l'adresse 10010.

La valeur de DL est une valeur 8 bits On peut très bien écrire cette instruction comme ceci MOV [10010], DL
car la source (DL) est une valeur 8 bits.
FASM va interpréter cette 2e écriture sans problème. Ce sont les crochets qui indiquent que c'est une adresse

MOV dword [10010], [2048]

Cette instruction est illégale car la destination et la source sont 2 emplacements mémoire de 32 bits.
Il n'est pas possible de faire cette opération directement. Il faut passer par un registre.

Voici comment
PUSH EAX ; on sauvegarde EAX (si besoin)
MOV EAX, [2048] ; on charge EAX
MOV dword [10010], EAX ; on copie EAX à l'adresse 10010
POP EAX ; on récupère la valeur initiale de EAX (si besoin)

Voici une autre variante avec les instructions PUSH et POP
PUSH dword [2048] ; on met sur la pile le contenu de l'adresse
POP dword [10010] ; on copie le dernier élément empilé à l'adresse 10010 ici pas besoin de sauvegarder le registre EAX

L'instruction MOV ne peut pas être utilisée pour charger le registre de segment CS.
La doc Intel indique aussi pour les registres de segments :
Si l'opérande de destination est un registre de segment (DS, ES, FS, GS ou SS),
l'opérande source doit être un sélecteur de segment valide.

L'instruction MOV telle que décrite ci-dessus ne modifie aucun drapeau (registre EFLAGS).

L'instruction MOV permet aussi de charger un registre de contrôle dans un registre général 32 bits et réciproquement.
Elle permet aussi de charger un registre de debbugage dans un registre général 32 bits et réciproquement.
Cette utilisation se fait dans un cadre particulier et modifie certains drapeaux.

B) Instruction MOVSX

(page 559 du manuel d'Intel: Jeu d'instructions volume 2A (A-M))

L'instruction MOVSX copie l'opérande source (mémoire ou registre) dans l'opérante destination (registre).
La valeur source est soit une opérande 8 bits soit 16 bits.
MOVSX va charger l'opérante 8 bits dans un registre 16 ou 32 bits en conservant le signe ou
va charger l'opérande 16 bits dans un registre 32 bits en conservant le signe.

Les formats sont les suivants (r pour registre et m pour mémoire, le nombre qui suit indique le nombre de bits)

MOVSX r16, r/m8 charge un registre 16 bits avec extension de signe à partir d'un registre/mémoire 8 bits
MOVSX r32, r/m8 charge un registre 32 bits avec extension de signe à partir d'un registre/mémoire 8 bits
MOVSX r32, r/m16 charge un registre 32 bits avec extension de signe à partir d'un registre/mémoire 16 bits

Par exemple si on a le registre 8 bits BL vaut -5,
l'instruction MOVSX EAX, BL va charger eax avec la valeur -5 mais sur 32 bits.

Voici quelques exemples
MOVSX EAX, BL ; charge EAX avec la valeur du reg 8 bits BL
MOVSX EAX, byte [10010] ; charge EAX avec la valeur 8 bits située à l'adresse mémoire 10010
MOVSX EAX, word [10010] ; charge EAX avec la valeur 16 bits située à l'adresse mémoire 10010

L'instruction MOVSX ne modifie aucun drapeau (registre EFLAGS).

C) Instruction MOVZX

(page 564 du manuel d'Intel: Jeu d'instructions volume 2A (A-M))

L'instruction MOVZX copie l'opérande source (mémoire ou registre) dans l'opérante destination (registre) et les bits de l'opérande destination non affectés par l'opération seront mis à 0. Le bit de signe signe est mis à 0.

Les formats pour MOVZX sont les suivants:

MOVZX r16, r/m8 charge un registre 16 bits avec mise à zéro des bits b8 à b15 à partir d'un registre/mémoire 8 bits MOVZX r32, r/m8 charge un registre 32 bits avec mise à zéro des bits b8 à b31 à partir d'un registre/mémoire 8 bits MOVZX r32, r/m16 charge un registre 32 bits avec mise à zéro des bits b16 à b31 à partir d'un registre/mémoire 16 bits

Par exemple si on a le registre 8 bit BL valant 5, l'instruction MOVZX EAX, BL va charger EAX avec la valeur 5 mais sur 32 bits.

Par contre si BL vaut -5, l'instruction MOVZX EAX, BL va charger EAX avec la valeur 251 sur 32 bits.

Pourquoi ? Voici -5 sur 8 bit 11111011

Maintenant on prend cette valeur et on ajoute 24 zéro sur la gauche pour avoir une représentation sur 32 bits

00000000000000000000000011111011

On voit tout de suite que le bit de signe est à 0, c'est donc un nombre positif!

Ce nombre vaut 251. Il faut bien faire attention à son utilisation.

Voici quelques exemples

MOVZX EAX, BL  ; charge EAX avec la valeur du reg 8 bits BL MOVZX EAX, byte [10010]  ; charge EAX avec la valeur 8 bits située à l'adresse mémoire 10010 MOVZX EAX, word [10010]  ; charge EAX avec la valeur 16 bits située à l'adresse mémoire 10010

L'instruction MOVZX ne modifie aucun drapeau (registre EFLAGS).

Il existe aussi les instructions MOVS, MOVSB, MOVSW et MOVSD qui permettent de déplacer des octets, des mots de 16 bits et de 32 bits en utilisant les registres d'index SI et DI. Ces déplacements s'effectuent entre mémoires. (page 552 du manuel d'Intel: Jeu d'instructions volume 2A (A-M))

D) Instructions DEC et INC

(page 232 du manuel d'Intel: Jeu d'instructions volume 2A (A-M)) (page 394 du manuel d'Intel: Jeu d'instructions volume 2A (A-M))

DEC décrémente de 1 (soustrait 1) à l'opérande de destination INC incrémente de 1 (ajoute 1) à l'opérande de destination

L'opérante peut être un registre de 8, 16 ou 32 bits ou une mémoire 8, 16 ou 32 bits.

Exemple :

MOV EAX, 10  ; EAX vaut 10 DEC EAX  ; EAX est décrémenté de 1, --> EAX vaut 9 INC AX  ; AX est incrément de 1 , --> EAX vaut 10

DEC byte [ECX]  ; la valeur (octet) située en mémoire dont l'adresse est contenue dans ECX est décrémenté de 1 INC dword [ESI]  ; la valeur (32 bits) située en mémoire dont l'adresse est contenue dans ESI est incrémenté de 1

Les instructions INC et DEC modifient les drapeaux suivants (registre EFLAGS).

OF, SF, ZF, AF, PF en fonction du résultat. On peut donc utiliser les instructions de tests après ces opérations. CF n'est pas affecté. Pour que CF soit affecté, il faut utiliser les instructions suivantes à la place, par exemple avec le registre eax

ADD eax, 1 pour remplacer INC eax
SUB eax, 1 pour remplacer DEC eax

E) Instructions ADD et SUB

(page 62 du manuel d'Intel: Jeu d'instructions volume 2A (A-M)) (page 233 du manuel d'Intel: Jeu d'instructions volume 2B (N-Z))

ADD additionne l'opérande source à l'opérande de destination et stocke le résultat dans l'opérande de destination. SUB soustrait l'opérande source à l'opérande de destination et stocke le résultat dans l'opérande de destination.

ADD destination, source SUB destination, source

L'opérande source peut être un registre, une mémoire ou une valeur immédiate (un nombre). L'opérande de destination peut être un registre, une mémoire. Les opérandes peuvent être au format 8, 16 ou 32 bits.

Deux mémoires ne peuvent être utilisées dans la même instruction. Lorsqu'une valeur immédiate est utilisée, l'instruction utilise ce nombre au format de l'opérande de destination si besoin (16 ou 32 bits) avec extension du signe pour ce nouveau format (c'est transparent pour nous).

Les instructions ADD et SUB modifient les drapeaux suivant (registre EFLAGS).

OF, SF, ZF, AF, PF et CF en fonction du résultat. On peut donc utiliser les instructions de tests après ces opérations.

Le corps d'un programme FASM pour les librairies PureBasic

Le corps d'un programme FASM pour les librairies PureBasic se présente comme ceci.

Tout d'abord, tout comme PB, les commentaires sont supportés et commencent par un point virgule. Tout ce qui suit le ; est considéré comme un commentaire. 1) Le FORMAT

On déclare le format objet utilisé - Microsoft coff 32 bits - (se reporter à la Doc FASM pour de plus amples renseignements) on écrira la ligne suivante telle quelle (page 69 de la doc FASM)

format MS COFF

2) Le nom de la Commande

On déclare ensuite le nom de notre commande, par exemple si on crée une commande en Purebasic :

InsertElement(a, b)

les paramètres n'ont pas d'importance dans la déclaration, ils seront définis dans le fichier descripteur obligatoire qu'il faudra créer (fichier .desc)

Le nom de la commande devra être précédé par PB_

La déclaration de cette commande devient (on utilise la directive Public de FASM pour pouvoir appeler cette commande depuis PB ainsi que dans la librairie)

Public PB_InsertElement

3) Commandes PureBasic

Si on veut utiliser des commandes Pure (par exemple la commande NewList) on utilisera la directive extrn suivi du nom de la commande PB; la commande PB devra être obligatoirement précédée des 3 caractères suivant :

PB_

La commande NewList déclarée devient

extrn PB_NewList

Il en est de même pour les API Windows prédéclarées par PureBasic, par exemple pour l'API InitCommonControls, sauf que la commande commence par

_ au lieu de PB_

Cette API devra être suivi du symbole @ puis d'une valeur indiquant en nombre d'octets le total des paramètres.

Par exemple l'API InitCommonControls n'a aucun paramètre, sa déclaration devient

extrn _InitCommonControls@0

Par exemple l'API SendMessage() est définie comme ceci, avec 4 paramètres de type long SendMessage_(hwnd, uMsg, wParam, lParam),sa déclaration dans le fichier asm sera

extrn _SendMessage@16

le 16 indiquant qu'il y a 4 paramètres de type long (4 octets chacun) C'est également la même chose si on veut utiliser une commande d'une de ses propres librairies ou d'une librairie utilisateur. Par exemple pour utiliser la commande SetListIconGadgetColor() de ma librairie MoreListiconGadgetColor, on déclarera la commande comme ceci

extrn PB_SetListIconGadgetColor

4) Les équivalences et égalités

Dans la plupart des langages assembleur, on définit des équivalences qui permettent de rendre la lecture plus compréhensible car l'assembleur devient vite fastidieux à comprendre en tant que programme. Imaginons que nous utilisions le registre ESI comme variable (temps d'accès très rapide) et que la variable se nomme Valeur

La déclaration d'équivalence utilise la directive equ

Valeur equ esi

Attention, FASM considère Valeur comme différent de valeur, je n'ai pas encore cherché si on peut éviter la différentiation des majuscules/minuscules. Lorsque FASM va convertir le fichier en exe, il remplacera partout le mot Valeur par esi (transparent pour nous)

On peut aussi écrire par exemple

Valeur2 equ 3

idem, FASM remplacera Valeur2 par 3

On peut aussi écrire

Valeur = 2

La directive equ est très intéressante lorsque l'on utilise des mémoires etc. Imaginons que le registre ebp pointe une adresse et à cette adresse on a une valeur que l'on utilisera. On peut écrire

Valeur equ dword [ebp]

puis utiliser par exemple ceci

MOV eax, Valeur

ce qui revient à écrire

MOV eax, dword [ebp]

mais MOV eax, Valeur est plus parlant.

Je l'utilise souvent pour déclarer les constantes, par exemple la constante Windows LVM_SETBKCOLOR vaut $1001 On la déclare comme ceci (idem qu'en Pure pour le format hexa et binaire).

LVM_SETBKCOLOR equ $1001

5) Les variables globales

Les variables globales sont utilisables par toutes les commandes de la librairie mais ne sont pas accessibles depuis le code basic de PureBasic (sauf à utiliser l'asm).

Si on veut pouvoir utiliser des variables globales dans d'autres commandes de la librairie, il faut les déclarer avec la directive Public

Imaginons que l'on veuille utiliser la variable globale 'Compteur' dans toute la librairie Sa déclaration publique devient

Public Compteur

Attention, la déclaration Public ne réserve pas de place pour la variable globale, on verra ça dans quelques lignes. 6) La section programme (les instructions)

On déclare les instructions par la ligne toute faite suivante

section '.text' code readable executable

qui indique à FASM que ce qui va suivre est du code en lecture et exécutable.

Ensuite on met notre étiquette (label) qui permettra au programme de connaître exactement ou se situe le début code. Cette étiquette n'est rien d'autre que le nom de la fonction précédé de PB_ et terminé par :

Pour notre exemple de commande qui se nomme InsertElement(a, b), on a :

Public PB_InsertElement:

et puis ensuite on met les instructions asm. Les étiquettes doivent se terminer par les deux points  : 7) La section des données (chaines utilisables)

Si on utilise des chaînes de caractères prédéfinies ou des Datas à inclure, c'est dans cette section qu'il faut les déclarer.
Je n'ai pas testé mais je pense que l'on peut mettre les data à la suite immédiate des chaînes sans avoir à déclarer une nouvelle section.
Dans les programmes PureBasic, elles sont séparées pour pouvoir aligner les données des chaînes (pas celles des Datas).
Nous verrons dans le prochain tutorial comment aligner les données avec FASM pour Purebasic.
On déclare la section avec la ligne suivante

section '.data' Data readable writeable

Il s'agit d'une section de données que l'on peut lire et écrire (on pourrait essayer de ne la mettre que Readable car avec PB, on ne réutilise pas cet espace pour modifier les chaînes de caractères.

La syntaxe de déclaration d'une chaîne est la suivante :

Chaine1: db "Création de librairies asm pour PureBasic",0

On commence par une étiquette (ici Chaine1:) qui permettra l'accès à l'adresse de la chaîne,
puis on écrit db qui est une directive FASM qui indique que la donnée est sur un octet (b comme byte), le d de db indique que la valeur est connue lors de la compilation, on aura bien la chaîne qui sera inscrite dans le fichier exécutable.
Ensuite on commence par ouvrir les guillemets et on écrit la chaîne puis, on referme les guillemets qui indiquent que la chaîne est terminée. Ensuite, une virgule pour séparer les données et enfin le 0 de fin de chaîne toujours sur 1 octet puisqu'on utilise la directive db.
Si on veut mettre plusieurs chaînes, on met en suivant les chaînes (une chaîne par ligne)

Chaine1: db "Création de librairies asm pour PureBasic",0 Chaine2: db "avec PureBasic V 3.92",0 Chaine3: db "et FASM...",0

Les directives utilisables avec des valeurs connues à la compilation:

db 1 octet dw 2 octets = 1 word = 16 bits dd 4 octets = 1 dword = 1 Long = 32 bits dp, df 6 octets = 48 bits dq 8 octets = 64 bits dt 10 octets = 80 bits

8) La section des variables globales

Même principe que pour les chaînes sauf que pour les variables, les valeurs ne sont pas connues à la compilation.
La première de la directive devient r au lieu de d (r comme réservé)
La section des variables globales est déclarées comme ceci:

section '.bss' readable writeable

Le nom des variables globales Purebasic (sauf les listes chaînées) commencent par v_. Pour nos libs, on est pas obligé de faire pareil. On commence par écrire le nom de la variable puis la directive en fonction de la longueur puis ensuite un 1.

Exemple :

section '.bss' readable writeable

BoutonDemarrerIcone rd 1 BoutonRecommencerIcone rd 1 Brush rd 1

9) La section des Data

C'est le même principe qu'au paragraphe 7

La déclaration

section '.data' Data readable writeable

et ensuite les valeurs séparables par une virgule (on peut mettre une étiquette ou on veut en début de ligne pour pouvoir récupérer les Datas)

Exemple pour des valeurs numériques

Debut: dd 65536,269484038,65536,57147416,6684672,538968064

                dd 65536,212336664,63832064,808452096,65536,480772120

Suivant: db 36,26,6,0,66,53

et pour des Datas alphanumériques

   db "MOV",0,"AAA",0,"AAD",0,"AAM",0,"AAS",0,"ADC",0,"ADD",0,"AND",0
   db "CALL",0,"CBW",0,"CLC",0,"CLD",0,"CLI",0,"CMC",0,"CMP",0,"CMPSB",0

Pour pouvoir utiliser ces Datas, il faut connaître le type (byte, long, string) qui détermine la manière dont on va lire ces Datas. Pour les chaines, il suffit d'ajouter à l'adresse de début, la longueur de la chaine + 1 (0 de fin de chaine sur 1 octet)

Voilà, on a vu le corps d'un programme FASM pour Pure. Nous verrons dans un prochain tut l'alignement des données pour les sections de données et variables et la macro correspondante et une ou 2 macros FASM simples.

Voici de 3 exemples pour récapituler (extrait de mes libraires)

 format MS COFF
 Public PB_StatusBarFieldWidth

 ; StatusBarFieldWidth(StatusBarID, Champ)
 ; retourne la largeur du champ de la statusBar
 ; identifiée par StatusBarID
 ; Field identifie le champ concerné

 ; --------------------------------------
 ;   Libs externes/Extern Libs
 ; --------------------------------------

 extrn _SendMessageA@16
 extrn PB_StatusBarBorderSize

 ; --------------------------------------
 ;            équivalence
 ; --------------------------------------

 Decalage = (Fin_Decalage-DebutFin_Decalage)*4
 LocalVar = 16 ; nombres d'octets réservés sur la pile

 ; --------------------------------------
 ;      Paramètres d'entrée
 ; --------------------------------------

 Champ equ esp+Decalage+LocalVar+8
 StatusBarID equ esp+Decalage+LocalVar+4

 ; --------------------------------------
 ;         Variables locales
 ; --------------------------------------

 ; Value.RECT
 Value.bottom equ esp + 12
 Value.right equ esp + 8
 Value.top equ esp + 4
 Value.left equ esp

 ; --------------------------------------
 ;            Section code
 ; --------------------------------------

 section '.text' code readable executable

 PB_StatusBarFieldWidth:

 DebutFin_Decalage:
 PUSH ebx
 PUSH ecx
 Fin_Decalage:

 ADD esp, -LocalVar
 LEA edx, [Value.left]
 PUSH edx
 PUSH dword [Champ+4]          ; Champ
 PUSH dword 1034                   ; #SB_GETRECT
 PUSH dword [StatusBarID+12] ; StatusBarID
 CALL _SendMessageA@16
 TEST eax, eax
 JZ _Erreur

 ; Récupération de la largeur du champ Value\right - Value\left
 MOV eax, dword [Value.right]
 SUB eax, dword [Value.left]
 JMP _Retour

 _Erreur:
 DEC eax

 _Retour:
 ADD esp, LocalVar
 POP ecx
 POP ebx
 RET 8

Autre exemple :

 format MS COFF
 public PB_StatusBarHeight

 ; --------------------------------------
 ;   Libs externes/Extern Libs
 ; --------------------------------------

 extrn _SendMessageA@16
 extrn PB_StatusBarBorderSize ; commande de la même librairie

 ; --------------------------------------
 ;            équivalence
 ; --------------------------------------

 Decalage = (Fin_Decalage-DebutFin_Decalage)*4
 LocalVar = 28 ; nombres d'octets réservés sur la pile

 PB_BorderV equ dword 1

 ; --------------------------------------
 ;       Paramètres d'entrée
 ; --------------------------------------

 StatusBarID equ dword [esp+Decalage+LocalVar+4]

 ; --------------------------------------
 ;         Variables locales
 ; --------------------------------------

 ; Value.RECT
 Value.bottom    equ esp + 24
 Value.right        equ  esp + 20
 Value.top          equ esp + 16
 Value.left           equ esp + 12

 BordureInterRectangle   equ esp + 8
 BordureVerticale           equ esp + 4
 BordureHorizontale       equ esp

 ; --------------------------------------
 ;            Section code
 ; --------------------------------------

 section '.text' code readable executable

 PB_StatusBarHeight:

 DebutFin_Decalage:
 PUSH ebx
 PUSH ecx
 Fin_Decalage:

 ADD esp, -LocalVar
 MOV edx, StatusBarID
 LEA eax,[Value.left]
 PUSH eax              ; adresse de BordureHorizontale
 PUSH dword 0
 PUSH dword 1034 ; SB_GETRECT
 PUSH edx              ; StatusBarID
 CALL _SendMessageA@16
 TEST eax, eax
 JZ _Erreur

 ; Récupération de la hauteur et de la largeur de la StatusBar
 MOV edx, StatusBarID
 PUSH PB_BorderV
 PUSH edx ; StatusBarID
 CALL PB_StatusBarBorderSize
 CMP eax, -1
 JZ _Erreur

 ; retourne Value\bottom - Value\top + BordureVerticale
 ; ici eax = BordureVerticale
 MOV edx, [Value.bottom]
 SUB edx, [Value.top]
 ADD eax, edx
 JMP _Retour

 _Erreur:
 MOV eax, -1         ; retourne -1 en cas d'erreur

 _Retour:
 ADD esp, LocalVar
 POP ecx
 POP ebx
 RET 4

Autre exemple :

 format MS COFF

 ; --------------------------------------
 ;     Fonctions externes
 ; --------------------------------------

 extrn PB_NewList
 extrn _InitCommonControls@0

 ; --------------------------------------
 ;       Variables globales
 ; --------------------------------------

 Public t_ElementHeader
 Public e_ElementHeader
 Public t_ColorieHeader
 Public e_ColorieHeader
 Public t_ColonneVerrouiller
 Public e_ColonneVerrouiller
 Public WindProc_Origine_

 Public _v_WindProc_Origine
 Public t_CouleurItem
 Public e_CouleurItem

 ; --------------------------------------
 ;     Macro alignement
 ; --------------------------------------

 macro bssalign value { rb (value-1) - ($-_VarSection + value-1) mod value }
 include 'Macros.inc'


 Public PB_InitListIconGadget

 section '.text' code readable executable


 PB_InitListIconGadget:

 PUSH ebp
 PUSH ebx
 PUSH ecx

 CALL _InitCommonControls@0

 ;========================================================================
 ; Initialisation pour SetHeaderColor()
 ;========================================================================
 XOR ecx, ecx
 MOV [WindProc_Origine_], ecx        ; initialise la variable à 0
 MOV [_v_WindProc_Origine], ecx     ; initialise la variable à 0
 MOV ebp, 12                                   ; taille de la structure
 MOV ebx, t_ColorieHeader
 CALL PB_NewList

 ;========================================================================
 ; Initialisation pour LockcolumnSize()
 ;========================================================================
 XOR ecx, ecx
 MOV ebp,12        ; taille de la structure
 MOV ebx,t_ColonneVerrouiller
 CALL PB_NewList

 ;========================================================================
 ; Initialisation pour les couleurs des items
 ;========================================================================
 XOR ecx, ecx
 MOV ebp, 24       ; taille de la structure
 MOV ebx, t_CouleurItem
 CALL PB_NewList

 ;========================================================================
 ; Initialisation pour les éléments du header
 ;========================================================================
 XOR ecx, ecx
 MOV ebp,16        ; taille de la structure
 MOV ebx, t_ElementHeader
 CALL PB_NewList

 ;========================================================================
 POP ecx
 POP ebx
 POP ebp
 RET

 section '.bss' readable writeable
 _VarSection:
 bssalign 4

 t_ElementHeader rd 1
 e_ElementHeader rd 1

 t_ColorieHeader rd 1
 e_ColorieHeader rd 1

 t_ColonneVerrouiller rd 1
 e_ColonneVerrouiller rd 1

 t_CouleurItem rd 1
 e_CouleurItem rd 1

 WindProc_Origine_ rd 1
 _v_WindProc_Origine rd 1

10) Valeur retournée par une commandes en asm

Nous verrons cela plus en détail dans le prochain tut, mais pour retourner une valeur, cela se fait par le registre eax sauf pour les chaînes et les nombres flottants (STO pour les flottants)

Prochain tut : L'alignement des données pour les sections de données, approche d'une macro simple. Comment retourner une valeur pour Pure, le fichier descripteur de PureBasic.

 

Rechercher
Installer l'extension de recherche Plus d'informations

 

Comprendre
Tu me dis, j'oublie. Tu m'enseignes, je me souviens. Tu m'impliques, j'apprends. - Benjamin Franklin

 

Partager
La connaissance est la seule chose qui s'accroit lorsqu'on la partage. - Sacha Boudjema

 

Créer
L'imagination est plus importante que la connaissance. - Albert Einstein

 

 

Le wiki en images Le wiki en images Image du mois: «Snowball: un prototype de jeu développé avec NeL.