2009-03-12 5 views
1

moi avons écrit le code suivant dans AT & T Assembleur Syntaxe pour gcccopie et appel de fonctions dans x86 AT & T-Assembleur à gcc

.global main 
.section .data 

to_gen_inner: #x f, implicit n 
     pushl %ebp 
     movl %esp, %ebp 
     movl $0xFF00FF00, %eax 
     call printregs 
     lret 

.set to_gen_inner_len, . - to_gen_inner 

.section .text 

main: 
     pushl %ebp 
     movl %esp, %ebp 

     #allocate memory 
     pushl $to_gen_inner_len 
     call malloc 
     popl %ecx 

     pushl $to_gen_inner_len 
     pushl to_gen_inner 
     pushl %eax 
     call copy_bytes 
     popl %eax 
     popl %ecx 
     popl %ecx 

     lcall *(%eax) 

     movl %ebp, %esp 
     popl %ebp 
     ret 

printfregs: 
     .ascii "eax: %8X\nebx: %8X\necx: %8X\nedx: %8X\n\0" 

printregs: 
     pushl %edx 
     pushl %ecx 
     pushl %ebx 
     pushl %eax 
     pushl $printfregs 
     call printf 
     popl %ecx 
     popl %eax 
     popl %ebx 
     popl %ecx 
     popl %edx 
     lret 

copy_bytes: #dest source length 
     pushl %ebp 
     movl %esp, %ebp 

     subl $24, %esp 

     movl 8(%ebp), %ecx # dest 
     movl %eax, -4(%ebp) 

     movl 12(%ebp), %ebx # source 
     movl %eax, -8(%ebp) 

     movl 16(%ebp), %eax # length 
     movl %eax, -12(%ebp) 

     addl %eax, %ecx # last dest-byte 
     movl %ecx, -16(%ebp) 

     addl %eax, %edx # last source-byte 
     movl %ecx, -20(%ebp) 

     movl -4(%ebp), %eax 
     movl -8(%ebp), %ebx 
     movl -16(%ebp), %ecx 

     copy_bytes_2: 
     movb (%ebx), %dl 
     movb %dl, (%eax) 
     incl %eax 
     incl %ebx 
     cmp %eax, %ecx 
     jne copy_bytes_2 

     movl %ebp, %esp 
     popl %ebp 
     ret 

En fait, ce que je veux faire est de copier le code de fonction de to_gen_inner dans le mémoire que j'alloue avec malloc, puis saute dedans. Ce code produit un défaut de segmentation. gdb sais:

Program received signal SIGSEGV, Segmentation fault. 
main() at speicher3.S:32 
32    lcall *(%eax) 
Current language: auto; currently asm 
(gdb) disas $pc-5 $pc+5 
Dump of assembler code from 0x80483eb to 0x80483f5: 
0x080483eb <main+23>: add %al,(%eax) 
0x080483ed <main+25>: pop %eax 
0x080483ee <main+26>: pop %ecx 
0x080483ef <main+27>: pop %ecx 
0x080483f0 <main+28>: lcall *(%eax) 
0x080483f2 <main+30>: mov %ebp,%esp 
0x080483f4 <main+32>: pop %ebp 
End of assembler dump. 
(gdb) disas $pc-6 $pc+5 
Dump of assembler code from 0x80483ea to 0x80483f5: 
0x080483ea <main+22>: add %al,(%eax) 
0x080483ec <main+24>: add %bl,0x59(%eax) 
0x080483ef <main+27>: pop %ecx 
0x080483f0 <main+28>: lcall *(%eax) 
0x080483f2 <main+30>: mov %ebp,%esp 
0x080483f4 <main+32>: pop %ebp 
End of assembler dump. 
(gdb) 

Je ne sais pas pourquoi. J'utilise déjà lcall et lret, que j'ai lu est pensé pour les appels absolus, avec appel et ret, ça ne marche pas non plus, même erreur. Je ne sais pas ce que je pourrais faire mal. Quelqu'un peut-il m'aider s'il vous plaît?

Répondre

6

Vous avez les problèmes suivants:

  • lors de la mise en place de la pile pour votre appel à copy_bytes, vous voulez pushl to_gen_inner de $ non pushl to_gen_inner (ce dernier pousse le contenu des points de to_gen_inner mémoire à)

  • lors de la copie des valeurs à la stackframe locale à l'intérieur copy_bytes, vous devez écrire le registre, vous venez de lire le paramètre en, au lieu d'écrire toujours EAX

  • LCALL * (% eax) expé cts pour lire une adresse de la mémoire pointée par EAX, et sautez là. De plus, il s'attend à lire 48 octets, les 16 premiers étant le segment. J'ai remplacé votre appel avec appel *% eax; a également remplacé les lrets avec des rets en conséquence. L'appel à printregs est assemblé comme un appel relatif, ce qui explose puisque l'instruction que vous exécutez n'est plus au même décalage relatif à la cible que lors de son assemblage. Je l'ai remplacé avec

    movl $printregs, %ecx 
    call *%ecx 
    

(qui Trashes% ECX)

  • enfin, to_gen_inner met en place le stackframe à l'entrée, mais ne parvient pas à détruire la sortie

Avec tous ces corrigé, le code ressemble à ceci:

.global main 
.section .data 

to_gen_inner: #x f, implicit n 
     pushl %ebp 
     movl %esp, %ebp 
     movl $0xFF00FF00, %eax 
     movl $printregs, %ecx 
     call *%ecx 
     movl %ebp, %esp 
     popl %ebp   
     ret 

.set to_gen_inner_len, . - to_gen_inner 

.section .text 

main: 
     pushl %ebp 
     movl %esp, %ebp 

     #allocate memory 
     pushl $to_gen_inner_len 
     call malloc 
     popl %ecx 

     pushl $to_gen_inner_len 
     pushl $to_gen_inner 
     pushl %eax 
     call copy_bytes 
     popl %eax 
     popl %ecx 
     popl %ecx 

     call *%eax 

     movl %ebp, %esp 
     popl %ebp 
     ret 

printfregs: 
     .ascii "eax: %8X\nebx: %8X\necx: %8X\nedx: %8X\n\0" 

printregs: 
     pushl %edx 
     pushl %ecx 
     pushl %ebx 
     pushl %eax 
     pushl $printfregs 
     call printf 
     popl %ecx 
     popl %eax 
     popl %ebx 
     popl %ecx 
     popl %edx 
     ret 

copy_bytes: #dest source length 
     pushl %ebp 
     movl %esp, %ebp 

     subl $24, %esp 

     movl 8(%ebp), %ecx # dest 
     movl %ecx, -4(%ebp) 

     movl 12(%ebp), %ebx # source 
     movl %ebx, -8(%ebp) 

     movl 16(%ebp), %eax # length 
     movl %eax, -12(%ebp) 

     addl %eax, %ecx # last dest-byte 
     movl %ecx, -16(%ebp) 

     addl %eax, %edx # last source-byte 
     movl %ecx, -20(%ebp) 

     movl -4(%ebp), %eax 
     movl -8(%ebp), %ebx 
     movl -16(%ebp), %ecx 

     copy_bytes_2: 
     movb (%ebx), %dl 
     movb %dl, (%eax) 
     incl %eax 
     incl %ebx 
     cmp %eax, %ecx 
     jne copy_bytes_2 

     movl %ebp, %esp 
     popl %ebp 
     ret 

... qui construit et fonctionne ici pour moi. J'espère que cela pourra aider.

+0

Hm. Étrange. Votre code fonctionne aussi avec juste *% eax (ce que j'ai fait en premier). On dirait que ce n'était pas la principale raison pour laquelle mon code a échoué. En tous cas. Merci beaucoup. – schoppenhauer

+0

Ah - on dirait que c'est call *% eax vs call * (% eax) - les premières branches à l'adresse de% eax, cette dernière appelle l'adresse contenue dans la mémoire pointée par% eax. Éditera la réponse. – moonshadow

Questions connexes