Code : Tout sélectionner
Tutorial 7 - les instructions asm les plus courantes et le corps d'un programme FASM pour les librairies.
--------------------------------------------------------------------------------------------------------
Par Denis
1) 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 2ème é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 2ème é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.
A noter que 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.
L'instruction MOV 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
A noter que 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
A noter que 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 --> INC eax
SUB eax, 1 --> 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) 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) 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) 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é
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.
FASM, lorsqu'il va convertir le fichier en exe, 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 utilisables par toutes les commandes de la librairie.
Si on veut pouvoir utiliser des variables globales dans d'autres commandes de la librairie (j'ai pas dit
qu'on pouvait les utiliser depuis PureBasic directement !) 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 du 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 :
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 :
------------
; Version 2.0 (September, 2003)
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.
A+
Denis