2009-10-11 7 views
6

Je vais travailler sur un grand projet d'assemblage mais je commence à peine à apprendre cette nouvelle langue. J'essaie de faire quelques exemples simples comme vous pourriez trouver pour C++ en highschool (somme de deux nombres, est un nombre premier, etc).Appelez la fonction C de l'Assemblée - l'application se bloque à "appel printf" et je ne sais pas pourquoi

Maintenant, je dois afficher tous les nombres premiers jusqu'à n. Le problème est que l'application se bloque à "call printf" et je ne sais pas pourquoi.

Pouvez-vous m'aider avec ceci?

.section .data 
prime_number_str: 
.asciz "%d " 

.section .text 

.global  _start 
_start: 
pushl $20 
call .first_prime_numbers 
addl $4, %esp 
pushl $0 
call exit 


.first_prime_numbers:  #argument first n numbers 
movl 4(%esp), %ecx #get the first argument 
do_test: 
pushl %ecx  #push function arguments 
call .prime 
addl $4, %esp  #restore the stack 

#if not prime jump to the next number 
cmpl $0, %eax 
je no_not_prime 

#print the number 
pushl %eax   #save eax 
pushl %ecx   #first argument 
pushl $prime_number_str  #text to print 
call printf 
addl $4, %esp 
popl %eax   #restore eax 

no_not_prime: 
loop do_test 
ret 


.prime:    #argument: number to check 
movl 4(%esp), %eax #get the first argument 

#divide the argument by 2 
xorl %edx, %edx    
movl $2, %ecx   
pushl %eax  #save the value of eax 
divl %ecx  
movl %eax, %ecx  #init the counter register 
popl %eax  #restore the value of eax 

movl $1, %ebx  #assume the argument is prime 
test_prime: 
# if ecx == 1 then return exit the function 
cmpl $1, %ecx  
jle return_value 

pushl %eax  #save the old value of eax 

#divide the value by the value of counter 
xorl %edx, %edx  
divl %ecx  

#if the reminder is 0 then the number is not prime 
cmpl $0, %edx 
popl %eax  #restore the value of eax 
je not_prime 


subl $1, %ecx  #decrease counter 
jmp test_prime  #try next division 

not_prime: 
movl $0, %ebx 
return_value: 
movl %ebx, %eax 
ret 

Répondre

4

Il est probablement parce que vos registres sont tous foiré après appelé printf, vous devez enregistrer les registres que vous avez tendance à utiliser après printf puis les restaurer après l'appel.

C'est quelque chose que vous devriez faire Toujours quand vous faites syscall ou d'autres appels qui pourraient tampurer avec vos registres.

Aussi, vous devriez regarder dans gdb (débogueur gnu) ressemble à vous codez GAS donc si vous êtes sur un système gnu/linux essayer:

gdb youprogram 

puis l'exécuter pour voir où il échoue.

1

Veuillez noter également qu'en C/C++ vous devez vous-même faire apparaître les registres (en Pascal appelant la conversion, la procédure émet un "ret 8" par exemple).

2

Un autre problème est que vous ne nettoyez pas correctement la pile après l'appel de printf. Vous devez ajouter 8 à ESP car vous avez appuyé sur ECX (4 octets) et sur une adresse (4 octets en mode 32 bits). Notez également que, au moins sous Windows (avec MinGW), printf stompe sur EAX (valeur de retour), ECX et EDX, et modifie EFLAGS. Comme toutes les fonctions C standard que j'ai utilisées jusqu'ici, d'ailleurs.

Questions connexes