printf

2016-05-06 6 views
5

के साथ एकल-परिशुद्धता फ्लोट को मुद्रित करने के लिए मैं x86_64 असेंबली में एक फ़्लोटिंग पॉइंट नंबर मुद्रित करने का प्रयास कर रहा हूं लेकिन यह केवल मान को शून्य के रूप में प्रिंट करता है।printf

इसके बारे में कुछ प्रश्न पहले से ही हैं। you set the number of vector registers you're using in %al सुनिश्चित करके एक हल किया गया। एक और दिखाया कि you need to have a stack alignment of 16 bytes। लेकिन, मैं उन दोनों चीजों को कर रहा हूं और अभी भी सही आउटपुट नहीं प्राप्त कर रहा हूं।

# prints a floating point value 
.section .rodata 
.fmt: .string "num: %f\n" 
.num: .float 123.4 

.section .text 
.global main 
.type main, @function 
main: 
    subq $8, %rsp  # 16-byte alignment 

    # print my number 
    movss .num, %xmm0 # load float value 
    movq $.fmt, %rdi # load format string 
    movb $1, %al  # use 1 vector register 
    call printf 

    # exit 
    addq $8, %rsp  # undo alignment 
    movq $0, %rax  # return 0 
    ret 

उत्तर

5

printf(3)'s %f format specifier wants a double:

यह मेरा कार्यक्रम है। float, केवल double या long double स्वीकार करने के लिए printf प्राप्त करने का कोई तरीका नहीं है।

सी डिफ़ॉल्ट तर्क प्रोन्नति निर्दिष्ट कार्यों foo(char *fmt, ...) तरह double को float बढ़ावा देने, और आर्ग कि प्रोटोटाइप के ... भाग से मेल अनुगामी के लिए, int में बहुत ही सीमित पूर्णांक प्रकार के सामान्य पूर्णांक प्रोन्नति प्रदर्शन variadic करने के लिए कॉल कि। (यह प्रोटोटाइप वाले कार्यों को कॉल करने के लिए सभी तर्कों पर लागू होता है।) N1570 6.5.2.2 Function calls, subsections 6 and 7

इस प्रकार सी एक फोन करने वाले एक floatprintf को पारित करने के लिए कोई तरीका प्रदान करता है, तो यह इसके लिए कोई रूपांतरण है, और इसका मतलब है %fdouble। (%lf आमतौर पर double के लिए भी काम करता है, यह मानते हुए कि कार्यान्वयन गैर-पूर्णांक/wchar_t रूपांतरणों के लिए इसे अनदेखा करता है)। ध्यान दें कि scanf अलग है, क्योंकि float * और double * उन प्रचारों से प्रभावित नहीं हैं।


इस मामले में, CVTSS2SD .num, %xmm0 साथ लोड।

आप compiler output को देखें, तो आप जीसीसी %xmm0 के पुराने मूल्य पर झूठी निर्भरता को तोड़ने के लिए रजिस्टर शून्य सब कुछ तुमने किया था, और pxor कर पहले देखेंगे। (cvtss2sd का खराब डिज़ाइन अपरिवर्तित गंतव्य के ऊपरी 64 बिट्स को छोड़ देता है।) सावधानी के पक्ष में जीसीसी त्रुटियां, और कई मामलों में झूठी निर्भरताओं को तोड़ने के लिए xor-zeroing निर्देशों को सम्मिलित करता है।


आप शायद हो रही है 0 क्योंकि xmm0 के ऊपरी बिट्स शून्य होने के लिए होता है। तो 123.4f के लिए मंथिसा के कम 32 बिट्स में printfdouble (x86 पर आईईईई बाइनरी 64) के रूप में xmm0 के 64 बिट्स को देखता है।

यदि float के साथ समकक्ष प्रयास करें, (उदा। http://www.h-schmidt.net/FloatConverter/IEEE754.html पर), कम आधे में कुछ बिट्स सेट करते हुए, आपको बहुत छोटा असामान्य संख्या मिलती है। यदि आपने %g (वैज्ञानिक नोटेशन) या %a (हेक्स) का उपयोग किया है, तो गैर-शून्य बिट्स दिखाई देंगे। (जब तक आपके पास एमएक्ससीएसआर में शून्य मोड सक्षम नहीं थे।)

+0

यह मेरे लिए आश्चर्यजनक है कि वर्षों से सी ++ लिखने और कई बार प्रिंटफ का उपयोग करने के बावजूद ... मुझे यह कभी नहीं पता था। – cgmb

+1

@cgmb: हाँ, यह स्पष्ट नहीं है। मैं भूल जाता हूं, लेकिन सी में एक var-args फ़ंक्शन को 'फ्लोट' पास करना भी संभव नहीं होगा। पदोन्नति नियम 'डबल' में रूपांतरण निर्दिष्ट करते हैं। मैं उम्मीद करता हूं कि यह संभव था, कम से कम जीएनयू सी के लिए एक प्रारूप विनिर्देशक होगा। ('% एचएफ' या कुछ की तरह)।मेरे लिए, मैं वास्तव में केवल इस सीमा में एएसएम देखने से चिपक गया, क्योंकि अन्यथा संकलक हमेशा आपके लिए रूपांतरण करता है। (इसके अलावा, वास्तव में '% एक' हेक्स-शैली स्वरूपण के साथ 'फ्लोट' मुद्रित करना चाहते हैं) –