2009-10-11 6 views
6

ich auf einem großen Versammlung Projekt arbeiten werden, aber bin jetzt gerade erst diese neue Sprache zu lernen. Ich versuche, einige einfache Beispiele zu machen, wie Sie für C++ in der Highschool finden könnten (Summe zwei Zahlen, ist eine Zahl Prime, etc).Aufruf C-Funktion von Montage - die Anwendung gefriert bei „call printf“ und ich habe keine Ahnung, warum

Jetzt habe ich bis zu n alle Primzahlen angezeigt werden soll. Das Problem ist, dass die Anwendung bei "call printf" einfriert und ich habe keine Ahnung warum.

Können Sie mir helfen mit diesem?

.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 

Antwort

4

Es ist wahrscheinlich, weil Ihr Register alle nach printf messed sind aufgerufen, müssen Sie die Register speichern, die Sie nach printf zu verwenden, neigen dazu, und diese wiederherstellen, dann nach dem Aufruf.

Das ist etwas, sollten Sie immer tun, wenn Sie syscall oder andere Anrufe zu tun, die mit dem Register TAMPERE könnten.

Auch sollten Sie schauen in gdb (Gnu Debugger) sieht aus wie Sie GAS codieren also, wenn Sie auf einem GNU/Linux-System versuchen, sind:

gdb youprogram 

und es dann zu sehen, laufen, wo es fehlschlägt.

1

Bitte beachten Sie auch, dass in C/C++ Sie die Register herausspringen müssen, um sich (in Pascal-Aufruf convertion, gibt das Verfahren einen „ret 8“ zum Beispiel).

2

Ein weiteres Problem ist, dass Sie nicht richtig, den Stapel nach dem Aufruf von printf aufzuräumen. Sie müssen 8 zu ESP hinzufügen, weil Sie ECX (4 Byte) und eine Adresse (4 Byte im 32-Bit-Modus) gedrückt haben.

Beachten Sie außerdem, dass printf, zumindest unter Windows (mit MinGW), auf EAX (Rückgabewert), ECX und EDX stürzt und EFLAGS ändert. Wie alle Standard-C-Funktionen, die ich bis jetzt verwendet habe.

Verwandte Themen