निर्णय और लूप
डिफ़ॉल्ट रूप से CPU आपके निर्देशों को उसी क्रम में निष्पादित करता है जिस क्रम में वे ऊपर से नीचे दिखाई देते हैं। अपने आप में, वह क्रम कभी कोई चुनाव नहीं कर सकता या काम दोहरा नहीं सकता। एक ब्रांच वह तरीका है जिससे एक प्रोग्राम उस सीधे रास्ते को छोड़ता है: यह एक शर्त की जाँच करता है और, जब शर्त सत्य होती है, तो CPU को अगली पंक्ति के बजाय किसी भिन्न स्थान पर जारी रखने का निर्देश देता है। हर निर्णय और हर लूप इसी एक तंत्र से आता है।
यहाँ कोई if या for नहीं है। आप उन्हें लेबल (नामित स्थान) और ब्रांच (शर्त सत्य होने पर किसी स्थान पर कूदना) से बनाते हैं। एक लेबल एक नाम होता है जिसके बाद : आता है।
यह समझने के लिए कि एक ब्रांच कैसे निष्पादित होती है, आपको प्रोग्राम काउंटर (PC) के बारे में जानना होगा। PC एक विशेष रजिस्टर है, जो आपके कोड से छिपा होता है, जो निष्पादित हो रहे निर्देश का मेमोरी पता रखता है। एक ब्रांच निर्देश PC में एक नया मान लिखता है, इसलिए CPU अपना अगला निर्देश कोड की अगली पंक्ति से नहीं बल्कि आपके लक्ष्य लेबल से प्राप्त करता है।
शाखा परिवार
हर ब्रांच दो रजिस्टरों की तुलना करती है और केवल तब लेबल पर कूदती है जब परीक्षण सत्य होता है। जब परीक्षण विफल होता है, तो निष्पादन अगली पंक्ति पर जारी रहता है। छह परीक्षण मूल बनाते हैं:
beq a, b, label # यदि a == b हो तो शाखा लेंbne a, b, label # यदि a != b हो तो शाखा लेंblt a, b, label # यदि a < b हो तो शाखा लें (साइन सहित)bge a, b, label # यदि a >= b हो तो शाखा लें (साइन सहित)bltu a, b, label # यदि a < b हो तो शाखा लें (बिना साइन)bgeu a, b, label # यदि a >= b हो तो शाखा लें (बिना साइन)
और समानता की जाँच करते हैं और चिह्न की उपेक्षा करते हैं। और क्रम-युग्म बनाते हैं, कम-से-कम और अधिक-या-बराबर, और रजिस्टरों की तुलना साइन्ड संख्याओं के रूप में करते हैं। और वही तुलनाएँ करते हैं लेकिन मानों को अनसाइन्ड मानते हैं, जो उन पतों या गणनाओं के लिए उपयुक्त है जो कभी ऋणात्मक नहीं होते।
साइन्ड और अनसाइन्ड का क्या अर्थ है? एक रजिस्टर 32 बिट रखता है, और वही बिट दो तरह से पढ़े जा सकते हैं। अनसाइन्ड के रूप में पढ़ने पर, वे 0 से लगभग 4 अरब तक एक साधारण पूर्ण संख्या बनाते हैं। साइन्ड के रूप में पढ़ने पर, सबसे ऊपरी बिट ऋण चिह्न के रूप में गिना जाता है, इसलिए आधे बिट पैटर्न ऋणात्मक संख्याओं को दर्शाते हैं। बिट स्वयं नहीं बदलते। केवल आपके पढ़ने का तरीका बदलता है। इसीलिए तुलनाओं के दो समूह हैं: सामान्य संख्याओं के लिए जो ऋणात्मक हो सकती हैं, साइन्ड वाले (, ) उपयोग करें, और उन मानों के लिए जो कभी ऋणात्मक नहीं होते, जैसे मेमोरी पते, अनसाइन्ड वाले (, ) उपयोग करें।
कोई सीधा "ब्रांच इफ ग्रेटर" या "ब्रांच इफ लेस-ऑर-इक्वल" नहीं है। आप उन्हें दो रजिस्टरों की अदला-बदली करके प्राप्त करते हैं, और असेंबलर और को छद्म-ब्रांच के रूप में प्रदान करता है जो आपके लिए अदला-बदली करती हैं, इसलिए बन जाता है। दो और शॉर्टकट: और एक रजिस्टर की शून्य से तुलना करते हैं, और बिना किसी शर्त के कूदता है।
li t0, 0 # योग = 0li t1, 1 # i = 1li t2, 6 # सीमा = 6 (जब तक i < 6 तब तक लूप)loop:bge t1, t2, done # जब i >= 6 हो तो लूप छोड़ेंadd t0, t0, t1 # योग += iaddi t1, t1, 1 # i++j loop # फिर से जाँचने वापस जाएँdone:mv a0, t0 # योग प्रिंट करें (15 होना चाहिए)li a7, 1ecallli a7, 10ecall
इसका अनुसरण करें। t0 चालू योग रखता है (0 से शुरू), t1 काउंटर i रखता है (1 से शुरू), और t2 सीमा 6 रखता है। loop से हर गुज़र में: लूप को छोड़ देता है जब i 6 तक पहुँच जाता है। अन्यथा योग में i जोड़ता है, i को एक से बढ़ाता है, और फिर से परीक्षण के लिए वापस कूदता है। लूप 1, 2, 3, 4, और 5 जोड़ता है, और done कुल 15 प्रिंट करता है।
bge t1 की तुलना t2 से करता है यह तय करने के लिए कि लूप जारी रहेगा या नहीं।
t1 6 हो जाता है, नियंत्रण को done पर स्थानांतरित करता है बजाय शरीर को फिर से चलने देने के। वह परीक्षण ही उस गुज़र को अलग करता है जो दोहराता है उस गुज़र से जो रुकता है।t1 बढ़ता है और प्रोग्राम काउंटर (pc) वापस loop पर कूदता है। हर बार जब pc loop पर लौटता है, ब्रांच शर्त असत्य थी, इसलिए लूप फिर से चलता है।