खोज…


परिचय

X86 परिवार लंबे समय से आसपास रहा है, और जैसे कि कई तरकीबें और तकनीकें हैं जिन्हें खोजा और विकसित किया गया है जो कि सार्वजनिक ज्ञान है - या शायद इतना सार्वजनिक नहीं है। इन चालों में से अधिकांश इस तथ्य का लाभ उठाते हैं कि कई निर्देश प्रभावी रूप से एक ही काम करते हैं - लेकिन विभिन्न संस्करण तेज हैं, या मेमोरी को बचाते हैं, या झंडे को प्रभावित नहीं करते हैं। यहाँ कई तरकीबें खोजी गई हैं। प्रत्येक के पास अपने पेशेवरों और विपक्ष हैं, इसलिए सूचीबद्ध होना चाहिए।

टिप्पणियों

जब संदेह होता है, तो आप हमेशा बहुत व्यापक इंटेल 64 और आईए -32 आर्किटेक्चर ऑप्टिमाइज़ेशन रेफरेंस मैनुअल का उल्लेख कर सकते हैं, जो कि x86 आर्किटेक्चर के पीछे कंपनी का एक शानदार संसाधन है।

एक रजिस्टर को शून्य करना

किसी रजिस्टर को शून्य करने का स्पष्ट तरीका 0 से एक उदाहरण में MOV के लिए है:

B8 00 00 00 00    MOV eax, 0

ध्यान दें कि यह एक 5-बाइट अनुदेश है।

यदि आप झंडे लहराने के लिए तैयार हैं ( MOV झंडे को कभी भी प्रभावित नहीं करता है), तो आप XOR इंस्ट्रक्शन को अपने साथ रजिस्टर करने के लिए बिटवायर्न-एक्सओआर का उपयोग कर सकते हैं:

33 C0             XOR eax, eax

इस निर्देश के लिए केवल 2 बाइट्स की आवश्यकता होती है और सभी प्रोसेसरों पर तेजी से निष्पादित होता है

एक रजिस्टर में कैरी फ्लैग ले जाना

पृष्ठभूमि

यदि कैरी ( C ) ध्वज में एक मान है जिसे आप एक रजिस्टर में रखना चाहते हैं, तो भोला तरीका कुछ ऐसा करना है:

    mov  al, 1
    jc   NotZero
    mov  al, 0
NotZero:

'Sbb' का उपयोग करें

एक और अधिक सीधा रास्ता, कूद से बचने के लिए, "उधार के साथ घटाव" का उपयोग करना है:

    sbb  al,al    ; Move Carry to al

यदि C शून्य है, तो al शून्य होगा। अन्यथा यह 0xFF ( -1 ) होगा। यदि आपको इसकी आवश्यकता 0x01 , तो जोड़ें:

    and  al, 0x01 ; Mask down to 1 or 0

पेशेवरों

  • उसी आकार के बारे में
  • दो या एक कम निर्देश
  • कोई महंगी छलांग नहीं

विपक्ष

  • यह तकनीक से अपरिचित पाठक के लिए अपारदर्शी है
  • यह अन्य झंडे को बदल देता है

0 के लिए एक रजिस्टर का परीक्षण करें

पृष्ठभूमि

यह पता लगाने के लिए कि क्या कोई रजिस्टर शून्य रखता है, भोले तकनीक को ऐसा करना है:

    cmp   eax, 0

लेकिन अगर आप इसके लिए opcode को देखते हैं, तो आपको यह मिलता है:

83 F8 00      cmp   eax, 0

test उपयोग करें

    test   eax, eax      ; Equal to zero?

आपके द्वारा प्राप्त किए गए opcode की जाँच करें:

85 c0         test   eax, eax

पेशेवरों

  • केवल दो बाइट्स!

विपक्ष

  • एक पाठक के लिए अपारदर्शी तकनीक से अपरिचित है

आप इस तकनीक पर प्रश्नोत्तर प्रश्न पर भी गौर कर सकते हैं।

लिनक्स सिस्टम कम ब्लोट के साथ कॉल करता है

32-बिट लिनक्स में, सिस्टम कॉल आमतौर पर सिसेंटर इंस्ट्रक्शन का उपयोग करके किया जाता है (मैं आमतौर पर कहता हूं क्योंकि पुराने प्रोग्राम अब int 0x80 उपयोग करते हैं), लेकिन यह एक प्रोग्राम में काफी जगह ले सकता है और इसलिए ऐसे तरीके हैं जो एक हैं चीजों को छोटा और गति देने के लिए कोनों को काट सकते हैं।
यह आमतौर पर 32-बिट लिनक्स पर एक सिस्टम कॉल का लेआउट है:

mov eax, <System call number>
mov ebx, <Argument 1> ;If applicable
mov ecx, <Argument 2> ;If applicable
mov edx, <Argument 3> ;If applicable
push <label to jump to after the syscall>
push ecx
push edx
push ebp
mov ebp, esp
sysenter

यह बड़े पैमाने पर सही है! लेकिन इस झंझट से बचने के लिए हम कुछ तरकीबें अपना सकते हैं।
सबसे पहले 3 32-बिट रजिस्टरों के आकार के घटे हुए एस्प के मान को 12 बाइट्स के लिए ईबीपी सेट करना है। यह तब तक बहुत अच्छा है जब तक कि आप कचरे के साथ ईबीपी, ईएक्सएक्स और ईएक्सएक्स के साथ ठीक नहीं हो जाते हैं (जैसे कि जब आप वैसे भी उन रजिस्टरों में एक मूल्य को आगे बढ़ाएंगे), हम एलईए अनुदेश का उपयोग करके ऐसा कर सकते हैं ताकि हमें ज़रूरत न हो ईएसपी के मूल्य को ही प्रभावित करने के लिए।

mov eax, <System call number>
mov ebx, <Argument 1>
mov ecx, <Argument 2>
mov edx, <Argument 3>
push <label to jump to after the syscall>
lea ebp, [esp-12]
sysenter

हालांकि, हम नहीं कर रहे हैं, अगर सिस्टम कॉल sys_exit है तो हम स्टैक पर कुछ भी धक्का नहीं देने के साथ दूर हो सकते हैं!

mov eax, 1
xor ebx, ebx ;Set the exit status to 0
mov ebp, esp
sysenter

3 या 5 से गुणा करें

पृष्ठभूमि

एक रजिस्टर और एक स्थिरांक के उत्पाद को प्राप्त करने और इसे दूसरे रजिस्टर में संग्रहीत करने के लिए, भोले को ऐसा करना है:

    imul ecx, 3      ; Set ecx to 5 times its previous value
    imul edx, eax, 5 ; Store 5 times the contend of eax in edx

lea प्रयोग करें

गुणा महंगा ऑपरेशन है। शिफ्ट्स और ऐड के संयोजन का उपयोग करना तेज़ है। ३२ या ६४ बिट रजिस्टर जो ३ या ५ द्वारा esp या rsp नहीं है, के कंटेस्टेंट को मेल करने की विशेष स्थिति के लिए, आप अंतिम निर्देश का उपयोग कर सकते हैं। यह उत्पाद की जल्दी गणना करने के लिए पता गणना सर्किट का उपयोग करता है।

    lea ecx, [2*ecx+ecx] ; Load 2*ecx+ecx = 3*ecx into ecx
    lea edx, [4*edx+edx] ; Load 4*edx+edx = 5*edx into edx

कई असेंबलर भी समझेंगे

    lea ecx, [3*ecx]
    lea edx, [5*edx]

सभी संभव गुणकों के लिए उन्हें अन्य ebp या rbp , जिसके परिणामस्वरूप निर्देश imul का उपयोग करने के imul

पेशेवरों

  • बहुत तेजी से निष्पादित करता है

विपक्ष

  • यदि आपका मल्टीप्लैंड ebp या rbp यह imul का उपयोग करके उन्हें एक बाइट लेता है
  • टाइप करने के लिए अधिक अगर आपके कोडांतरक शॉर्टकट का समर्थन नहीं करते हैं
  • एक पाठक के लिए अपारदर्शी तकनीक से अपरिचित है


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow