सीआर कॉलिंग सम्मेलन के लिए एआरएम, बचाने के लिए रजिस्टर

यह थोड़ी देर के बाद से मैंने आखिरी बार हाथ से इकट्ठा किया था और मैं विवरण पर थोड़ा जंगली हूं। अगर मैं हाथ से सी समारोह कहता हूं, तो मुझे केवल r0-r3 और lr को बचाने के बारे में चिंता करने की ज़रूरत है, है ना? यदि सी फ़ंक्शन किसी अन्य रजिस्ट्रार का उपयोग करता है, तो क्या यह उन स्टैक पर सहेजने और उन्हें बहाल करने के लिए ज़िम्मेदार है? दूसरे शब्दों में, संकलक सी कार्यों के लिए ऐसा करने के लिए कोड उत्पन्न करेगा। उदाहरण के लिए यदि मैं एक असेंबलर फ़ंक्शन में r10 का उपयोग करता हूं, तो मुझे स्टैक पर या मेमोरी पर अपना मान धक्का देना नहीं है, और सी कॉल के बाद इसे पॉप/पुनर्स्थापित करना है, क्या मैं?

यह arm-eabi-gcc 4.3.0 के लिए है।

मुझे एहसास है कि मैं पूरे ईएबीआई को पढ़ सकता हूं, लेकिन फिर आरटीएफएम को कम करने के लिए एसओ क्या है, है ना? :-)

0
यहां एक बाहरी लिंक है जो सहायक हो सकता है। एपीसीएस परिचय , विशेष रूप से कुछ अलग-अलग नाम
जोड़ा लेखक artless noise, स्रोत

5 उत्तर

To add up missing info on NEON registers:

एएपीसीएस , §5.1.1 से कोर रजिस्टर:

  • r0-r3 are the argument and scratch registers; r0-r1 are also the result registers
  • r4-r8 are callee-save registers
  • r9 might be a callee-save register or not (on some variants of AAPCS it is a special register)
  • r10-r11 are callee-save registers
  • r12-r15 are special registers

एएपीसीएस से, §5.1.2.1 वीएफपी रजिस्टर उपयोग सम्मेलन:

  • s16–s31 (d8–d15, q4–q7) must be preserved
  • s0–s15 (d0–d7, q0–q3) and d16–d31 (q8–q15) do not need to be preserved

Original post:
arm-to-c-calling-convention-neon-registers-to-save

0
जोड़ा

For 64-bit ARM, A64 (from Procedure Call Standard for the ARM 64-bit Architecture)

ए 64 निर्देश सेट के लिए दृश्यमान तीसरे, 64-बिट, सामान्य उद्देश्य (पूर्णांक) रजिस्ट्रार हैं; इन्हें r0-r30 लेबल किया गया है। 64-बिट संदर्भ में इन रजिस्टरों को आम तौर पर x0-x30 नामों का उपयोग करने के लिए संदर्भित किया जाता है; 32-बिट संदर्भ में रजिस्टरों को w0-w30 का उपयोग करके निर्दिष्ट किया जाता है। इसके अतिरिक्त, एक स्टैक-पॉइंटर रजिस्टर, SP का उपयोग प्रतिबंधित संख्याओं के साथ किया जा सकता है।

  • SP The Stack Pointer
  • r30 LR The Link Register
  • r29 FP The Frame Pointer
  • r19…r28 Callee-saved registers
  • r18 The Platform Register, if needed; otherwise a temporary register.
  • r17 IP1 The second intra-procedure-call temporary register (can be used by call veneers and PLT code); at other times may be used as a temporary register.
  • r16 IP0 The first intra-procedure-call scratch register (can be used by call veneers and PLT code); at other times may be used as a temporary register.
  • r9…r15 Temporary registers
  • r8 Indirect result location register
  • r0…r7 Parameter/result registers

पहले आठ रजिस्ट्रार, r0-r7 का उपयोग तर्क मानों को एक सबराउटिन में पास करने और फ़ंक्शन से परिणाम मान वापस करने के लिए किया जाता है। इन्हें नियमित रूप से मध्यवर्ती मूल्यों को रखने के लिए भी उपयोग किया जा सकता है (लेकिन, सामान्य रूप से, केवल सबराउटिन कॉल के बीच)।

रजिस्टर्स r16 (IP0) और r17 (IP1) को एक लिंकर द्वारा एक नियमित और किसी भी सबराउटिन के बीच स्क्रैच रजिस्टर के रूप में उपयोग किया जा सकता है। Subroutine कॉल के बीच मध्यवर्ती मूल्यों को पकड़ने के लिए इन्हें नियमित रूप से भी उपयोग किया जा सकता है।

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

SIMD

एआरएम 64-बिट आर्किटेक्चर में एक और बीस-दो रजिस्ट्रार हैं, v0-v31 , जिसका उपयोग सिमड और फ़्लोटिंग-प्वाइंट ऑपरेशंस द्वारा किया जा सकता है। रजिस्टर का सटीक नाम एक्सेस के आकार को इंगित करेगा।

Note: Unlike in AArch32, in AArch64 the 128-bit and 64-bit views of a SIMD and Floating-Point register do not overlap multiple registers in a narrower view, so q1, d1 and s1 all refer to the same entry in the register bank.

पहले आठ रजिस्ट्रार, v0-v7 का उपयोग तर्क मानों को एक सबराउटिन में पास करने और फ़ंक्शन से परिणाम मान वापस करने के लिए किया जाता है। इन्हें नियमित रूप से मध्यवर्ती मूल्यों को रखने के लिए भी उपयोग किया जा सकता है (लेकिन, सामान्य रूप से, केवल सबराउटिन कॉल के बीच)।

रजिस्टर्स v8-v15 को सबराउटिन कॉल में कैली द्वारा संरक्षित किया जाना चाहिए; शेष रजिस्ट्रार ( v0-v7, v16-v31 ) को संरक्षित करने की आवश्यकता नहीं है (या कॉलर द्वारा संरक्षित किया जाना चाहिए)। इसके अतिरिक्त, v8-v15 में संग्रहीत प्रत्येक मान के केवल 64-बिट्स को संरक्षित करने की आवश्यकता है; बड़े मूल्यों को संरक्षित करने के लिए कॉलर की ज़िम्मेदारी है।

0
जोड़ा

यह आपके द्वारा संकलित किए जा रहे प्लेटफॉर्म के लिए एबीआई पर निर्भर करता है। लिनक्स पर, दो एआरएम एबीआई हैं; पुराना और नया वाला। AFAIK, नया एक (ईएबीआई) वास्तव में एआरएम के एएपीसीएस है। वर्तमान में पूर्ण ईएबीआई परिभाषाएं यहां एआरएम पर रहते हैं InfoCenter

एएपीसीएस, §5.1.1 से:

  • r0-r3 are the argument and scratch registers; r0-r1 are also the result registers
  • r4-r8 are callee-save registers
  • r9 might be a callee-save register or not (on some variants of AAPCS it is a special register)
  • r10-r11 are callee-save registers
  • r12-r15 are special registers

एक कैली-सेव रजिस्टर कैली द्वारा बचाया जाना चाहिए (कॉलर-सेव रजिस्टर के विरोध में, जहां कॉलर रजिस्टर सहेजता है); इसलिए, अगर यह एबीआई है जिसका आप उपयोग कर रहे हैं, तो आपको किसी अन्य फ़ंक्शन को कॉल करने से पहले r10 को सहेजने की आवश्यकता नहीं है (अन्य फ़ंक्शन इसे सहेजने के लिए ज़िम्मेदार है)।

Edit: Which compiler you are using makes no difference; gcc in particular can be configured for several different ABIs, and it can even be changed on the command line. Looking at the prologue/epilogue code it generates is not that useful, since it is tailored for each function and the compiler can use other ways of saving a register (for instance, saving it in the middle of a function).

0
जोड़ा
"आप इस एबीआई विनिर्देश और इसके सहायक दस्तावेज और उदाहरण कोड को इस पृष्ठ से ज़िप संग्रह के रूप में डाउनलोड कर सकते हैं।" ज़िप संग्रह: infocenter.arm.com/help/topic /com.arm.doc.ihi0036b/bsabi.zip
जोड़ा लेखक jww, स्रोत
धन्यवाद, ऐसा लगता है कि कुछ घंटी बजती है। मुझे लगता है कि आपकी सूची में पहला "आर 0-आर 4" एक टाइपो है, है ना? +1 (और शायद सबसे अच्छा जवाब जब तक कि एक कट्टरपंथी मोड़ नहीं है)
जोड़ा लेखक richq, स्रोत
मैं बस इस पीसीएस दस्तावेज़ के माध्यम से जा रहा हूं और इसमें संदेह है, वैरिएबल रजिस्ट्रार v1-v8 का उपयोग स्थानीय चरों को सहेजने के लिए किया जाता है, यदि हां, तो क्या होता है जब मैं अधिक स्थानीय चर आवंटित करता हूं? मैं ढेर और इन रजिस्टरों को जोड़ने में सक्षम नहीं हूं ...
जोड़ा लेखक Xavier Geoffrey, स्रोत
हां, यह एक टाइपो था (और केवल एक ही नहीं, लेकिन मैंने पहली बार सबमिट करने से पहले अन्य लोगों को तय किया - या तो मुझे उम्मीद है)।
जोड़ा लेखक CesarB, स्रोत
सारांशित करने के लिए: जब एक सी फ़ंक्शन को कॉल करते हैं, तो रजिस्ट्रार r0-r3, r12 (और शायद r9) को सहेजने की आवश्यकता होती है। मेरे अनुभव से, जीसीसी एक समारोह के अंदर एक स्क्रैच रजिस्टर के रूप में आर 12 का उपयोग करता है और इसलिए यदि हाथ/अंगूठे-इंटरवर्किंग का उपयोग नहीं किया जाता है तो भी यह कैली-सेव नहीं होता है। इंटरवर्किंग के मामले में, लिंकर गोंद कोड उत्पन्न करेगा जो आर 12 का उपयोग करता है यदि एक आर्म फ़ंक्शन अंगूठे का कार्य करता है।
जोड़ा लेखक Sven, स्रोत
एलेक्स द्वारा टिप्पणी भ्रमित है क्योंकि यह कैली के दृष्टिकोण से है। यहां चर्चा की गई सवाल कॉलर के दृष्टिकोण से है। एक कॉलर को कॉल करते समय कॉलर को r4-r11 को सहेजने की आवश्यकता नहीं होती है। सी फ़ंक्शन (कैली) इन रजिस्टरों को सहेज लेगा। साथ ही, कोई भी स्पष्ट क्यों नहीं करता कि कॉलर द्वारा आर 9 को सहेजने की आवश्यकता है या नहीं? मैं एक आर्म-एबी-जीसीसी टूलचेन के लिए विश्वास करता हूं, आर 9 भी कैली-सेव किया जाता है। आर 9 मुद्दे को सुलझाने वाली जानकारी के स्रोत पर कौन इंगित कर सकता है?
जोड़ा लेखक Sven, स्रोत
मुझे लगता है कि यह याद रखना बहुत आसान है कि आपको r4-r11 को सहेजना और पुनर्स्थापित करना होगा यदि आप उनका उपयोग करने जा रहे हैं; यही कारण है कि वे callee बचाया गया है।
जोड़ा लेखक amc, स्रोत
Amorenoc की टिप्पणी का विस्तार करने के लिए: r4-r11 (शायद r9 के अपवाद के साथ) फ़ंक्शन को कॉल करते समय "सुरक्षित" माना जा सकता है। r0-r3 फ़ंक्शन कॉल के बाद शायद संरक्षित नहीं किया जाएगा, और लिंकिंग के तरीके के आधार पर, न तो r12 (जिसे स्क्रैच रजिस्टर के रूप में उपयोग किया जा सकता है)।
जोड़ा लेखक Leo, स्रोत

सीज़रबी और पावेल के उत्तरों ने एएपीसीएस से उद्धरण दिए, लेकिन खुले मुद्दे बने रहे। क्या कैली आर 9 बचाती है? आर 12 के बारे में क्या? आर 14 के बारे में क्या? इसके अलावा, उत्तर बहुत सामान्य थे, और अनुरोध के रूप में arm-eabi टूलचेन के लिए विशिष्ट नहीं थे। यह पता लगाने के लिए एक व्यावहारिक दृष्टिकोण यहां दिया गया है कि कौन से रजिस्टर कैली-सेव किए गए हैं और जो नहीं हैं।

निम्नलिखित सी कोड में एक इनलाइन असेंबली ब्लॉक होता है, जो रजिस्ट्रार r0-r12 और r14 को संशोधित करने का दावा करता है। कंपाइलर एबीआई द्वारा आवश्यक रजिस्टरों को बचाने के लिए कोड उत्पन्न करेगा।

void foo() {
  asm volatile ( "nop" : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14");
}

कमांड लाइन arm-eabi-gcc-4.7 -O2 -S -o - foo.c का उपयोग करें और उदाहरण के लिए अपने प्लेटफ़ॉर्म के लिए स्विच जोड़ें (जैसे -mcpu = arm7tdmi )। आदेश STDOUT पर जेनरेट किए गए असेंबली कोड को मुद्रित करेगा। ऐसा कुछ ऐसा दिख सकता है:

foo:
    stmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
    nop
    ldmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
    bx  lr

नोट, कि संकलक उत्पन्न कोड r4-r11 बचाता है और पुनर्स्थापित करता है। कंपाइलर r0-r3, r12 को सहेजता नहीं है। यह आर 14 (एलियाएस एलआर) को पुनर्स्थापित करता है पूरी तरह से आकस्मिक है क्योंकि मुझे अनुभव से पता है कि निकास कोड भी सहेजे गए एलआर को आर 0 में लोड कर सकता है और फिर "बीएक्स एलआर" के बजाय "बीएक्स आर 0" कर सकता है। या तो -mcpu = arm7tdmi -mno-thumb-interwork जोड़कर या -mcpu = cortex-m4 -mthumb का उपयोग करके हम थोड़ा अलग असेंबली कोड प्राप्त करते हैं जो इस तरह दिखता है:

foo:
    stmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
    nop
    ldmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}

फिर, r4-r11 सहेजे और बहाल कर रहे हैं। लेकिन आर 14 (उर्फ एलआर) बहाल नहीं किया गया है।

संक्षेप में:

  • r0-r3 नहीं callee-saved
  • हैं
  • r4-r11 callee से सहेजे गए हैं
  • आर 12 (उपनाम आईपी) नहीं कैली-सेव किया गया
  • है
  • r13 (उपनाम एसपी) कैली-सेव किया गया है
  • r14 (उर्फ एलआर) नहीं कैली-सेव किया गया
  • है
  • r15 (उर्फ पीसी) प्रोग्राम काउंटर है और फ़ंक्शन कॉल से पहले lr के मान पर सेट है

यह कम से कम arm-eabi-gcc के डिफ़ॉल्ट के लिए है। कमांड लाइन स्विच (विशेष रूप से -बीबी स्विच) हैं जो परिणाम को प्रभावित कर सकते हैं।

0
जोड़ा
आह, रजिस्ट्रारों को इस कारण से इंटरप्ट के लिए बैंक किया जाता है। वैसे भी हम असहमत होने के लिए सहमत हैं।
जोड़ा लेखक artless noise, स्रोत
मुझे लगता है कि आपके पास एक काल्पनिक अर्थ में एक बिंदु है; आप कुछ असेंबलर लिख सकते हैं जो lr में फ़ंक्शन पॉइंटर लौटाता है। हालांकि, मुझे नहीं लगता कि lr का मूल मूल्य आपके लिए क्या करेगा। आप उस कोड को निष्पादित कर रहे हैं जो lr में वापसी पर था, इसलिए इसका मूल मान कोड निष्पादन द्वारा स्पष्ट है। अच्छी तरह से पावेल द्वारा समझाया गया है r12-r15 विशेष रजिस्ट्रार हैं । कॉलिंग पर lr का मान निकास पर पीसी का मान होगा। सवाल यह है कि lr को पुनर्स्थापित किया गया है या मेरे लिए विचित्र नहीं लगता है। यह निर्भर क
जोड़ा लेखक artless noise, स्रोत
पीसी </कोड पर विवरण के लिए एआरएम लिंक और फ्रेम सूचक देखें > और lrr12 को ip के रूप में भी जाना जाता है और इसका उपयोग प्रस्तावना और epilogue के दौरान किया जा सकता है। यह एक अस्थिर रजिस्टर है। यह दिनचर्या के लिए महत्वपूर्ण है जो कॉल स्टैक/फ्रेम को पार्स कर रहे हैं।
जोड़ा लेखक artless noise, स्रोत
आपका विश्लेषण सही है ; वापस आने के लिए lr popped पीसी के रूप में है। आपके r9 प्रश्न का उत्तर एपीसीएस । इसे इस दस्तावेज़ में स्थैतिक आधार कहा जाता है और अनुभाग पुनर्वित्त बनाम गैर-पुनर्वित्त कोड सापेक्ष है। एपीसीएस कई कॉन्फ़िगरेशन का समर्थन करता है, लेकिन gcc आमतौर पर पुनः प्रविष्टि बिना स्टैक सीमा है। विशेष रूप से, एपीसीएस के कुछ प्रकारों में
जोड़ा लेखक artless noise, स्रोत
यह वही है जो मैं खोज रहा था - यह पता लगाने का एक तरीका है कि कौन से रजिस्टरों को मेरे प्रोजेक्ट के लिए उपयोग कर रहे विशिष्ट कंपाइलर सेटिंग्स द्वारा संरक्षित किया जाता है। धन्यवाद!
जोड़ा लेखक TonyK, स्रोत
lr से संबंधित मेरा विश्लेषण किस मायने में गलत है? मुझे लगता है कि तुमने मुझे गलत समझा। किसी भी तरह, मैं दूसरा असेंबली कोड स्निपेट प्रस्तुत कर रहा था क्योंकि पहली बार lr कैली सहेजा गया था। हालांकि, मुझे लगता है कि यह नहीं है। हां, दूसरे स्निपेट में, lr को वापस करने के लिए एक त्वरित तरीका के रूप में पीसी के रूप में पॉप किया गया है और मैंने इसे समझाया नहीं है, लेकिन दूसरा स्निपेट पेश करने का बिंदु यह था कि यह दिखाता है कि lr कैली सहेजा नहीं गया है।
जोड़ा लेखक Sven, स्रोत
यह सच है कि lr को पीसी पर पुनर्स्थापित किया गया है। लेकिन यह सच नहीं है, कि कोई उम्मीद कर सकता है कि lr का मान पुनर्स्थापित किया गया है। मैं नहीं देखता कि यह कैसे गलत हो सकता है। यह मान उस रजिस्टर में समाप्त होता है जो lr नहीं है, इस प्रश्न के लिए पूरी तरह से अप्रासंगिक है कि lr को पुनर्स्थापित किया गया है या नहीं। आप सही हैं कि रजिस्टरों का सेट जो बहाल किया गया है और पुनर्स्थापित नहीं किया जा सकता है -mabi विकल्प परिवर्तन के रूप में बदल सकता है।
जोड़ा लेखक Sven, स्रोत
अभी, मैं ARM7TDMI पर नेस्टेड इंटरप्ट्स के लिए एक असेंबलर रैपर लिख रहा हूं। चाहे lr का मान सी-कोड को कॉल द्वारा संरक्षित किया गया हो, महत्वपूर्ण है, क्योंकि lr के मान को असेंबलर वार्पर द्वारा अपने पूर्व मान में बहाल किया जाना चाहिए। तो यह जानकर कि lr कैली-सेव किया गया है, वह सभी कल्पित नहीं है।
जोड़ा लेखक Sven, स्रोत

फ़ंक्शन कॉल और बाधा के लिए कम से कम कॉर्टेक्स एम 3 आर्किटेक्चर में भी अंतर है।

यदि कोई इंटरप्ट होता है तो यह स्वचालित पुश R0-R3, R12, LR, पीसी को स्टैक पर और जब वापसी आईआरक्यू स्वचालित पीओपी बना देगा। यदि आप आईआरक्यू रूटीन में अन्य रजिस्टरों का उपयोग करते हैं तो आपको उन्हें मैन्युअल रूप से स्टैक पर पुश/पॉप करना होगा।

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

0
जोड़ा