2009-10-11 7 views
6

मैं एक बड़ी असेंबली प्रोजेक्ट पर काम कर रहा हूं लेकिन अब मैं इस नई भाषा को सीखना शुरू कर रहा हूं। मैं कुछ सरल उदाहरण बनाने की कोशिश कर रहा हूं जैसे कि आप हाईस्कूल में सी ++ के लिए पा सकते हैं (योग दो संख्याएं, एक संख्या प्रमुख है, आदि)।असेंबली से कॉल सी फ़ंक्शन - एप्लिकेशन "कॉल प्रिंटफ" पर जम जाता है और मुझे नहीं पता कि

अब मुझे सभी प्राइम संख्याओं को एन तक प्रदर्शित करना होगा। समस्या यह है कि एप्लिकेशन "कॉल प्रिंटफ" पर जम जाता है और मुझे नहीं पता कि क्यों।

क्या आप इससे मेरी सहायता कर सकते हैं?

.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 

उत्तर

4

यह शायद इसलिए है क्योंकि आपके रजिस्टरों सभी अव्यवस्थित हैं printf कहा जाता है के बाद, आप रजिस्टरों कि आप printf के बाद का उपयोग करें और फिर कॉल के बाद उन्हें बहाल करने के लिए करते हैं बचाने की जरूरत है।

यह ऐसा कुछ है जो आपको करना चाहिए जब आप syscall या अन्य कॉल जो आपके रजिस्टरों के साथ छेड़छाड़ कर सकते हैं।

इसके अलावा, आप gdb (जीएनयू डिबगर) पर गौर करना चाहिए लगता है कि आप गैस कोडिंग कर रहे हैं की तरह इसलिए यदि आप एक जीएनयू/लिनक्स प्रणाली कोशिश में हैं:

gdb youprogram 

और फिर देखने के लिए जहां यह विफल रहता है इसे चलाने के।

1

कृपया यह भी ध्यान दें कि सी/सी ++ में आपको रजिस्टरों को स्वयं पॉप आउट करने की आवश्यकता है (पास्कल कॉलिंग कनवर्टन में, प्रक्रिया उदाहरण के लिए "ret 8" जारी करती है)।

2

एक अन्य मुद्दा यह है कि आप printf को कॉल के बाद स्टैक को ठीक तरह से साफ नहीं कर रहे हैं। आपको ईएसपी में 8 जोड़ने की जरूरत है क्योंकि आपने ईसीएक्स (4-बाइट्स) और एक पता (32-बिट मोड में 4-बाइट) को धक्का दिया है।

इसके अलावा, ध्यान दें कि, कम से कम विंडोज़ (मिनजीडब्लू का उपयोग करके), ईएक्स (रिटर्न वैल्यू), ईसीएक्स, और ईडीएक्स पर प्रिंटफ स्टॉम्प, और ईएफएलजीएस को संशोधित करता है। सभी मानक सी कार्यों के रूप में, मैंने इस मामले के लिए अब तक उपयोग किया है।

संबंधित मुद्दे