Désassemblage de code C avec GDB - Curiosité

a marqué ce sujet comme résolu.
Auteur du sujet

Salut à tous !

Je poste ce message car j’ai quelques petites interrogations à propos d’un programme basique en C, dont je ne comprends pas certains aspects du code assembleur une fois passé à GDB à coups de disass :

#include <string.h>  // memcpy, strcmp
#include <stdio.h>   // printf, scanf

#define INPUT_SIZE 50

int main() {
    // on demande un mot de passe à l'utilisateur
    char input[INPUT_SIZE];
    printf("Password?\n");
    scanf("%s", input);
    
    // on teste le mot de passe entré
    if (! strcmp(input, "PASSWORD")) {
        printf("Granted");
    } else {
        printf("Denied");
    }
}

Avec GDB, l’output en assembleur est le suivant :

Dump of assembler code for function main:
   0x0000000000401550 <+0>:     push   rbp
   0x0000000000401551 <+1>:     mov    rbp,rsp
   0x0000000000401554 <+4>:     sub    rsp,0x60
   0x0000000000401558 <+8>:     call   0x401670 <__main>
   0x000000000040155d <+13>:    lea    rcx,[rip+0x2a9c]        # 0x404000
   0x0000000000401564 <+20>:    call   0x402ab0 <puts>
   0x0000000000401569 <+25>:    lea    rax,[rbp-0x40]
   0x000000000040156d <+29>:    mov    rdx,rax
   0x0000000000401570 <+32>:    lea    rcx,[rip+0x2a93]        # 0x40400a
   0x0000000000401577 <+39>:    call   0x402aa8 <scanf>
   0x000000000040157c <+44>:    lea    rax,[rbp-0x40]
   0x0000000000401580 <+48>:    lea    rdx,[rip+0x2a86]        # 0x40400d
   0x0000000000401587 <+55>:    mov    rcx,rax
   0x000000000040158a <+58>:    call   0x402a98 <strcmp>
   0x000000000040158f <+63>:    test   eax,eax
   0x0000000000401591 <+65>:    jne    0x4015a1 <main+81>
   0x0000000000401593 <+67>:    lea    rcx,[rip+0x2a7c]        # 0x404016
   0x000000000040159a <+74>:    call   0x402ab8 <printf>
   0x000000000040159f <+79>:    jmp    0x4015ad <main+93>
   0x00000000004015a1 <+81>:    lea    rcx,[rip+0x2a76]        # 0x40401e
   0x00000000004015a8 <+88>:    call   0x402ab8 <printf>
   0x00000000004015ad <+93>:    mov    eax,0x0
   0x00000000004015b2 <+98>:    add    rsp,0x60
   0x00000000004015b6 <+102>:   pop    rbp
   0x00000000004015b7 <+103>:   ret
End of assembler dump.

Mes quelques questions sont les suivantes :

  • Pourquoi alloue-t-on 0x60 octets sur la pile ? N’est-ce pas "un peu beaucoup" ? D’autant que (n’hésitez pas à me corriger si je dis une ânerie !), les différentes constantes ont l’air d’être stockées dans le segment .rdata.
  • Il me semblait que pour appeler des fonctions C en asm, il fallait préalablement pusher les différents arguments ; or, cela n’est visiblement pas le cas… ? (peut-être y a-t-il une histoire de fastcall, mais je compile avec -O0)

Merci d’avance !

Note : Je suis sous Windows, si jamais vous vous demandiez ;)

Édité par vincentp

+0 -0

Cette réponse a aidé l’auteur du sujet

Salut,

Concernant la deuxième question :

  • Il me semblait que pour appeler des fonctions C en asm, il fallait préalablement pusher les différents arguments ; or, cela n’est visiblement pas le cas… ? (peut-être y a-t-il une histoire de fastcall, mais je compile avec -O0)

Ça dépend des conventions d’appel, mais celle que tu décris est plutôt une convention 32 bits. Ici il semble que la convention utilisée soit la Microsoft 64 bits.

Concernant l’espace inutilisé alloué sur la pile, j’avoue que je ne sais pas ! Peut-être une histoire d’alignement ? Mais ça paraît quand même beaucoup.

Auteur du sujet

Tu ne serais pas en train de regarder un code après compilation non optimisée ? Est-ce bien pertinent ?

À vrai dire, c’est juste pour l’exercice, je conçois qu’un code "en situation réelle" est au moins en -O2 ou -O3 :D

Avec du O2, il consomme juste ce qu’on lui demande. https://godbolt.org/z/xK5hvK

Même là, je constate qu’il y a un sub rsp, 56… pourquoi ?

+0 -0

Cette réponse a aidé l’auteur du sujet

Il y a un padding pour garder un multiple de 16 octets après ton buffer. Si tu augmentes la taille jusqu’à 56, tu ne verras pas de différence, mais à 57, cela bascule à 72. Et cela va de 16 en 16 à partir de 8 avec ce compilo dans cette conf: 8, 24, 40, 72

gcc semble utiliser d’autres alignements.

EDIT: En debug, l’appel à strcmp coûte aussi: j’imagine que c’est pour récupérer son résultat peut-être? (si on teste intput[0] à la place, le poids sur la pile est moindre

Édité par lmghs

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte