Introduction to ARM64v8
अपवाद स्तर - EL (ARM64v8)
ARMv8 आर्किटेक्चर में, निष्पादन स्तर, जिसे अपवाद स्तर (ELs) के रूप में जाना जाता है, निष्पादन वातावरण के विशेषाधिकार स्तर और क्षमताओं को परिभाषित करता है। चार अपवाद स्तर हैं, जो EL0 से EL3 तक फैले हुए हैं, प्रत्येक का एक अलग उद्देश्य है:
EL0 - उपयोगकर्ता मोड:
यह सबसे कम विशेषाधिकार स्तर है और नियमित एप्लिकेशन कोड निष्पादित करने के लिए उपयोग किया जाता है।
EL0 पर चलने वाले एप्लिकेशन एक-दूसरे और सिस्टम सॉफ़्टवेयर से अलग होते हैं, जिससे सुरक्षा और स्थिरता बढ़ती है।
EL1 - ऑपरेटिंग सिस्टम कर्नेल मोड:
अधिकांश ऑपरेटिंग सिस्टम कर्नेल इस स्तर पर चलते हैं।
EL1 के पास EL0 की तुलना में अधिक विशेषाधिकार होते हैं और यह सिस्टम संसाधनों तक पहुँच सकता है, लेकिन सिस्टम की अखंडता सुनिश्चित करने के लिए कुछ प्रतिबंधों के साथ।
EL2 - हाइपरवाइजर मोड:
यह स्तर वर्चुअलाइजेशन के लिए उपयोग किया जाता है। EL2 पर चलने वाला एक हाइपरवाइजर एक ही भौतिक हार्डवेयर पर कई ऑपरेटिंग सिस्टम (प्रत्येक अपने EL1 में) का प्रबंधन कर सकता है।
EL2 वर्चुअलाइज्ड वातावरण के लिए अलगाव और नियंत्रण की सुविधाएँ प्रदान करता है।
EL3 - सुरक्षित मॉनिटर मोड:
यह सबसे अधिक विशेषाधिकार स्तर है और अक्सर सुरक्षित बूटिंग और विश्वसनीय निष्पादन वातावरण के लिए उपयोग किया जाता है।
EL3 सुरक्षित और गैर-सुरक्षित राज्यों (जैसे सुरक्षित बूट, विश्वसनीय OS, आदि) के बीच पहुँच को प्रबंधित और नियंत्रित कर सकता है।
इन स्तरों का उपयोग विभिन्न सिस्टम पहलुओं को प्रबंधित करने के लिए एक संरचित और सुरक्षित तरीके की अनुमति देता है, उपयोगकर्ता एप्लिकेशन से लेकर सबसे विशेषाधिकार प्राप्त सिस्टम सॉफ़्टवेयर तक। ARMv8 का विशेषाधिकार स्तरों के प्रति दृष्टिकोण विभिन्न सिस्टम घटकों को प्रभावी ढंग से अलग करने में मदद करता है, जिससे सिस्टम की सुरक्षा और मजबूती बढ़ती है।
रजिस्टर (ARM64v8)
ARM64 में 31 सामान्य-उद्देश्य रजिस्टर होते हैं, जिन्हें x0
से x30
तक लेबल किया गया है। प्रत्येक एक 64-बिट (8-बाइट) मान संग्रहीत कर सकता है। जिन ऑपरेशनों के लिए केवल 32-बिट मान की आवश्यकता होती है, उन रजिस्टरों को 32-बिट मोड में w0 से w30 के नामों का उपयोग करके एक्सेस किया जा सकता है।
x0
सेx7
- ये आमतौर पर स्क्रैच रजिस्टर के रूप में और उपरूटीन में पैरामीटर पास करने के लिए उपयोग किए जाते हैं।
x0
एक फ़ंक्शन का लौटने वाला डेटा भी ले जाता है।
x8
- लिनक्स कर्नेल में,x8
svc
निर्देश के लिए सिस्टम कॉल नंबर के रूप में उपयोग किया जाता है। macOS में x16 का उपयोग किया जाता है!x9
सेx15
- अधिक अस्थायी रजिस्टर, अक्सर स्थानीय चर के लिए उपयोग किए जाते हैं।x16
औरx17
- इंट्रा-प्रोसीजुरल कॉल रजिस्टर। तात्कालिक मानों के लिए अस्थायी रजिस्टर। इन्हें अप्रत्यक्ष फ़ंक्शन कॉल और PLT (प्रोसीजर लिंक टेबल) स्टब के लिए भी उपयोग किया जाता है।
x16
svc
निर्देश के लिए सिस्टम कॉल नंबर के रूप में macOS में उपयोग किया जाता है।
x18
- प्लेटफ़ॉर्म रजिस्टर। इसे सामान्य-उद्देश्य रजिस्टर के रूप में उपयोग किया जा सकता है, लेकिन कुछ प्लेटफार्मों पर, यह रजिस्टर प्लेटफॉर्म-विशिष्ट उपयोगों के लिए आरक्षित है: विंडोज़ में वर्तमान थ्रेड वातावरण ब्लॉक के लिए पॉइंटर, या वर्तमान लिनक्स कर्नेल में निष्पादित कार्य संरचना को इंगित करने के लिए।x19
सेx28
- ये कॉल-सेव किए गए रजिस्टर हैं। एक फ़ंक्शन को अपने कॉलर के लिए इन रजिस्टरों के मानों को संरक्षित करना चाहिए, इसलिए इन्हें स्टैक में संग्रहीत किया जाता है और कॉलर पर वापस जाने से पहले पुनर्प्राप्त किया जाता है।x29
- फ्रेम पॉइंटर स्टैक फ्रेम को ट्रैक करने के लिए। जब एक नया स्टैक फ्रेम बनाया जाता है क्योंकि एक फ़ंक्शन को कॉल किया जाता है, तोx29
रजिस्टर स्टैक में संग्रहीत किया जाता है और नया फ्रेम पॉइंटर पता (sp
पता) इस रजिस्टर में संग्रहीत किया जाता है।
इस रजिस्टर का उपयोग एक सामान्य-उद्देश्य रजिस्टर के रूप में भी किया जा सकता है, हालांकि इसे आमतौर पर स्थानीय चर के संदर्भ के रूप में उपयोग किया जाता है।
x30
याlr
- लिंक रजिस्टर। यह एकBL
(ब्रांच विद लिंक) याBLR
(ब्रांच विद लिंक टू रजिस्टर) निर्देश के निष्पादन के समय रिटर्न पता रखता है,pc
मान को इस रजिस्टर में संग्रहीत करके।
इसे किसी अन्य रजिस्टर की तरह भी उपयोग किया जा सकता है।
यदि वर्तमान फ़ंक्शन एक नए फ़ंक्शन को कॉल करने जा रहा है और इसलिए
lr
को ओवरराइट करेगा, तो यह इसे स्टैक में शुरुआत में संग्रहीत करेगा, यह उपसंहार है (stp x29, x30 , [sp, #-48]; mov x29, sp
->fp
औरlr
को स्टोर करें, स्थान बनाएं और नयाfp
प्राप्त करें) और अंत में इसे पुनर्प्राप्त करें, यह प्रस्तावना है (ldp x29, x30, [sp], #48; ret
->fp
औरlr
को पुनर्प्राप्त करें और लौटें)।
sp
- स्टैक पॉइंटर, जिसका उपयोग स्टैक के शीर्ष को ट्रैक करने के लिए किया जाता है।
sp
मान को हमेशा कम से कम एक क्वाडवर्ड संरेखण पर रखा जाना चाहिए, अन्यथा एक संरेखण अपवाद हो सकता है।
pc
- प्रोग्राम काउंटर, जो अगले निर्देश की ओर इशारा करता है। इस रजिस्टर को केवल अपवाद उत्पन्न करने, अपवाद लौटाने और शाखाओं के माध्यम से अपडेट किया जा सकता है। इस रजिस्टर को पढ़ने के लिए केवल सामान्य निर्देश शाखा के साथ लिंक निर्देश (BL, BLR) हैं, जोpc
पता कोlr
(लिंक रजिस्टर) में संग्रहीत करते हैं।xzr
- ज़ीरो रजिस्टर। इसे 32-बिट रजिस्टर रूप मेंwzr
भी कहा जाता है। इसका उपयोग आसानी से शून्य मान प्राप्त करने के लिए (सामान्य ऑपरेशन) याsubs
का उपयोग करके तुलना करने के लिए किया जा सकता है जैसेsubs XZR, Xn, #10
परिणामस्वरूप डेटा को कहीं भी संग्रहीत किए बिना (xzr
में)।
Wn
रजिस्टर Xn
रजिस्टर का 32-बिट संस्करण हैं।
SIMD और फ्लोटिंग-पॉइंट रजिस्टर
इसके अलावा, 128-बिट लंबाई के 32 रजिस्टर हैं, जिन्हें अनुकूलित सिंगल इंस्ट्रक्शन मल्टीपल डेटा (SIMD) ऑपरेशनों में और फ्लोटिंग-पॉइंट अंकगणित करने के लिए उपयोग किया जा सकता है। इन्हें Vn रजिस्टर कहा जाता है, हालांकि वे 64-बिट, 32-बिट, 16-बिट और 8-बिट में भी काम कर सकते हैं और तब इन्हें Qn
, Dn
, Sn
, Hn
और Bn
कहा जाता है।
सिस्टम रजिस्टर
सैकड़ों सिस्टम रजिस्टर हैं, जिन्हें विशेष-उद्देश्य रजिस्टर (SPRs) भी कहा जाता है, जो प्रोसेसर के व्यवहार की निगरानी और नियंत्रण के लिए उपयोग किए जाते हैं।
इन्हें केवल समर्पित विशेष निर्देश mrs
और msr
का उपयोग करके पढ़ा या सेट किया जा सकता है।
विशेष रजिस्टर TPIDR_EL0
और TPIDDR_EL0
आमतौर पर रिवर्स इंजीनियरिंग करते समय पाए जाते हैं। EL0
उपसर्ग उस न्यूनतम अपवाद को इंगित करता है जिससे रजिस्टर को एक्सेस किया जा सकता है (इस मामले में EL0 नियमित अपवाद (विशेषाधिकार) स्तर है जिस पर नियमित प्रोग्राम चलते हैं)।
इनका उपयोग आमतौर पर थ्रेड-स्थानीय भंडारण मेमोरी क्षेत्र के बेस पते को संग्रहीत करने के लिए किया जाता है। आमतौर पर पहला EL0 में चलने वाले प्रोग्राम के लिए पढ़ने और लिखने योग्य होता है, लेकिन दूसरा EL0 से पढ़ा जा सकता है और EL1 (जैसे कर्नेल) से लिखा जा सकता है।
mrs x0, TPIDR_EL0 ; TPIDR_EL0 को x0 में पढ़ें
msr TPIDR_EL0, X0 ; x0 को TPIDR_EL0 में लिखें
PSTATE
PSTATE में कई प्रक्रिया घटक होते हैं जो ऑपरेटिंग-सिस्टम-दृश्यमान SPSR_ELx
विशेष रजिस्टर में अनुक्रमित होते हैं, X वह अनुमति स्तर है जिस पर अपवाद उत्पन्न होता है (यह अपवाद समाप्त होने पर प्रक्रिया की स्थिति को पुनर्प्राप्त करने की अनुमति देता है)।
ये सुलभ क्षेत्र हैं:
N
,Z
,C
औरV
स्थिति ध्वज:N
का अर्थ है कि ऑपरेशन ने नकारात्मक परिणाम दियाZ
का अर्थ है कि ऑपरेशन ने शून्य दियाC
का अर्थ है कि ऑपरेशन ने कैरी कियाV
का अर्थ है कि ऑपरेशन ने साइन ओवरफ्लो दिया:दो सकारात्मक संख्याओं का योग नकारात्मक परिणाम देता है।
दो नकारात्मक संख्याओं का योग सकारात्मक परिणाम देता है।
घटाव में, जब एक बड़ा नकारात्मक संख्या एक छोटे सकारात्मक संख्या (या इसके विपरीत) से घटाई जाती है, और परिणाम को दिए गए बिट आकार की सीमा के भीतर प्रदर्शित नहीं किया जा सकता है।
स्पष्ट रूप से प्रोसेसर नहीं जानता कि ऑपरेशन साइन किया गया है या नहीं, इसलिए यह ऑपरेशनों में C और V की जांच करेगा और संकेत देगा कि यदि कैरी हुआ था तो यह साइन किया गया था या असाइन किया गया था।
सभी निर्देश इन ध्वजों को अपडेट नहीं करते हैं। कुछ जैसे CMP
या TST
करते हैं, और अन्य जिनके पास s उपसर्ग होता है जैसे ADDS
भी ऐसा करते हैं।
वर्तमान रजिस्टर चौड़ाई (
nRW
) ध्वज: यदि ध्वज का मान 0 है, तो प्रोग्राम फिर से शुरू होने पर AArch64 निष्पादन स्थिति में चलेगा।वर्तमान अपवाद स्तर (
EL
): EL0 में चलने वाला एक नियमित प्रोग्राम का मान 0 होगा।सिंगल स्टेपिंग ध्वज (
SS
): डिबगर्स द्वारा सिंगल स्टेप करने के लिए उपयोग किया जाता है,SPSR_ELx
के भीतर SS ध्वज को 1 पर सेट करके एक अपवाद के माध्यम से। प्रोग्राम एक कदम चलेगा और एक सिंगल स्टेप अपवाद उत्पन्न करेगा।अवैध अपवाद स्थिति ध्वज (
IL
): इसका उपयोग तब किया जाता है जब एक विशेषाधिकार प्राप्त सॉफ़्टवेयर एक अवैध अपवाद स्तर स्थानांतरण करता है, यह ध्वज 1 पर सेट किया जाता है और प्रोसेसर एक अवैध स्थिति अपवाद उत्पन्न करता है।DAIF
ध्वज: ये ध्वज एक विशेषाधिकार प्राप्त प्रोग्राम को कुछ बाहरी अपवादों को चयनात्मक रूप से मास्क करने की अनुमति देते हैं।यदि
A
1 है, तो इसका अर्थ है कि असिंक्रोनस एबॉर्ट्स उत्पन्न होंगे।I
बाहरी हार्डवेयर इंटरप्ट रिक्वेस्ट (IRQs) का उत्तर देने के लिए कॉन्फ़िगर करता है। और F फास्ट इंटरप्ट रिक्वेस्ट (FIRs) से संबंधित है।स्टैक पॉइंटर चयन ध्वज (
SPS
): EL1 और उससे ऊपर चलने वाले विशेषाधिकार प्राप्त प्रोग्राम अपने स्वयं के स्टैक पॉइंटर रजिस्टर और उपयोगकर्ता-मॉडल वाले के बीच स्विच कर सकते हैं (जैसेSP_EL1
औरEL0
के बीच)। यह स्विचिंगSPSel
विशेष रजिस्टर में लिखकर की जाती है। इसे EL0 से नहीं किया जा सकता।
कॉलिंग कन्वेंशन (ARM64v8)
ARM64 कॉलिंग कन्वेंशन निर्दिष्ट करता है कि एक फ़ंक्शन के लिए पहले आठ पैरामीटर रजिस्टर x0
से x7
में पास किए जाते हैं। अतिरिक्त पैरामीटर स्टैक पर पास किए जाते हैं। रिटर्न मान रजिस्टर x0
में वापस पास किया जाता है, या x1
में भी यदि यह 128 बिट लंबा है। x19
से x30
और sp
रजिस्टर को फ़ंक्शन कॉल के बीच संरक्षित किया जाना चाहिए।
जब असेंबली में एक फ़ंक्शन पढ़ते हैं, तो फ़ंक्शन प्रस्तावना और उपसंहार की तलाश करें। प्रस्तावना आमतौर पर फ्रेम पॉइंटर (x29
) को सहेजने, नए फ्रेम पॉइंटर को सेट करने, और स्टैक स्पेस आवंटित करने में शामिल होती है। उपसंहार आमतौर पर सहेजे गए फ्रेम पॉइंटर को पुनर्स्थापित करने और फ़ंक्शन से लौटने में शामिल होती है।
स्विफ्ट में कॉलिंग कन्वेंशन
स्विफ्ट में अपनी कॉलिंग कन्वेंशन है जिसे https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64 में पाया जा सकता है।
सामान्य निर्देश (ARM64v8)
ARM64 निर्देश आमतौर पर फॉर्मेट opcode dst, src1, src2
में होते हैं, जहाँ opcode
वह ऑपरेशन है जिसे किया जाना है (जैसे add
, sub
, mov
, आदि), dst
वह गंतव्य रजिस्टर है जहाँ परिणाम संग्रहीत किया जाएगा, और src1
और src2
वह स्रोत रजिस्टर हैं। तात्कालिक मानों का भी स्रोत रजिस्टर के स्थान पर उपयोग किया जा सकता है।
mov
: एक रजिस्टर से दूसरे में मान स्थानांतरित करें।उदाहरण:
mov x0, x1
— यह मान कोx1
सेx0
में स्थानांतरित करता है।ldr
: मेमोरी से एक मान को रजिस्टर में लोड करें।उदाहरण:
ldr x0, [x1]
— यहx1
द्वारा इंगित मेमोरी स्थान से एक मान कोx0
में लोड करता है।ऑफसेट मोड: एक ऑफसेट जो ओरिजिन पॉइंटर को प्रभावित करता है, उदाहरण के लिए:
ldr x2, [x1, #8]
, यह x2 में x1 + 8 से मान लोड करेगा।ldr x2, [x0, x1, lsl #2]
, यह x2 में x0 के ऐरे से एक वस्तु लोड करेगा, स्थिति x1 (सूचकांक) * 4 से।पूर्व-सूचकांक मोड: यह ओरिजिन पर गणनाएँ लागू करेगा, परिणाम प्राप्त करेगा और नए ओरिजिन को भी ओरिजिन में संग्रहीत करेगा।
ldr x2, [x1, #8]!
, यहx1 + 8
कोx2
में लोड करेगा औरx1
मेंx1 + 8
का परिणाम संग्रहीत करेगा।str lr, [sp, #-4]!
, लिंक रजिस्टर को sp में संग्रहीत करें और रजिस्टर sp को अपडेट करें।पोस्ट-सूचकांक मोड: यह पिछले वाले की तरह है लेकिन मेमोरी पते को एक्सेस किया जाता है और फिर ऑफसेट की गणना की जाती है और संग्रहीत की जाती है।
ldr x0, [x1], #8
,x1
कोx0
में लोड करें औरx1
कोx1 + 8
के साथ अपडेट करें।PC-सापेक्ष पता लगाना: इस मामले में लोड करने के लिए पता PC रजिस्टर के सापेक्ष गणना की जाती है।
ldr x1, =_start
, यह_start
प्रतीक के प्रारंभ होने का पता x1 में लोड करेगा जो वर्तमान PC से संबंधित है।str
: एक रजिस्टर से मेमोरी में मान स्टोर करें।उदाहरण:
str x0, [x1]
— यहx0
में मान कोx1
द्वारा इंगित मेमोरी स्थान में संग्रहीत करता है।ldp
: रजिस्टर के जोड़े को लोड करें। यह निर्देश दो रजिस्टर को लगातार मेमोरी स्थानों से लोड करता है। मेमोरी पता आमतौर पर किसी अन्य रजिस्टर में मान के साथ एक ऑफसेट जोड़कर बनाया जाता है।उदाहरण:
ldp x0, x1, [x2]
— यहx0
औरx1
कोx2
औरx2 + 8
पर मेमोरी स्थानों से लोड करता है।stp
: रजिस्टर के जोड़े को स्टोर करें। यह निर्देश दो रजिस्टर को लगातार मेमोरी स्थानों में संग्रहीत करता है। मेमोरी पता आमतौर पर किसी अन्य रजिस्टर में मान के साथ एक ऑफसेट जोड़कर बनाया जाता है।उदाहरण:
stp x0, x1, [sp]
— यहx0
औरx1
कोsp
औरsp + 8
पर मेमोरी स्थानों में संग्रहीत करता है।stp x0, x1, [sp, #16]!
— यहx0
औरx1
कोsp+16
औरsp + 24
पर मेमोरी स्थानों में संग्रहीत करता है, औरsp
कोsp+16
के साथ अपडेट करता है।add
: दो रजिस्टरों के मानों को जोड़ें और परिणाम को एक रजिस्टर में संग्रहीत करें।सिंटैक्स: add(s) Xn1, Xn2, Xn3 | #imm, [shift #N | RRX]
Xn1 -> गंतव्य
Xn2 -> ऑपरेन्ड 1
Xn3 | #imm -> ऑपरेन्ड 2 (रजिस्टर या तात्कालिक)
[shift #N | RRX] -> एक शिफ्ट करें या RRX कॉल करें
उदाहरण:
add x0, x1, x2
— यहx1
औरx2
में मानों को जोड़ता है और परिणाम कोx0
में संग्रहीत करता है।add x5, x5, #1, lsl #12
— यह 4096 के बराबर है (1 को 12 बार शिफ्ट करना) -> 1 0000 0000 0000 0000adds
यह एकadd
करता है और ध्वज को अपडेट करता है।sub
: दो रजिस्टरों के मानों को घटाएं और परिणाम को एक रजिस्टर में संग्रहीत करें।add
सिंटैक्स की जांच करें।उदाहरण:
sub x0, x1, x2
— यहx2
के मान कोx1
से घटाता है और परिणाम कोx0
में संग्रहीत करता है।subs
यह घटाव की तरह है लेकिन ध्वज को अपडेट करता है।mul
: दो रजिस्टरों के मानों को गुणा करें और परिणाम को एक रजिस्टर में संग्रहीत करें।उदाहरण:
mul x0, x1, x2
— यहx1
औरx2
में मानों को गुणा करता है और परिणाम कोx0
में संग्रहीत करता है।div
: एक रजिस्टर के मान को दूसरे से विभाजित करें और परिणाम को एक रजिस्टर में संग्रहीत करें।उदाहरण:
div x0, x1, x2
— यहx1
के मान कोx2
से विभाजित करता है और परिणाम कोx0
में संग्रहीत करता है।lsl
,lsr
,asr
,ror
,rrx
:लॉजिकल शिफ्ट लेफ्ट: अंत से 0 जोड़ें और अन्य बिट्स को आगे बढ़ाएं (n-बार 2 से गुणा करें)
लॉजिकल शिफ्ट राइट: शुरुआत में 1 जोड़ें और अन्य बिट्स को पीछे की ओर बढ़ाएं (unsigned में n-बार 2 से विभाजित करें)
अर्थमैटिक शिफ्ट राइट:
lsr
की तरह, लेकिन यदि सबसे महत्वपूर्ण बिट 1 है, तो 0 जोड़ने के बजाय, 1 जोड़े जाते हैं (signed में n-बार 2 से विभाजित करें)रोटेट राइट:
lsr
की तरह, लेकिन जो कुछ भी दाईं ओर से हटा दिया गया है, उसे बाईं ओर जोड़ा जाता है।रोटेट राइट विद एक्सटेंड:
ror
की तरह, लेकिन कैरी ध्वज को "सबसे महत्वपूर्ण बिट" के रूप में। इसलिए कैरी ध्वज को बिट 31 में स्थानांतरित किया जाता है और हटा दिया गया बिट कैरी ध्वज में होता है।bfm
: बिट फील्ड मूव, ये ऑपरेशन0...n
बिट्स को एक मान से कॉपी करते हैं और उन्हेंm..m+n
स्थानों में रखते हैं।#s
सबसे बाईं बिट स्थिति को निर्दिष्ट करता है और#r
रोटेट राइट मात्रा को।बिटफील्ड मूव:
BFM Xd, Xn, #r
साइन बिटफील्ड मूव:
SBFM Xd, Xn, #r, #s
अनसाइन बिटफील्ड मूव:
UBFM Xd, Xn, #r, #s
बिटफील्ड एक्सट्रैक्ट और इंसर्ट: एक रजिस्टर से एक बिटफील्ड को कॉपी करें और इसे दूसरे रजिस्टर में कॉपी करें।
BFI X1, X2, #3, #4
X1 के 3वें बिट से X2 के 4 बिट्स को डालें।BFXIL X1, X2, #3, #4
X2 के 3वें बिट से चार बिट्स को निकालें और उन्हें X1 में कॉपी करें।SBFIZ X1, X2, #3, #4
X2 से 4 बिट्स को साइन-एक्सटेंड करें और उन्हें X1 में डालें, बिट स्थिति 3 से दाईं बिट्स को शून्य करते हुए।SBFX X1, X2, #3, #4
X2 से 3 से शुरू होने वाले 4 बिट्स को निकालता है, उन्हें साइन-एक्सटेंड करता है, और परिणाम को X1 में रखता है।UBFIZ X1, X2, #3, #4
X2 से 4 बिट्स को शून्य-एक्सटेंड करता है और उन्हें X1 में डालता है, बिट स्थिति 3 से दाईं बिट्स को शून्य करते हुए।UBFX X1, X2, #3, #4
X2 से 3 से शुरू होने वाले 4 बिट्स को निकालता है और शून्य-एक्सटेंडेड परिणाम को X1 में रखता है।साइन एक्सटेंड टू X: एक मान के साइन को बढ़ाता है (या अनसाइन संस्करण में केवल 0 जोड़ता है) ताकि इसके साथ ऑपरेशन किया जा सके:
SXTB X1, W2
W2 से X1 तक एक बाइट के साइन को बढ़ाता है (W2
X2
का आधा है) ताकि 64 बिट्स को भर सके।SXTH X1, W2
W2 से X1 तक एक 16-बिट संख्या के साइन को बढ़ाता है ताकि 64 बिट्स को भर सके।SXTW X1, W2
W2 से X1 तक एक बाइट के साइन को बढ़ाता है ताकि 64 बिट्स को भर सके।UXTB X1, W2
W2 से X1 तक एक बाइट में 0 जोड़ता है (अनसाइन) ताकि 64 बिट्स को भर सके।extr
: निर्दिष्ट रजिस्टरों के जोड़े से बिट्स निकालता है।उदाहरण:
EXTR W3, W2, W1, #3
यह W1+W2 को जोड़ता है और W2 के बिट 3 से W1 के बिट 3 तक को प्राप्त करता है और इसे W3 में संग्रहीत करता है।cmp
: दो रजिस्टरों की तुलना करें और स्थिति ध्वज सेट करें। यहsubs
का एक उपनाम है जो गंतव्य रजिस्टर को शून्य रजिस्टर पर सेट करता है। यह जानने के लिए उपयोगी है किm == n
।यह
subs
के समान सिंटैक्स का समर्थन करता है।उदाहरण:
cmp x0, x1
— यहx0
औरx1
में मानों की तुलना करता है और स्थिति ध्वज को तदनुसार सेट करता है।cmn
: नकारात्मक ऑपरेन्ड की तुलना करें। इस मामले में यहadds
का एक उपनाम है और समान सिंटैक्स का समर्थन करता है। यह जानने के लिए उपयोगी है किm == -n
।ccmp
: शर्तीय तुलना, यह एक तुलना है जो केवल तभी की जाएगी जब एक पूर्ववर्ती तुलना सत्य थी और विशेष रूप से nzcv बिट्स को सेट करेगी।cmp x1, x2; ccmp x3, x4, 0, NE; blt _func
-> यदि x1 != x2 और x3 < x4, तो func पर कूदें।यह इसलिए है क्योंकि
ccmp
केवल तब निष्पादित होगा जब पिछलीcmp
एकNE
थी, यदि नहीं थी तो बिट्सnzcv
को 0 पर सेट किया जाएगा (जोblt
तुलना को संतुष्ट नहीं करेगा)।इसे
ccmn
के रूप में भी उपयोग किया जा सकता है (समान लेकिन नकारात्मक, जैसेcmp
बनामcmn
)।tst
: यह जांचता है कि क्या तुलना के मान दोनों 1 हैं (यह किसी भी परिणाम को कहीं भी संग्रहीत किए बिना ANDS की तरह काम करता है)। यह एक रजिस्टर के मान के साथ जांचने के लिए उपयोगी है और यह जांचता है कि क्या मान में निर्दिष्ट रजिस्टर के किसी भी बिट्स का मान 1 है।उदाहरण:
tst X1, #7
X1 के अंतिम 3 बिट्स में से कोई भी 1 है या नहीं, इसकी जांच करें।teq
: XOR ऑपरेशन परिणाम को छोड़कर।b
: बिना शर्त शाखा।उदाहरण:
b myFunction
ध्यान दें कि यह लिंक रजिस्टर को लौटने के पते से नहीं भरेगा (उपरोक्त उपरूटीन कॉल के लिए उपयुक्त नहीं है जिसे वापस लौटने की आवश्यकता है)।
bl
: लिंक के साथ शाखा, जिसका उपयोग एक उपरूटीन को कॉल करने के लिए किया जाता है।x30
में रिटर्न पता संग्रहीत करता है।उदाहरण:
bl myFunction
— यह फ़ंक्शनmyFunction
को कॉल करता है और रिटर्न पताx30
में संग्रहीत करता है।ध्यान दें कि यह लिंक रजिस्टर को लौटने के पते से नहीं भरेगा (उपरोक्त उपरूटीन कॉल के लिए उपयुक्त नहीं है जिसे वापस लौटने की आवश्यकता है)।
blr
: रजिस्टर के लिए लिंक के साथ शाखा, जिसका उपयोग एक उपरूटीन को कॉल करने के लिए किया जाता है जहाँ लक्ष्य एक रजिस्टर में निर्दिष्ट होता है। रिटर्न पताx30
में संग्रहीत होता है। (यह हैउदाहरण:
blr x1
— यह उस फ़ंक्शन को कॉल करता है जिसका पताx1
में है और रिटर्न पताx30
में संग्रहीत होता है।ret
: उपरूटीन से लौटें, आमतौर परx30
में पते का उपयोग करते हुए।उदाहरण:
ret
— यह वर्तमान उपरूटीन से लौटता है जोx30
में लौटने के पते का उपयोग करता है।b.<cond>
: शर्तीय शाखाएँ।b.eq
: बराबर होने पर शाखा, पिछलेcmp
निर्देश के आधार पर।उदाहरण:
b.eq label
— यदि पिछलेcmp
निर्देश ने दो समान मान पाए, तो यहlabel
पर कूदता है।b.ne
: बराबर नहीं होने पर शाखा। यह निर्देश स्थिति ध्वजों की जांच करता है (जो पिछले तुलना निर्देश द्वारा सेट किए गए थे), और यदि तुलना किए गए मान समान नहीं थे, तो यह एक लेबल या पते पर शाखा बनाता है।उदाहरण:
cmp x0, x1
निर्देश के बाद,b.ne label
— यदिx0
औरx1
में मान समान नहीं थे, तो यहlabel
पर कूदता है।cbz
: शून्य पर तुलना करें और शाखा बनाएं। यह निर्देश एक रजिस्टर की तुलना शून्य से करता है, और यदि वे समान हैं, तो यह एक लेबल या पते पर शाखा बनाता है।उदाहरण:
cbz x0, label
— यदिx0
में मान शून्य है, तो यहlabel
पर कूदता है।cbnz
: गैर-शून्य पर तुलना करें और शाखा बनाएं। यह निर्देश एक रजिस्टर की तुलना शून्य से करता है, और यदि वे समान नहीं हैं, तो यह एक लेबल या पते पर शाखा बनाता है।उदाहरण:
cbnz x0, label
— यदिx0
में मान गैर-शून्य है, तो यहlabel
पर कूदता है।tbnz
: बिट का परीक्षण करें और गैर-शून्य पर शाखा बनाएं।उदाहरण:
tbnz x0, #8, label
tbz
: बिट का परीक्षण करें और शून्य पर शाखा बनाएं।उदाहरण:
tbz x0, #8, label
शर्तीय चयन ऑपरेशन: ये ऑपरेशन हैं जिनका व्यवहार शर्तीय बिट्स के आधार पर भिन्न होता है।
csel Xd, Xn, Xm, cond
->csel X0, X1, X2, EQ
-> यदि सत्य है, तो X0 = X1, यदि गलत है, तो X0 = X2csinc Xd, Xn, Xm, cond
-> यदि सत्य है, तो Xd = Xn, यदि गलत है, तो Xd = Xm + 1cinc Xd, Xn, cond
-> यदि सत्य है, तो Xd = Xn + 1, यदि गलत है, तो Xd = Xncsinv Xd, Xn, Xm, cond
-> यदि सत्य है, तो Xd = Xn, यदि गलत है, तो Xd = NOT(Xm)cinv Xd, Xn, cond
-> यदि सत्य है, तो Xd = NOT(Xn), यदि गलत है, तो Xd = Xncsneg Xd, Xn, Xm, cond
-> यदि सत्य है, तो Xd = Xn, यदि गलत है, तो Xd = - Xmcneg Xd, Xn, cond
-> यदि सत्य है, तो Xd = - Xn, यदि गलत है, तो Xd = Xncset Xd, Xn, Xm, cond
-> यदि सत्य है, तो Xd = 1, यदि गलत है, तो Xd = 0csetm Xd, Xn, Xm, cond
-> यदि सत्य है, तो Xd = <सभी 1>, यदि गलत है, तो Xd = 0adrp
: एक प्रतीक का पृष्ठ पता गणना करें और इसे एक रजिस्टर में संग्रहीत करें।उदाहरण:
adrp x0, symbol
— यहsymbol
का पृष्ठ पता गणना करता है और इसेx0
में संग्रहीत करता है।ldrsw
: मेमोरी से एक साइन 32-बिट मान लोड करें और इसे 64 बिट्स में साइन-एक्सटेंड करें।उदाहरण:
ldrsw x0, [x1]
— यहx1
द्वारा इंगित मेमोरी स्थान से एक साइन 32-बिट मान लोड करता है, इसे 64 बिट्स में साइन-एक्सटेंड करता है, और इसेx0
में संग्रहीत करता है।stur
: एक रजिस्टर मान को एक मेमोरी स्थान में स्टोर करें, एक अन्य रजिस्टर से ऑफसेट का उपयोग करते हुए।उदाहरण:
stur x0, [x1, #4]
— यहx0
में मान को उस मेमोरी पते में संग्रहीत करता है जोx1
में वर्तमान पते से 4 बाइट अधिक है।svc
: एक सिस्टम कॉल करें। इसका अर्थ "सुपरवाइजर कॉल" है। जब प्रोसेसर इस निर्देश को निष्पादित करता है, तो यह उपयोगकर्ता मोड से कर्नेल मोड में स्विच करता है और मेमोरी में एक विशिष्ट स्थान पर कूदता है जहाँ कर्नेल का सिस्टम कॉल हैंडलिंग कोड स्थित है।उदाहरण:
फंक्शन प्रस्तावना
लिंक रजिस्टर और फ्रेम पॉइंटर को स्टैक में सहेजें:
नए फ्रेम पॉइंटर को सेट करें:
mov x29, sp
(वर्तमान फ़ंक्शन के लिए नए फ्रेम पॉइंटर को सेट करता है)स्थानीय चर के लिए स्टैक पर स्थान आवंटित करें (यदि आवश्यक हो):
sub sp, sp, <size>
(जहाँ<size>
आवश्यक बाइट्स की संख्या है)
फ़ंक्शन एपिलॉग
स्थानीय चर को डिआलॉक करें (यदि कोई आवंटित किया गया था):
add sp, sp, <size>
लिंक रजिस्टर और फ्रेम पॉइंटर को पुनर्स्थापित करें:
Return:
ret
(कॉलर को लिंक रजिस्टर में पते का उपयोग करके नियंत्रण लौटाता है)
AARCH32 निष्पादन स्थिति
Armv8-A 32-बिट प्रोग्रामों के निष्पादन का समर्थन करता है। AArch32 A32
और T32
के दो निर्देश सेटों में से एक में चल सकता है और interworking
के माध्यम से उनके बीच स्विच कर सकता है।
Privileged 64-बिट प्रोग्राम 32-बिट प्रोग्रामों के निष्पादन को निम्न स्तर के 32-बिट में अपवाद स्तर स्थानांतरण को निष्पादित करके शेड्यूल कर सकते हैं।
ध्यान दें कि 64-बिट से 32-बिट में संक्रमण अपवाद स्तर के निम्न स्तर के साथ होता है (उदाहरण के लिए, EL1 में 64-बिट प्रोग्राम EL0 में प्रोग्राम को ट्रिगर करता है)। यह तब किया जाता है जब AArch32
प्रक्रिया थ्रेड निष्पादित होने के लिए तैयार होती है और SPSR_ELx
विशेष रजिस्टर के बिट 4 को 1 पर सेट किया जाता है और SPSR_ELx
का शेष भाग AArch32
प्रोग्राम का CPSR संग्रहीत करता है। फिर, विशेषाधिकार प्राप्त प्रक्रिया ERET
निर्देश को कॉल करती है ताकि प्रोसेसर AArch32
में प्रवेश करे, जो CPSR** के आधार पर A32 या T32 में प्रवेश करता है।**
interworking
CPSR के J और T बिट्स का उपयोग करके होता है। J=0
और T=0
का अर्थ है A32
और J=0
और T=1
का अर्थ है T32। यह मूल रूप से सबसे निचले बिट को 1 पर सेट करने का संकेत देता है कि निर्देश सेट T32 है।
यह interworking शाखा निर्देशों के दौरान सेट किया जाता है, लेकिन जब PC को गंतव्य रजिस्टर के रूप में सेट किया जाता है तो अन्य निर्देशों के साथ भी सीधे सेट किया जा सकता है। उदाहरण:
एक और उदाहरण:
Registers
16 32-बिट रजिस्टर हैं (r0-r15)। r0 से r14 का उपयोग किसी भी ऑपरेशन के लिए किया जा सकता है, हालाँकि इनमें से कुछ आमतौर पर आरक्षित होते हैं:
r15
: प्रोग्राम काउंटर (हमेशा)। अगले निर्देश का पता रखता है। A32 में वर्तमान + 8, T32 में, वर्तमान + 4।r11
: फ्रेम पॉइंटरr12
: इंट्रा-प्रोसीजरल कॉल रजिस्टरr13
: स्टैक पॉइंटरr14
: लिंक रजिस्टर
इसके अलावा, रजिस्टर बैंक्ड रजिस्ट्रियों
में बैकअप होते हैं। ये ऐसे स्थान हैं जो रजिस्टर के मानों को संग्रहीत करते हैं जिससे अपवाद हैंडलिंग और विशेषाधिकार प्राप्त ऑपरेशनों में तेज़ संदर्भ स्विचिंग करना संभव होता है ताकि हर बार मैन्युअल रूप से रजिस्टर को सहेजने और पुनर्स्थापित करने की आवश्यकता न हो।
यह CPSR
से प्रोसेसर मोड के SPSR
में प्रोसेसर स्थिति को सहेजकर किया जाता है जिसमें अपवाद लिया जाता है। अपवाद लौटने पर, CPSR
को SPSR
से पुनर्स्थापित किया जाता है।
CPSR - वर्तमान प्रोग्राम स्थिति रजिस्टर
AArch32 में CPSR AArch64 में PSTATE
के समान काम करता है और इसे अपवाद लिए जाने पर बाद में निष्पादन को पुनर्स्थापित करने के लिए SPSR_ELx
में भी संग्रहीत किया जाता है:
फील्ड कुछ समूहों में विभाजित हैं:
एप्लिकेशन प्रोग्राम स्थिति रजिस्टर (APSR): अंकगणितीय ध्वज और EL0 से सुलभ
निष्पादन स्थिति रजिस्टर: प्रक्रिया का व्यवहार (OS द्वारा प्रबंधित)।
एप्लिकेशन प्रोग्राम स्थिति रजिस्टर (APSR)
N
,Z
,C
,V
ध्वज (AArch64 की तरह ही)Q
ध्वज: इसे 1 पर सेट किया जाता है जब भी पूर्णांक संतृप्ति होती है विशेष संतृप्ति अंकगणितीय निर्देश के निष्पादन के दौरान। एक बार इसे1
पर सेट करने के बाद, यह मैन्युअल रूप से 0 पर सेट होने तक मान बनाए रखेगा। इसके अलावा, इसका मान अप्रत्यक्ष रूप से जांचने के लिए कोई निर्देश नहीं है, इसे मैन्युअल रूप से पढ़कर करना होगा।GE
(बड़ा या समान) ध्वज: इसका उपयोग SIMD (सिंगल इंस्ट्रक्शन, मल्टीपल डेटा) ऑपरेशनों में किया जाता है, जैसे "समानांतर जोड़" और "समानांतर घटाना"। ये ऑपरेशन एक ही निर्देश में कई डेटा बिंदुओं को संसाधित करने की अनुमति देते हैं।
उदाहरण के लिए, UADD8
निर्देश चार जोड़े बाइट्स (दो 32-बिट ऑपरेन्ड से) को समानांतर में जोड़ता है और परिणामों को 32-बिट रजिस्टर में संग्रहीत करता है। फिर यह APSR
में इन परिणामों के आधार पर GE
ध्वज सेट करता है। प्रत्येक GE ध्वज एक बाइट जोड़ के लिए संबंधित होता है, यह दर्शाते हुए कि उस बाइट जोड़े के लिए जोड़ ओवरफ्लो हुआ या नहीं।
SEL
निर्देश इन GE ध्वजों का उपयोग करके शर्तीय क्रियाएँ करता है।
निष्पादन स्थिति रजिस्टर
J
औरT
बिट्स:J
0 होना चाहिए और यदिT
0 है तो A32 निर्देश सेट का उपयोग किया जाता है, और यदि यह 1 है, तो T32 का उपयोग किया जाता है।IT ब्लॉक स्थिति रजिस्टर (
ITSTATE
): ये 10-15 और 25-26 से संबंधित बिट्स हैं। येIT
उपसर्गित समूह के भीतर निर्देशों के लिए शर्तें संग्रहीत करते हैं।E
बिट: एंडियननेस को दर्शाता है।मोड और अपवाद मास्क बिट्स (0-4): ये वर्तमान निष्पादन स्थिति को निर्धारित करते हैं। 5वां यह दर्शाता है कि प्रोग्राम 32-बिट (1) के रूप में चल रहा है या 64-बिट (0) के रूप में। अन्य 4 वर्तमान में उपयोग किए जा रहे अपवाद मोड का प्रतिनिधित्व करते हैं (जब कोई अपवाद होता है और इसे संभाला जा रहा है)। सेट किया गया संख्या वर्तमान प्राथमिकता को दर्शाता है यदि इस दौरान कोई अन्य अपवाद उत्पन्न होता है।
AIF
: कुछ अपवादों कोA
,I
,F
बिट्स का उपयोग करके अक्षम किया जा सकता है। यदिA
1 है तो इसका मतलब है कि असिंक्रोनस एबॉर्ट्स उत्पन्न होंगे।I
बाहरी हार्डवेयर इंटरप्ट रिक्वेस्ट्स (IRQs) का उत्तर देने के लिए कॉन्फ़िगर करता है। और F फास्ट इंटरप्ट रिक्वेस्ट्स (FIRs) से संबंधित है।
macOS
BSD syscalls
syscalls.master पर जाएं। BSD syscalls में x16 > 0 होगा।
Mach Traps
syscall_sw.c में mach_trap_table
और mach_traps.h में प्रोटोटाइप देखें। Mach traps की अधिकतम संख्या MACH_TRAP_TABLE_COUNT
= 128 है। Mach traps में x16 < 0 होगा, इसलिए आपको पिछले सूची से नंबर को माइनस के साथ कॉल करना होगा: _kernelrpc_mach_vm_allocate_trap
-10
है।
आप libsystem_kernel.dylib
को डिसअसेंबलर में भी देख सकते हैं यह जानने के लिए कि इन (और BSD) syscalls को कैसे कॉल किया जाए:
ध्यान दें कि Ida और Ghidra केवल कैश को पास करके विशिष्ट dylibs को भी डिकंपाइल कर सकते हैं।
कभी-कभी libsystem_kernel.dylib
से डिकंपाइल किया गया कोड जांचना स्रोत कोड की तुलना में आसान होता है क्योंकि कई syscalls (BSD और Mach) का कोड स्क्रिप्ट के माध्यम से उत्पन्न होता है (स्रोत कोड में टिप्पणियाँ देखें) जबकि dylib में आप देख सकते हैं कि क्या कॉल किया जा रहा है।
machdep कॉल
XNU एक और प्रकार के कॉल का समर्थन करता है जिसे मशीन निर्भर कहा जाता है। इन कॉल की संख्या आर्किटेक्चर पर निर्भर करती है और न तो कॉल और न ही संख्या स्थिर रहने की गारंटी है।
comm पृष्ठ
यह एक कर्नेल मालिक मेमोरी पृष्ठ है जो हर उपयोगकर्ता प्रक्रिया के पते के स्केप में मैप किया गया है। इसका उद्देश्य उपयोगकर्ता मोड से कर्नेल स्पेस में संक्रमण को तेज करना है, ताकि उन कर्नेल सेवाओं के लिए syscalls का उपयोग करने की तुलना में जो इतनी बार उपयोग की जाती हैं, यह संक्रमण बहुत अप्रभावी हो जाएगा।
उदाहरण के लिए, कॉल gettimeofdate
सीधे comm पृष्ठ से timeval
का मान पढ़ता है।
objc_msgSend
यह फ़ंक्शन Objective-C या Swift प्रोग्रामों में उपयोग में लाना बहुत सामान्य है। यह फ़ंक्शन एक Objective-C ऑब्जेक्ट के एक मेथड को कॉल करने की अनुमति देता है।
पैरामीटर (दस्तावेज़ में अधिक जानकारी):
x0: self -> इंस्टेंस का पॉइंटर
x1: op -> मेथड का सेलेक्टर
x2... -> कॉल किए गए मेथड के शेष तर्क
तो, यदि आप इस फ़ंक्शन की शाखा से पहले ब्रेकपॉइंट लगाते हैं, तो आप आसानी से lldb में देख सकते हैं कि क्या कॉल किया जा रहा है (इस उदाहरण में ऑब्जेक्ट NSConcreteTask
से एक ऑब्जेक्ट को कॉल करता है जो एक कमांड चलाएगा):
पर्यावरण चर NSObjCMessageLoggingEnabled=1
सेट करने से यह लॉग करना संभव है कि यह फ़ंक्शन कब कॉल किया गया है, जैसे कि /tmp/msgSends-pid
फ़ाइल में।
इसके अलावा, OBJC_HELP=1
सेट करने और किसी भी बाइनरी को कॉल करने पर आप अन्य पर्यावरण चर देख सकते हैं जिनका उपयोग आप log करने के लिए कर सकते हैं जब कुछ Objc-C क्रियाएँ होती हैं।
जब यह फ़ंक्शन कॉल किया जाता है, तो निर्दिष्ट उदाहरण के कॉल किए गए तरीके को ढूंढना आवश्यक है, इसके लिए विभिन्न खोजें की जाती हैं:
आशावादी कैश लुकअप करें:
यदि सफल, तो समाप्त
runtimeLock प्राप्त करें (पढ़ें)
यदि (realize && !cls->realized) वर्ग को वास्तविक बनाएं
यदि (initialize && !cls->initialized) वर्ग को प्रारंभ करें
वर्ग की अपनी कैश का प्रयास करें:
यदि सफल, तो समाप्त
वर्ग विधि सूची का प्रयास करें:
यदि पाया गया, तो कैश भरें और समाप्त
सुपरक्लास कैश का प्रयास करें:
यदि सफल, तो समाप्त
सुपरक्लास विधि सूची का प्रयास करें:
यदि पाया गया, तो कैश भरें और समाप्त
यदि (resolver) विधि रिसॉल्वर का प्रयास करें, और वर्ग लुकअप से दोहराएं
यदि अभी भी यहाँ हैं (= सभी अन्य विफल हो गए हैं) तो फॉरवर्डर का प्रयास करें
Shellcodes
संकलन करने के लिए:
बाइट्स निकालने के लिए:
नए macOS के लिए:
Last updated