`Testl` eax खिलाफ बाज?


118

मैं कुछ विधानसभा को समझने की कोशिश कर रहा हूं।

विधानसभा इस प्रकार है, मैं testlलाइन में रुचि रखता हूं :

000319df  8b4508        movl   0x08(%ebp), %eax  
000319e2  8b4004        movl   0x04(%eax), %eax  
000319e5  85c0          testl  %eax, %eax  
000319e7  7407          je     0x000319f0  

मैं के उस बिंदु को समझने के लिए कोशिश कर रहा हूँ testlके बीच %eaxऔर %eax? मुझे लगता है कि यह कोड महत्वपूर्ण नहीं है, मैं सिर्फ अपने साथ परीक्षण को समझने की कोशिश कर रहा हूं - क्या मूल्य हमेशा सच नहीं होगा?

जवाबों:


91

यह परीक्षण करता eaxहै कि 0 है, या ऊपर, या नीचे। इस मामले में, जंप eax0 लिया गया है।


2
मैंने इस लोकप्रिय उत्तर को एक बेहतर विहित उत्तर में बदलने के लिए एक संपादन किया, "यह किस चीज के बारे में है, और यह सीएमपी से कैसे अलग है", जो निहित है। पर्याय JE और JZ के अर्थ के बारे में टिप्पणियों के लिए नीचे दिए गए मेरे स्वयं के उत्तर को देखें। कृपया मेरे संपादन की समीक्षा करें क्योंकि यह बहुत महत्वपूर्ण है, और यह अभी भी आपका उत्तर है।
पीटर कॉर्डेस

@PeterCordes मैं इरादे की सराहना करता हूं, लेकिन मैं आपके संपादन को वापस करने जा रहा हूं। 1. आपकी "आवाज़" मेरी से बहुत अलग है, और अभी यह मेरे जवाब की तुलना में बहुत अधिक पढ़ती है। 2. अधिक समस्यापूर्ण मुखरता है कि झंडे के बीच testऔर उसी तरह से बाहर आते हैं cmp। हां, मैं समझता हूं कि कोडी के लिए आपकी टिप्पणियों के आधार पर आपका विश्वास है। हालाँकि, इसे मेरी पोस्ट में डालना अलग बात है; यह एक जोर है कि मैं इसके लिए खड़ा होना चाहता हूं, सिर्फ इसलिए कि मुझे नहीं पता कि यह सभी मामलों में समान है।
क्रिस जस्टर-यंग

1
@PeterCordes अगर मुझे कुछ खाली समय मिलता है, तो मैं इस जवाब को अधिक विहित करने के लिए मांस देना चाहता हूं। मैं इसे वैसे ही लिखूंगा जैसे मैं इसे लिखता हूं, और मैं इस बारे में काफी विशिष्ट हूं कि मैं कैसे चीजें लिखता हूं। :-) उदाहरण के लिए, मैं लिखते हैं je, jz, cmp, और test, और नहीं जेई, JZ, सीएमपी, या परीक्षा। मैं उस तरह picky हूँ।
क्रिस जस्टर-यंग

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

2
वाह, इस सवाल के अपने जवाब को संपादित करने के बाद कि मैंने आपके साथ क्या जोड़ा, मुझे एहसास हुआ कि मैंने जून में जो कुछ लिखा था, उसमें से लगभग सभी को मैंने दोहराया था। ऊप्स! मैंने अपने दावे का समर्थन करने के लिए इसे अधिक तर्क के साथ अद्यतन किया test a,aऔर cmp $0,aझंडे को पहचानने के लिए सेट किया; यह इंगित करने के लिए धन्यवाद कि यह एक गैर-तुच्छ दावा है। पुन: परीक्षण बनाम test: हाल ही में मैंने इंटेल के मैनुअल की तरह सभी-कैप्स का उपयोग करना शुरू कर दिया है। लेकिन जब मैं AT & T mnemonics बनाम Intel mnemonics के बारे में बात कर रहा हूं, मैं testbAT & T के लिए शैली का उपयोग करता हूं । IDK यदि पठनीयता में मदद करता है।
पीटर कॉर्ड्स

90

का अर्थ testहै एक साथ तर्क और शून्य के लिए परिणाम की जांच करना। तो यह कोड परीक्षण करता है कि क्या EAX शून्य है या नहीं। jeशून्य होगा तो कूद जाएगा।

BTW, यह एक छोटा निर्देश उत्पन्न करता है cmp eax, 0जिसके कारण यह है कि संकलक आमतौर पर इस तरह से करेंगे।


34

परीक्षण निर्देश ऑपरेंड के बीच एक तार्किक AND- ऑपरेशन करता है, लेकिन परिणाम को एक रजिस्टर में वापस नहीं लिखता है। केवल झंडे अपडेट किए गए हैं।

आपके उदाहरण में टेस्ट ईरेक्स, ईएक्सएक्स शून्य ध्वज सेट करेगा यदि ईएक्सएक्स शून्य है, साइन-फ्लैग यदि उच्चतम बिट सेट और कुछ अन्य झंडे भी।

यदि ज़ीरो फ़्लैग सेट किया गया है तो जंप यदि समान (je) निर्देश कूदता है।

आप कोड को इस तरह अधिक पठनीय कोड में अनुवाद कर सकते हैं:

cmp eax, 0
je  somewhere

इसकी कार्यक्षमता समान है लेकिन कुछ बाइट्स के लिए अधिक कोड-स्थान की आवश्यकता होती है। यही कारण है कि कंपाइलर ने तुलना के बजाय एक परीक्षण का उत्सर्जन किया।


3
दरअसल, cmp वहां काम नहीं कर सकता है। यही है, यह प्रस्तुत विशिष्ट मामले के लिए काम करता है, लेकिन सीएमपी झंडे को परीक्षण के मुकाबले अलग तरीके से प्रभावित करता है, इसके कारण इसके बजाय आंतरिक उप है। मन में कुछ रखने के लिए।
कोड़ी ब्रोक्स

4
शून्य के खिलाफ परीक्षण के लिए यह पूरी तरह से मान्य है।
निल्स पिपेनब्रिनक सिप 29'08

3
लेकिन आपको नहीं पता कि बाद में झंडे में और क्या दिखता है। झंडे पर प्रभाव बहुत अलग हैं, इसलिए यह एक मुद्दा हो सकता है और बहुत बार होता है।
कोड़ी ब्रोक्स

2
नहीं, एकमात्र झंडे जो किसी भिन्न / विधि / सेट द्वारा कैरी किए जाते हैं और ओवरफ्लो होते हैं, दोनों को अन्य झंडे के 0. / मान / मान पर सेट किया जाएगा, क्योंकि cmp उप और परीक्षण का उपयोग करता है और।
कोडी ब्रोशर

2
@CodyBrocious: test eax, eaxऔर cmp eax, 0दोनों ने सभी झंडे सेट किए, और उन्हें समान मूल्यों पर सेट किया। दोनों निर्देशों ने "परिणाम के अनुसार" सभी झंडे लगाए। घटाना 0कभी भी कैरी या ओवरफ्लो उत्पन्न नहीं कर सकता है। आपका तर्क 0 के अलावा किसी भी अन्य के लिए सही है, लेकिन
0.50 के

22

testयह पसंद है and, सिवाय इसके कि यह केवल FLAGS लिखता है, इसके दोनों इनपुटों को बिना अनुमति के छोड़ देता है। दो अलग-अलग इनपुटों के साथ, यह परीक्षण के लिए उपयोगी है कि कुछ बिट्स सभी शून्य हैं, या यदि कम से कम एक सेट है। (उदाहरण के लिए test al, 3सेट ZF अगर EAX 4 का एक गुणक है (और इस प्रकार इसके निम्न 2 बिट्स शून्य हैं)।


test eax,eaxसभी झंडों को ठीक उसी तरह सेट करता है जिस तरह से cmp eax, 0होगा :

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


परीक्षण छोटा है (तत्काल नहीं) और कभी-कभी तेज (सीएमपी से अधिक मामलों में अधिक सीपीयू पर एक तुलना-और-शाखा के ऊपर मैक्रो-फ्यूज कर सकता है)। यह testशून्य के खिलाफ रजिस्टर की तुलना के लिए पसंदीदा मुहावरा बनाता है । यह एक peephole अनुकूलन है जिसके लिए cmp reg,0आप अर्थ अर्थ की परवाह किए बिना उपयोग कर सकते हैं।

तत्काल 0 के साथ सीएमपी का उपयोग करने का एकमात्र सामान्य कारण यह है कि आप मेमोरी ऑपरेंड के खिलाफ तुलना करना चाहते हैं। उदाहरण के लिए, cmpb $0, (%esi)एक अंतर्निहित लंबाई सी-स्टाइल स्ट्रिंग के अंत में एक शून्य शून्य बाइट की जांच करने के लिए।


AVX512F जोड़ता हैkortestw k1, k2 और AVX512DQ / BW (Skylake-X लेकिन KNL नहीं) जोड़ते हैं ktestb/w/d/q k1, k2, जो AVX512 मास्क रजिस्टरों (k0..k7) पर काम करते हैं , लेकिन फिर भी नियमित FLAGS सेट करते हैं test, उसी तरह जैसे कि पूर्णांक ORया ANDनिर्देश करते हैं। (SSE4 ptestया SSE की तरह क्रमबद्ध करें ucomiss: SIMD डोमेन में इनपुट और पूर्णांक फ्लैग में परिणाम।)

kortestw k1,k1एक AVX512 परिणाम की तुलना SSE / AVX2 (v)pmovmskb/ps/pd+ testया के आधार पर शाखा / cmovcc / setcc के लिए मुहावरेदार तरीका है cmp


jzबनाम का उपयोग jeभ्रामक हो सकता है।

jzऔर jeशाब्दिक रूप से एक ही निर्देश है , यानी मशीन कोड में एक ही ओपकोड। वे एक ही काम करते हैं, लेकिन मनुष्यों के लिए अलग अर्थ हैं । Disassembler (और आम तौर पर कंपाइलर से asm आउटपुट) केवल एक का उपयोग करेगा, इसलिए शब्दार्थ भेद खो गया है।

cmpऔर subZF तब सेट करें जब उनके दो इनपुट बराबर हों (यानी घटाव परिणाम 0 हो)। je(कूदो यदि बराबर) शब्दार्थिक रूप से प्रासंगिक पर्यायवाची है।

test %eax,%eaxand %eax,%eaxपरिणाम शून्य होने पर / फिर ZF सेट करता है, लेकिन कोई "समानता" परीक्षण नहीं है। परीक्षण के बाद ZF आपको यह नहीं बताता है कि दोनों ऑपरेंड समान थे या नहीं। तो jz(शून्य से कूदो) शब्दार्थ प्रासंगिक पर्यायवाची है।


मैं testबिटवाइज़ andऑपरेशन के बारे में बुनियादी जानकारी को जोड़ने पर विचार करूंगा , हो सकता है कि लोग केवल विधानसभा सीखने के लिए स्पष्ट नहीं हों (और निर्देशन गाइड गाइड को हर 60 सेकंड में जांचने के लिए आलसी / अनजान हो;) :)।
पेड

1
@ Ped7g: काफी उचित है, मुझे लगता है कि इस जवाब में सब कुछ डालने के बजाय उस हिस्से को अन्य उत्तरों पर छोड़ने के लिए चोट नहीं पहुंचती है। AVX512 को जोड़ा kortest*और ktest*जब मैं उस पर था।
पीटर कॉर्ड्स

BTW, यह मूल रूप से उसी प्रश्न के दूसरे संस्करण के लिए मेरे उत्तर के समान है , लेकिन मैंने कहा कि प्रदर्शन के बारे में अधिक सामान, उदाहरण के लिए, समान मूल्य के साथ रजिस्टर को फिर से लिखकर नेहेलम जैसे पुराने पी 6-परिवार सीपीयू पर रजिस्टर-स्टॉल से बचने के लिए।
पीटर कॉर्ड्स

@PeterCordes यह स्वीकृत उत्तर होना चाहिए: संपूर्ण और तकनीकी। स्वीकृत पद के विपरीत, यह ज्ञान के प्रति जिज्ञासा और प्यास को बुझाता है। सर रख लो।
प्रोग्रामर

यह ध्यान दिया जाना चाहिए कि पीएफ कम 8 बिट्स की समता पर सेट है, जो इस मामले में एएल है।
ecm

5

कोड का यह स्निपेट एक सबरूटीन से है जो किसी चीज़ को, शायद कुछ संरचना या वस्तु को एक संकेतक दिया गया था। दूसरी पंक्ति के डेरेफेरर्स जो पॉइंटर, उस चीज़ से एक मूल्य प्राप्त कर रहे हैं - संभवतः खुद एक पॉइंटर या शायद सिर्फ एक इंट, इसके 2 सदस्य (ऑफसेट +4) के रूप में संग्रहीत। तीसरी और चौथी पंक्ति शून्य के लिए इस मान का परीक्षण करती है (NULL अगर यह एक पॉइंटर है) और शून्य होने पर निम्नलिखित कुछ ऑपरेशन (नहीं दिखाए गए) को छोड़ दें।

शून्य के लिए परीक्षण को कभी-कभी तात्कालिक शाब्दिक शून्य मान की तुलना में कोडित किया जाता है, लेकिन संकलक (या मानव?) जिसने यह लिखा है कि एक अंडकोष सेशन तेजी से चलेगा - पाइपलाइनिंग और रजिस्टर जैसे सभी आधुनिक सीपीयू सामान को ध्यान में रखते हुए सोचा होगा। नाम बदलने। यह उसी ट्रिक्स के बैग से है जो XOR EAX, EAX (जिसे मैंने कोलोराडो में किसी की लाइसेंस प्लेट पर देखा है!) के साथ एक रजिस्टर को क्लियर करने का विचार स्पष्ट है, लेकिन शायद इसके बजाय MOV EAX, # 0 (मैं एक पुराने नोटेशन का उपयोग करता हूं! )।

Asm में, perl की तरह, TMTOWTDI।


3

यदि ईएक्स शून्य है तो यह सशर्त कूद प्रदर्शन करेगा, अन्यथा यह 319e9 पर निष्पादन जारी रखेगा


0

कुछ कार्यक्रमों में उन्हें बफर ओवरफ्लो की जांच के लिए इस्तेमाल किया जा सकता है। आवंटित स्थान के शीर्ष पर 0 रखा गया है। स्टैक में डेटा इनपुट करने के बाद, यह आवंटित स्थान के बहुत शुरुआत में यह सुनिश्चित करने के लिए दिखता है कि आवंटित स्थान अतिप्रवाहित नहीं है।

यह अति-प्रवाह और अगर वहाँ नहीं था और वहाँ एक शून्य था, तो यह जांचने के लिए कि यह अभ्यास-अभ्यास के स्टैक0 अभ्यास में उपयोग किया गया था, यह "फिर से प्रयास करें" प्रदर्शित करेगा

0x080483f4 <main+0>:    push   ebp
0x080483f5 <main+1>:    mov    ebp,esp
0x080483f7 <main+3>:    and    esp,0xfffffff0
0x080483fa <main+6>:    sub    esp,0x60                     
0x080483fd <main+9>:    mov    DWORD PTR [esp+0x5c],0x0 ;puts a zero on stack
0x08048405 <main+17>:   lea    eax,[esp+0x1c]
0x08048409 <main+21>:   mov    DWORD PTR [esp],eax
0x0804840c <main+24>:   call   0x804830c <gets@plt>
0x08048411 <main+29>:   mov    eax,DWORD PTR [esp+0x5c] 
0x08048415 <main+33>:   test   eax,eax                  ; checks if its zero
0x08048417 <main+35>:   je     0x8048427 <main+51>
0x08048419 <main+37>:   mov    DWORD PTR [esp],0x8048500 
0x08048420 <main+44>:   call   0x804832c <puts@plt>
0x08048425 <main+49>:   jmp    0x8048433 <main+63>
0x08048427 <main+51>:   mov    DWORD PTR [esp],0x8048529
0x0804842e <main+58>:   call   0x804832c <puts@plt>
0x08048433 <main+63>:   leave
0x08048434 <main+64>:   ret

मैं यह नहीं देखता कि गैर-शून्य के लिए रजिस्टर की जांच करने का यह विशिष्ट मामला इस प्रश्नोत्तर में क्या है। विशेष रूप से तब cmp DWORD PTR [esp+0x5c], 0/ जब jz 0x8048427 <main+51>एक अलग एमओवी-लोड और फिर टेस्ट से अधिक कुशल होता। शून्य के लिए जाँच के लिए यह शायद ही एक सामान्य उपयोग-मामला है।
पीटर कॉर्ड्स

-4

हम jgjle देख सकते हैं यदि testl %edx,%edx. jle .L3हम आसानी से देख सकते हैं कि jle सूट है (SF^OF)|ZF, यदि% edx शून्य है, ZF = 1, लेकिन यदि% edx शून्य नहीं है और -1 है, तो Testl के बाद, OF = 0, और SF = 1, इसलिए झंडा = सत्य, जो कि कूद को लागू करता है। अंग्रेजी, मेरी अंग्रेजी खराब है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.