2008-08-21 21 views
7

यह थोड़ी सी अजीब बात है, लेकिन मैं आज जीएनयू असेंबलर के साथ घूम रहा था (मैं कम से कम वाक्यविन्यास पढ़ने में सक्षम होना चाहता हूं), और इस छोटे से विकसित उदाहरण को प्राप्त करने की कोशिश कर रहा था काम करने के लिए मेरा। अर्थात् मैं बस 0 से 100 तक जाना चाहता हूं, हर समय प्रिंटिंग नंबर। तो कुछ मिनट बाद मैं इस के साथ आते हैं:असेंबली भाषा में 0 से 100 तक बढ़ाना

# count.s: print the numbers from 0 to 100. 
    .text 
string: .asciz "%d\n" 
    .globl _main 

_main: 
    movl $0, %eax # The starting point/current value. 
    movl $100, %ebx # The ending point. 

_loop: 
    # Display the current value. 
    pushl %eax 
    pushl $string 
    call  _printf 
    addl  $8, %esp 

    # Check against the ending value. 
    cmpl %eax, %ebx 
    je _end 

    # Increment the current value. 
    incl %eax 
    jmp _loop 

_end: 

सभी मैं इस से प्राप्त 3 से अधिक मुद्रित और फिर से है। जैसे मैंने कहा, बस थोड़ा सा उदाहरण दिया गया है, इसलिए इसके बारे में ज्यादा चिंता न करें, यह जीवन या मृत्यु की समस्या नहीं है।

(स्वरूपण थोड़ा गड़बड़ है, लेकिन कुछ भी प्रमुख नहीं है)।

+2

'xorl% eax,% eax' पूरी तरह से' $ 0,% eax' movl के बराबर है, और 3 बाइट्स कम समय लगता है। बस केह रहा हू। :) –

उत्तर

12

आप किसी भी रजिस्टरों को जो भी कहा जाता है, उस पर भरोसा नहीं कर सकते हैं। या तो रजिस्टरों को ढेर पर धक्का दें और प्रिंटफ को कॉल करने के बाद उन्हें वापस बंद करें या स्मृति में रखे गए वृद्धि और अंत बिंदु मान रखें और रजिस्टरों में पढ़ने/लिखे गए जैसे आपको उनकी आवश्यकता हो।

मुझे आशा है कि निम्नलिखित कार्य। मुझे लगता है कि पुशल में एक समकक्ष पॉपल है और आप स्टैक पर अतिरिक्त संख्याओं को धक्का दे सकते हैं।

# count.s: print the numbers from 0 to 100. 
    .text 
string: .asciz "%d\n" 
    .globl _main 

_main: 
    movl $0, %eax # The starting point/current value. 
    movl $100,  %ebx # The ending point. 

_loop: 
    # Remember your registers. 
    pushl %eax 
    pushl %ebx 

    # Display the current value. 
    pushl %eax 
    pushl $string 
    call  _printf 
    addl  $8, %esp 

    # reinstate registers. 
    popl %ebx 
    popl %eax 

    # Check against the ending value. 
    cmpl %eax, %ebx 
    je _end 

    # Increment the current value. 
    incl %eax 
    jmp _loop 

_end: 
+1

बीटीडब्ल्यू - पुश और पॉप सभी रजिस्टरों को धक्का देंगे, और उन्हें सब पॉप करेंगे .. मुझे पता चला है कि पिछले – warren

+0

में नोट्स से काफी आसान है। यह ध्यान रखना महत्वपूर्ण है कि ... "@seanyboy, आपका समाधान अधिक है। ईक्स को किसी अन्य रजिस्टर के साथ ईएक्स को प्रतिस्थापित करना आवश्यक है।" – seanyboy

+0

@warren - 'pusha' और 'popa' 64-बिट मोड में समर्थित नहीं हैं। –

6

मैं _printf से बहुत परिचित नहीं हूं, लेकिन क्या यह हो सकता है कि यह ईएक्स को संशोधित करे? प्रिंटफ को मुद्रित वर्णों की संख्या वापस करनी चाहिए, जो इस मामले में दो हैं: '0' और '\ n'। मुझे लगता है कि यह इसे ईएक्स में लौटाता है, और जब आप इसे बढ़ाते हैं, तो आपको 3 मिलता है, जो आप प्रिंट करने के लिए आगे बढ़ते हैं। काउंटर के लिए एक अलग रजिस्टर का उपयोग करके आप बेहतर हो सकते हैं।

1

नाथन सही रास्ते पर है। आप यह नहीं मान सकते कि subroutine को कॉल करने के बाद रजिस्टर मानों को अनमोडिफाइड किया जाएगा। वास्तव में, यह मानना ​​सबसे अच्छा है कि उन्हें संशोधित किया जाएगा, अन्यथा subroutine यह काम नहीं कर पाएगा (कम से कम कम रजिस्टर गिनती आर्किटेक्चर के लिए x86)। यदि आप किसी मान को संरक्षित करना चाहते हैं तो आपको इसे स्मृति में संग्रहीत करना चाहिए (उदा। इसे स्टैक पर दबाएं और इसके स्थान का ट्रैक रखें)।

आपको अपने किसी भी अन्य चर के लिए ऐसा करने की आवश्यकता होगी। स्थानीय चरों को स्टोर करने के लिए रजिस्टरों का उपयोग करना पर्याप्त रजिस्टरों के साथ आर्किटेक्चर के लिए बहुत अधिक आरक्षित है (उदाहरण के लिए ईपीआईसी, एमडी 64, इत्यादि)

3

अच्छी तरह लिखित कार्य आमतौर पर सभी रजिस्टरों को ढेर पर धक्का देंगे और फिर उन्हें ' फिर से किया गया ताकि वे समारोह के दौरान अपरिवर्तित बने रहें। अपवाद ईएक्स होगा जिसमें रिटर्न वैल्यू होगा। प्रिंटफ जैसे लाइब्रेरी फ़ंक्शंस इस तरह से लिखे गए हैं, इसलिए वे ऐसा नहीं करेंगे क्योंकि वेज सुझाव देते हैं:

आपको अपने किसी भी अन्य चर के लिए ऐसा करने की आवश्यकता होगी। रजिस्टरों का उपयोग करते हुए स्थानीय चर स्टोर करने के लिए काफी पर्याप्त रजिस्टरों के साथ आर्किटेक्चर के लिए आरक्षित है यह (जैसे महाकाव्य, amd64, आदि)

वास्तव में, समर्थन करने के लिए इस तरह से वास्तव में निपटने के लिए मैं क्या पता है, compilers आम तौर पर काम करता है संकलन से इस मुद्दे के साथ।

@seanyboy, आपका समाधान अधिक है। इक्सैक्स जैसे किसी अन्य रजिस्टर के साथ ईएक्स को प्रतिस्थापित करना आवश्यक है।

-1

आप इसे फिर से लिख सकते हैं ताकि आप उन रजिस्टरों का उपयोग कर सकें जिन्हें बदलने का अनुमान नहीं है, उदाहरण के लिए %ebp। बस सुनिश्चित करें कि आप उन्हें शुरुआत में ढेर पर धक्का दें, और अपने दिनचर्या के अंत में उन्हें बंद कर दें।

# count.s: print the numbers from 0 to 100. 
    .text 
string: .asciz "%d\n" 
    .globl _main 

_main: 
    push %ecx 
    push %ebp 
    movl $0, %ecx # The starting point/current value. 
    movl $100,  %ebp # The ending point. 

_loop: 
    # Display the current value. 
    pushl %ecx 
    pushl $string 
    call  _printf 
    addl  $8, %esp 

    # Check against the ending value. 
    cmpl %ecx, %ebp 
    je _end 

    # Increment the current value. 
    incl %ecx 
    jmp _loop 

_end: 
    pop  %ebp 
    pop  %ecx 
5

आप उन रजिस्टरों का सुरक्षित रूप से उपयोग कर सकते हैं जो उन्हें स्वयं को बचाने के बिना "कैली-सेव" हैं। X86 पर ये edi, esi, और ebx हैं; अन्य वास्तुकला में अधिक है।

ये ABI संदर्भ में प्रलेखित हैं: http://math-atlas.sourceforge.net/devel/assembly/

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