1. #1
    Nouveau membre du Club Avatar de Butcher22
    Homme Profil pro
    Étudiant
    Inscrit en
    février 2014
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 22
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : février 2014
    Messages : 20
    Points : 34
    Points
    34

    Par défaut [C/ASM GNU] Utilisation de la pile

    Bonsoir,

    Voilà, cela fait un certain moment que je suis bloqué sur le fonctionnement de la pile en assembleur.
    Dans le cadre de mes études, je suis en train d'apprendre (sur le tas), la programmation en ASM sur un environnement Linux (GNU). Cela fait un certain temps que j'avais fait un peu d'ASM mais en utilisant les instructions Intel et les registres ax,bx,cx ; du coup, je suis encore un peu largué avec les différentes notations ..... m'enfin la question n'est pas là !
    Dernièrement, on a commencé à intégrer du code ASM à des prog C, mais pas directement dans le code C mais en ayant deux fichiers un .c et .s

    L'objectif est simple, coder une calculette en notation polonaise, donc devoir empiler les arguments.

    L'exemple est tiré du modèle du cours, d'où l'utilisation des registres rax,rbx (sur 64 bits), aussi ayant encore du mal à appréhender l'utilisation de la pile pour les fonctions, au lieu de push rbp j'ai utilisé le registre r15 comme tampon, mais bon toujours aucun résultat ....

    Le problème est évident, comment retrouver la bonne valeur du sommet de la pile pour pouvoir récupérer la bonne valeur apres un pop.... Le problème est que, passant par des fonctions, on doit sauvegarder l'état de la pile pour pouvoir en crée une autre pour les var du sous prog, puis revenir aux anciennes valeurs de la pile. Mais bon, clairement quelque chose m'échappe !

    Trêve de bavardage :p

    Makefile
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    pol_calcul: 	pol_calculA pol_calculC
    		    	gcc -gstabs -o pol_calcul pol_calculA.o pol_calculC.o
     
    pol_calculA: 	pol_calcul.s
    				gcc -c -g -o pol_calculA.o pol_calcul.s
     
    pol_calculC: 	pol_calcul.c
    				gcc -c -g -o pol_calculC.o pol_calcul.c
    pol_calcul.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <inttypes.h>
     
    void empiler(int64_t *);
    int64_t* depiler();
     
    #define MAX_SIZE 100
     
    int main() 
    {
    	int64_t tmp = 2;
    	int64_t* d;
     
    	printf("tmp = %ld || &tmp = %p \n",tmp,&tmp);
     
            empiler(&tmp);
    	printf("empiler &tmp ....\n");
     
    	d = depiler();
    	printf("depiler tmp .... = %ld\n",*d)		
     
    	return 0;
    }
    pol_calcul.s
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    .data
    .text
     
    .global empiler
    .type empiler, @function
    empiler:
    	movq %rbp, %r15		# sauvegarde pointeur base 
    	movq %rsp, %rbp
    	pushq %rdi
    	movq %rbp, %rsp     		# restauration pointeur base
    	movq %r15, %rbp
    	ret
     
    .global depiler
    .type depiler, @function
    depiler:
    	movq %rbp, %r15            # sauvegarde pointeur base
    	movq %rsp, %rbp
    	movq %rdi, %rax
    	movq %rbp, %rsp            # restauration pointeur base 
    	movq %r15, %rbp
    	ret
    Voilà, je suis ouvert à toute proposition, aussi si vous avez de bonne références pour en apprendre plus.
    D'avance merci

  2. #2
    Responsable Pascal, Delphi et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    mars 2003
    Messages
    7 169
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : mars 2003
    Messages : 7 169
    Points : 49 683
    Points
    49 683
    Billets dans le blog
    2

    Par défaut

    Bonjour,

    Citation Envoyé par Butcher22 Voir le message
    aussi si vous avez de bonne références pour en apprendre plus.
    Le cours d'Issam Abdallah est disponible ici : https://asm.developpez.com/cours/gas/

    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]

  3. #3
    Nouveau membre du Club Avatar de Butcher22
    Homme Profil pro
    Étudiant
    Inscrit en
    février 2014
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 22
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : février 2014
    Messages : 20
    Points : 34
    Points
    34

    Par défaut

    Bonsoir,

    merci pour le lien, ça aide toujours

    Sinon j'ai essayé d'avancer un peu de mon coté, donc voici une nouvelle "approche".

    J'initialise la pile avec un malloc dans le code C, puis grace à la fonction init(int64_t *) qui initialise le registre %r15 avec l'adresse de la pile.
    puis dans les fonctions empiler/dépiler je fais pointer %rsp sur l'adresse de la pile ( %15 ) puis je fait un push ou un pop.

    bon je pense pas que ce soit la meilleur solution, mais c'est un début, puisque j'arrive bien a empiler puis dépiler, mais je ne peux le faire que deux fois et j'ai une erreur de Seg..... pourquoi ? meme en changeant MAX_PILE

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <inttypes.h>
     
    /* PILE */
    void init(int64_t *);
    void empiler(int64_t );
    int64_t depiler();
     
    /* Operations */
    int64_t addition(int64_t, int64_t);
    int64_t substract(int64_t, int64_t);
    int64_t times(int64_t, int64_t);
    int64_t divide(int64_t, int64_t);
     
    #define MAX_PILE 2
    #define MAX_INPUT 100
     
    int main() 
    {
    	int i;
    	int64_t a,b,r;
    	char c;
     
    	int64_t* pile = NULL;	
    	pile = malloc(sizeof(int64_t) * MAX_PILE);
     
    	char* input = NULL;
    	input = malloc(sizeof(char) * MAX_INPUT);
     
    	init(pile); // init :  %r15 = &pile
     
    	printf("Saisir votre opération en notation polonaise\n");
    	scanf("%[^\n]s",input);
     
    	for (i=0; i<MAX_INPUT; i++)
    	{
    		c = *(input+i);
     
    		/* END */
    		if ( c == '\0')
    		{
    			printf("Resultat = %ld\n",depiler());
    			break;
    		}
     
    		/* OP */
    		switch ( c)
    		{
    			case ' ' : continue;
    			case '+' :
    			{				
    				b = depiler();
    				a = depiler();
    				r =  addition (a,b);
    				empiler(r);
    				break;
    			}
    			case '-':
    			{
    				b = depiler();
    				a = depiler();
    				r = substract(a,b);
    				empiler(r);
    				break;
    			}
    			case '*':
    			{
    				b = depiler();
    				a = depiler();
    				r = times(a,b);
    				empiler(r);
    				break;
    			}
    			case '/':
    			{
    				b = depiler();
    				a = depiler();
    				r = divide(a,b);
    				empiler(r);
    				break;
    			}
    			default:
    			{
    				r = c- 48;
    				empiler(r);
    			}
    		}
    	}
     
    	//free(pile);
    	free(input);
     
    	return 0;
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
     
    .data
    .text
     
    /**	
    * intisialisé %r15 avec &pile	
    **/
    .global init
    .type init, @function
    init:
    	pushq %rbp
    	movq %rsp, %rbp
    	#movq 16(%rbp), %r15		# 16/32 marchent pas
    	movq %rdi, %r15
    	movq %rbp, %rsp
    	popq %rbp
    	ret
     
     
    /**
    * empiler une valeur dans &pile = %r15
    **/
    .global empiler
    .type empiler, @function
    empiler:
    	pushq %rbp							# sauvegarde pointeur base
    	movq %rsp, %rbp					# rsp = rbp
      #movq 24(%rbp), %rax		# recup val (ne marche pas toujours)
    	movq %rdi, %rax					#	recup val (OK)
    	movq %rsp, %r14					# sauv &sommet_fonction_empiler
    	movq %r15, %rsp					# %rsp = &pile
    	push %rax								# ENNFIIINNNN
    	movq %rsp, %r15					# sauv nouvelle &pile
      movq %r14, %rsp					# restaurer &sommet_fonction_empiler
    	movq %rbp, %rsp     		# restauration pointeur base
    	popq %rbp
    	ret
     
    /**
    * depiler valeur depuis &pile = %r15
    **/
    .global depiler
    .type depiler, @function
    depiler:
    	pushq %rbp  			      # sauvegarde pointeur base
    	movq %rsp, %rbp					# rsp = rbp
    	movq %rsp, %r14					
    	movq %r15, %rsp
    	pop %rax
    	movq %rsp, %r15
    	movq %r14, %rsp
    	movq %rbp, %rsp         # restauration pointeur base
    	popq %rbp
    	ret
     
    .global addition
    .type addition, @function
    addition:
    	push %rbp           /* sauvegarde pointeur base */
    	movq %rsp, %rbp
    	push %rbx           /* sauvegarde des registres */
    	movq 24(%rbp), %rbx  /* on prépare les opérandes */
    	movq 32(%rbp), %rax
    	addq %rbx, %rax     /* on fait l'addition */
    	pop %rbx            /* on restaure les registres */
    	movq %rbp, %rsp     /* restauration pointeur base */
    	pop %rbp
    	ret
     
    .global substract
    .type substract, @function
    substract:
    	push %rbp
    	movq %rsp, %rbp
    	push %rbx
    	movq 24(%rbp), %rbx
    	movq 32(%rbp), %rax
    	subq %rbx, %rax
    	pop %rbx
    	movq %rbp, %rsp
    	pop %rbp
    	ret
     
    .global times
    .type times, @function
    times:
    	push %rbp
    	movq %rsp, %rbp
    	push %rbx
    	movq 24(%rbp), %rbx
    	movq 32(%rbp), %rax
    	imul %rbx
    	pop %rbx
    	movq %rbp, %rsp
    	pop %rbp
    	ret
     
    .global divide
    .type divide, @function
    divide:
    	movq $0, %rdx      /* Sinon problème de division */
    	push %rbp
    	movq %rsp, %rbp
    	push %rbx
    	movq 24(%rbp), %rbx
    	movq 32(%rbp), %rax
    	idiv %rbx
    	pop %rbx
    	movq %rbp, %rsp
    	pop %rbp
    	ret

    voila, j'ai essayé de commenter au max le code pour etre lisible.
    d'avance merci

Discussions similaires

  1. convertir de l'asm gnu en windows 16 ou 32 bits
    Par Linquisiteur dans le forum x86 32-bits / 64-bits
    Réponses: 2
    Dernier message: 10/05/2013, 18h11
  2. Vendre un produit utilisant une licence GNU
    Par laclac dans le forum Licences
    Réponses: 3
    Dernier message: 18/09/2007, 17h42
  3. Utiliser du C/asm avec Java
    Par Mossé Benjamin dans le forum APIs
    Réponses: 3
    Dernier message: 12/09/2007, 03h10
  4. déclaration et utilisation d'un buffer (pile TCP/IP)
    Par aefmaaradji84 dans le forum C++/CLI
    Réponses: 1
    Dernier message: 27/08/2007, 09h18
  5. Réponses: 5
    Dernier message: 30/01/2006, 14h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo