8-বিট এমসিইউগুলিতে সি ইন্টিজার প্রচার


14

উদাহরণ হিসাবে avr-gcc ব্যবহার করে, int প্রকারগুলি 16-বিট প্রশস্ত হতে নির্দিষ্ট করা হয়। সি-তে পূর্ণসংখ্যার প্রচারের কারণে সেগুলি অপারেশনগুলিকে 16-বিট ইনট টাইপগুলিতে রূপান্তরিত করাতে সি-8-বিট অপারেন্ডগুলিতে অপারেশন সম্পাদন করা কি এর অর্থ এই যে কোনও এভিআর-তে সমস্ত 8-বিট পাটিগণিত অপারেশনগুলি সি এর চেয়ে বেশি লেখা থাকলে বেশি সময় নেয় সি এর পূর্ণসংখ্যা প্রচারের কারণে যদি সমাবেশে লেখা হয়?


1
আমার মনে হয় না, সংকলক বুঝতে পারবে যে গন্তব্য ভেরিয়েবলটি একটি (স্বাক্ষরবিহীন) চর, তাই এটি শীর্ষ 8 বিট গণনা করতে বিরক্ত করবে না। তবুও, আমি দেখতে পেলাম যে জিসিসি কখনও কখনও কোডটি অপ্টিমাইজ করার ক্ষেত্রে খুব ভাল হয় না, তাই আপনি যদি এএসএম-এ কোড করেন তবে ফলাফল এমজিআইএইচটি দ্রুত হবে। তবে আপনি যদি খুব শক্ত বাজেটের সীমাবদ্ধতার সাথে খুব সময়-সমালোচনামূলক কাজগুলি / ইন্টারর্ট্পগুলি না করেন তবে আপনার উচিত একটি আরও শক্তিশালী প্রসেসর বেছে নেওয়া এবং এটি সি তে প্রোগ্রাম করা উচিত, বা কেবল নিম্নতর পারফরম্যান্স সম্পর্কে চিন্তা করবেন না (পরিবর্তে সময় বিবেচনা করুন) -থেকে-বাজার, আরও ভাল কোড পঠনযোগ্যতা / পুনরায় ব্যবহারযোগ্যতা, কম বাগ, ইসি ..)।
পরের-হ্যাক 11

আমি চেক করার সময় না পেয়ে ক্ষমা চাইছি। তবে আমি মনে করি জিসিসি-তে একটি কমান্ড-লাইন পতাকা ছিল যা 'পূর্ণসংখ্যা প্রচার' নিয়ন্ত্রণ করবে। কোডের নির্দিষ্ট অংশগুলির জন্য এটি নিয়ন্ত্রণ করার জন্য এমনকি একটি প্রাগমাও থাকতে পারে। পারফরম্যান্স কতটা সমালোচিত? একটি এভিআর প্রচুর ব্যবহারে কিছু গাণিতিকের গতির পার্থক্য কোনও সমস্যা নয়। কোডটি সঠিকভাবে কাজ করার জন্য ফক্সাস। তারপরে যদি কোনও পারফরম্যান্স সমস্যা থাকে তবে এটি কী তা সন্ধান করুন। এসেম্ব্লারগুলিতে কোডিংয়ের সময় নষ্ট করা সহজ হবে, কেবল আপনি এটির কোনও ব্যাপার না তা আবিষ্কার করুন।
গলবার

1
কেবল বিচ্ছিন্ন করে দেখুন এবং সংকলক কী করছে তা দেখুন। খাঁটি ভাষার দৃষ্টিকোণ থেকে হ্যাঁ। এখানে বাস্তবায়ন atypical। রেজিস্টার আকারের সাথে সাধারণত প্রান্তিককরণের চেষ্টা করে, এবং যদি আপনার 16 বিট রেজিস্টার থাকে তবে 8 বিটের গণিতটি 8 এর চেয়ে 16 বিট এ কম সস্তা হয় তবে এটি অন্য উপায় এবং 8 বিট এমসিইউ দিয়ে এটি বাস্তবায়নের জন্য বুদ্ধিমান হয় 16 বিট হিসাবে সুতরাং আপনার সম্ভবত উচর ব্যবহার করা উচিত যেখানে আপনি এই বিষয়ে যত্নশীল তবে এটি যে কোনও সাধারণ প্রোগ্রামিং অভ্যাস হিসাবে তৈরি না করে এটি অন্য যে কোনও জায়গায় আপনাকে সবচেয়ে বেশি কষ্ট দেয়।
old_timer

3
মনে রাখবেন: মন্তব্যে প্রশ্নের উত্তর দেওয়া থেকে বিরত থাকুন।
পাইপ

4
এই ধরণের প্রশ্নগুলি এসও-তে সি বিশেষজ্ঞদের জিজ্ঞাসা করা আরও ভাল, কারণ এটি খাঁটি সফ্টওয়্যার প্রশ্ন। সিতে পূর্ণসংখ্যা প্রচার কিছুটা জটিল বিষয় - গড় সি প্রোগ্রামারটির এটি সম্পর্কে প্রচুর ভুল ধারণা থাকবে।
লন্ডিন

উত্তর:


16

দীর্ঘ সংক্ষিপ্ত বিবরণ:

16 বিটের পূর্ণসংখ্যার প্রচার সর্বদা স্থান নেয় - সি স্ট্যান্ডার্ড এটি প্রয়োগ করে। তবে সংকলকটি 8 বিটের নিচে গণনাটি অপ্টিমাইজ করার অনুমতি দেয় (এম্বেড করা সিস্টেমের সংকলকগুলি সাধারণত এই ধরনের অপ্টিমাইজেশনে বেশ ভাল থাকে), যদি এটি অনুমান করতে পারে যে সাইনটি একই রকম হবে তবে টাইপটি প্রচার করা থাকলে এটি হত।

এই সবসময় তা হয় না! পূর্ণসংখ্যার প্রচারের ফলে অন্তর্নিহিত স্বাক্ষর পরিবর্তনগুলি এম্বেড থাকা সিস্টেমে বাগগুলির একটি সাধারণ উত্স।

বিস্তারিত ব্যাখ্যা এখানে পাওয়া যাবে: অন্তর্ভুক্ত প্রকার প্রচারের নিয়ম


8
unsigned int fun1 ( unsigned int a, unsigned int b )
{
    return(a+b);
}

unsigned char fun2 ( unsigned int a, unsigned int b )
{
    return(a+b);
}

unsigned int fun3 ( unsigned char a, unsigned char b )
{
    return(a+b);
}

unsigned char fun4 ( unsigned char a, unsigned char b )
{
    return(a+b);
}

যেমনটি প্রত্যাশিত ফান 1 সমস্ত ইনটস তাই 16 বিট গণিত

00000000 <fun1>:
   0:   86 0f           add r24, r22
   2:   97 1f           adc r25, r23
   4:   08 95           ret

যদিও প্রযুক্তিগতভাবে এটি ভুল হিসাবে কোড দ্বারা ডেকে আনা একটি 16 বিট সংযোজন ভুল, এমনকি অপ্রচলিত এই সংকলক ফলাফল আকারের কারণে অ্যাডসি অপসারণ করেছে।

00000006 <fun2>:
   6:   86 0f           add r24, r22
   8:   08 95           ret

সত্যিকার অর্থে এখানে পদোন্নতি ঘটে না, কম্পাইলাররা এটি নিশ্চিত করে না যে সংস্করণটি কীভাবে এই সূচনাটি ঘটেছে, তা আমার কেরিয়ারের প্রথম দিকে চলে গিয়েছিল এবং সংযোজনকারীরা ক্রমবর্ধমান (যেমন উপরের মত) প্রচার করেও প্রচার করে নি, যদিও আমি প্রচার করি এটি উচার গণিত করতে বলেছিলেন, অবাক হন না।

0000000a <fun3>:
   a:   70 e0           ldi r23, 0x00   ; 0
   c:   26 2f           mov r18, r22
   e:   37 2f           mov r19, r23
  10:   28 0f           add r18, r24
  12:   31 1d           adc r19, r1
  14:   82 2f           mov r24, r18
  16:   93 2f           mov r25, r19
  18:   08 95           ret

এবং আদর্শ, আমি জানি এটি 8 বিট, একটি 8 বিট ফলাফল চাই তাই আমি কেবল এটি 8 বিটটি সারা পথ দিয়ে করতে বলেছি।

0000001a <fun4>:
  1a:   86 0f           add r24, r22
  1c:   08 95           ret

সুতরাং সাধারণভাবে এটি নিবন্ধের আকারের জন্য লক্ষ্য করা ভাল, যা আদর্শভাবে একটি (ইউ) ইন্টের আকার, এর মতো একটি 8 বিট এমসিইউর জন্য সংকলক লেখককে একটি আপস করতে হয়েছিল ... পয়েন্টটি অভ্যাস তৈরি না করা গণিতের জন্য উচর ব্যবহার করে আপনি জানেন যে 8 টির বেশি বিটের দরকার নেই কারণ আপনি যখন সেই কোডটি সরান বা বড় রেজিস্টার সহ প্রসেসরে নতুন কোড লেখেন এখন সংকলকটির মুখোশ পড়া এবং প্রসারিত করতে হবে, যা কিছু স্থানীয়ভাবে কিছু নির্দেশাবলীতে করে থাকে, এবং অন্যরা না।

00000000 <fun1>:
   0:   e0800001    add r0, r0, r1
   4:   e12fff1e    bx  lr

00000008 <fun2>:
   8:   e0800001    add r0, r0, r1
   c:   e20000ff    and r0, r0, #255    ; 0xff
  10:   e12fff1e    bx  lr

আরও 8 বিট খরচ জোর করা। আমি সামান্য / প্রচুর প্রতারণা করেছি, এটিকে আরও ন্যায্য উপায়ে দেখার জন্য আরও জটিল জটিল উদাহরণগুলির প্রয়োজন হবে।

মন্তব্য আলোচনার ভিত্তিতে ইডিটি

unsigned int fun ( unsigned char a, unsigned char b )
{
    unsigned int c;
    c = (a<<8)|b;
    return(c);
}

00000000 <fun>:
   0:   70 e0           ldi r23, 0x00   ; 0
   2:   26 2f           mov r18, r22
   4:   37 2f           mov r19, r23
   6:   38 2b           or  r19, r24
   8:   82 2f           mov r24, r18
   a:   93 2f           mov r25, r19
   c:   08 95           ret

00000000 <fun>:
   0:   e1810400    orr r0, r1, r0, lsl #8
   4:   e12fff1e    bx  lr

আকর্ষণ নেই. যদিও অপ্টিমাইজার কেন সেই অতিরিক্ত নির্দেশ রেখেছিল, আপনি কি আর 19 তে এলডি ব্যবহার করতে পারবেন না? (আমি যখন জিজ্ঞাসা করেছি তখন উত্তরটি আমি জানতাম)।

EDIT2

avr জন্য

avr-gcc --version
avr-gcc (GCC) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

খারাপ অভ্যাস এড়াতে বা 8 বিটের তুলনা করা নয়

arm-none-eabi-gcc --version
arm-none-eabi-gcc (GCC) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

পরিষ্কারভাবে অপ্টিমাইজেশন চালু ছিল এটি আমার আউটপুটটির সাথে কীভাবে তুলনা করে তা দেখতে আপনার নিজের সংকলকটির সাথে চেষ্টা করতে কেবল এক সেকেন্ড সময় নেয়, তবে যাইহোক:

whatever-gcc -O2 -c so.c -o so.o
whatever-objdump -D so.o

এবং হ্যাঁ বাইট সাইজের ভেরিয়েবলের জন্য বাইটস ব্যবহার করা অবশ্যই কোনও এভিআর, পিক ইত্যাদিতে আপনার স্মৃতি রক্ষা করবে এবং আপনি এটি সংরক্ষণের জন্য সত্যই চেষ্টা করতে চান ... আপনি যদি এটি ব্যবহার করছেন তবে এখানে যতটা সম্ভব দেখানো হয়েছে স্মৃতিতে যতটা সম্ভব নিবন্ধভুক্ত হতে চলেছে, তাই ফ্ল্যাশ সাশ্রয় অতিরিক্ত ভেরিয়েবল না রেখেই আসে, রাম সাশ্রয়টি আসল নাও হতে পারে ..


2
"কম্পাইলাররা এটি নিশ্চিত করে না যে সংস্করণটি কীভাবে এই সূচনাটি ঘটেছিল তা শুরু হয়েছিল, আমার কেরিয়ারের প্রথম দিকে এবং এই সংকলক সত্ত্বেও অর্ডার অফ আউট (ঠিক যেমন উপরে) প্রচার করা সত্ত্বেও আমি প্রচারকে বলেছিলাম যে এটি উচার গণিত করতে বলেছি, অবাক না। " কারণ এমবেডেড সিস্টেম সি কম্পাইলার ভয়ঙ্কর মান অনুরূপ আছে ব্যবহৃত হয় :) কম্পাইলার সাধারণত নিখুত অনুমতি দেওয়া হয়, কিন্তু এখানে এটা কেটে দিতে পারে না যে ফলাফলের একটি ইন মাপসই করা হবে unsigned char, তাই এটি হয়ে গেছে প্রয়োজনীয় 16 বিট প্রচার সম্পাদন করতে, মান অনুসারে
লন্ডিন

1
@ বিড_টিমার (a<<8)|bযে কোনও সিস্টেমের জন্য সর্বদা ভুল যেখানে int16 বিট রয়েছে। স্বাক্ষরিত যা aস্পষ্টভাবে প্রচারিত হবে intaএমএসবিতে যদি কোনও মান ধরে থাকে তবে আপনি সেই ডেটাটি একটি 16 বিট সংখ্যার সাইন বিটে স্থানান্তরিত করবেন, যা অপরিজ্ঞাত আচরণের জন্য প্রার্থনা করে।
লন্ডিন

1
ফান 3 হ'ল মজাদার .. কোনও ... সংকলক সম্পূর্ণরূপে নিরঙ্কুশিত ... গণনা করা হয়েছে যে r1 সর্বদা 0 জিসিসিতে থাকে এবং র, আরবি, {আরএইচ, আরএল} ভেরিয়েবলগুলির জন্য রেজিস্টারগুলি ই, বি, এবং ফলাফলটি নির্দেশ করে, সংকলকটি করতে পারত: 1) Mov rh, r1; 2) মুভ আরএল, রা; 2) আরএল যোগ করুন, আরবি; 3) অ্যাডিসি আরএইচ, আরএইচ; 4) ret। 4 টি নির্দেশনা, বনাম 7 বা 8 ... নির্দেশ 1 টি ldi rh, 0 এ পরিবর্তন করা যেতে পারে।
পরের হ্যাক 14

1
এটি ব্যবহারের সংকলক এবং প্রাসঙ্গিক বিকল্পগুলি নির্দিষ্ট করে দিলে এটি আরও ভাল উত্তর হবে।
রাসেল বোরোগোভ

1
ইন্ট / চর ইত্যাদি ব্যবহার এড়াতে এবং এর চেয়ে আরও স্পষ্ট এবং পঠনযোগ্য int16_t এবং int8_t ব্যবহার করা ভাল idea
ব্যবহারকারী

7

অগত্যা প্রয়োজনীয় নয়, যেহেতু আধুনিক সংকলকগণ উত্পন্ন কোডটি অনুকূলকরণে ভাল কাজ করে। উদাহরণস্বরূপ, আপনি যদি z = x + y;সমস্ত ভেরিয়েবলগুলি লিখেন তবে গণনা সম্পাদনের আগে সংকলকটিকে unsigned charতাদের প্রচার করতে হবে unsigned int। তবে, যেহেতু শেষ ফলাফল প্রচার ছাড়াই ঠিক একই হবে, সংকলকটি কোড উত্পন্ন করবে যা কেবলমাত্র 8-বিট ভেরিয়েবল যুক্ত করে।

অবশ্যই, এটি সর্বদা ক্ষেত্রে হয় না, উদাহরণস্বরূপ ফলাফলটি z = (x + y)/2;উপরের বাইটের উপর নির্ভর করে, তাই প্রচার হবে। মধ্যবর্তী ফলাফলটি আবার জমা দিয়ে সমাবেশের আশ্রয় না নিয়ে এটি এড়ানো যায় unsigned char

সংকলক বিকল্পগুলি ব্যবহার করে এ জাতীয় কিছু অদক্ষতা এড়ানো যায়। উদাহরণস্বরূপ, অনেক 8-বিট সংকলক intসি-এর পরিবর্তে 1 বাইটে অঙ্কের ধরণের সাথে মানিয়ে নিতে একটি প্রগমা বা একটি কমান্ড-লাইন সুইচ থাকে have


4
"সংকলকটির স্বাক্ষরবিহীন ইনটকে উন্নীত করার জন্য প্রয়োজনীয়" " না, সংকলকটি তাদের প্রচার করতে হবে int, কারণ charসম্ভবত intকোনও প্ল্যাটফর্মের মত রূপান্তর র‌্যাঙ্কটি সম্ভবত নেই ।
লন্ডিন

3
"উদাহরণস্বরূপ, অনেক 8-বিট সংকলক সি-এর প্রয়োজন অনুসারে int এর পরিবর্তে 1 বাইটে অঙ্কের প্রকারের সাথে মানিয়ে নিতে একটি প্রগমা বা কমান্ড-লাইন সুইচ রাখেন have" সি স্ট্যান্ডার্ড গণনা ভেরিয়েবলগুলি 1 বাইটে বরাদ্দ করতে দেয়। এটি কেবল প্রয়োজন যে গণনার ধ্রুবক অবশ্যই হওয়া উচিত int(হ্যাঁ এটি বেমানান)। সি 11 6.7.2.2Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined...
লন্ডিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.