সি থেকে বিধানসভা পর্যন্ত


16

মনে করুন যে আমাদের কাছে avr-8 বিটের জন্য সি কোডের নীচের অংশ রয়েছে:

int v1=1;
int v2=2;
v2=v2+v1;

আমি নিম্নলিখিত disassemble আশা

ldi r18, 1;
ldi r19, 2;
add r19, r18;

তবে আমি দৌড়ানোর পরে:

avr-gcc -mmcu=atmega2560 Test.c -o Test.elf

এবং

avr-objdump -S Test.elf > Test.lss

আমি নিম্নলিখিত বিচ্ছিন্ন পেয়েছি

    ldi r24, 0x01   ; 1
    ldi r25, 0x00   ; 0
    std Y+2, r25    ; 0x02
    std Y+1, r24    ; 0x01
    ldi r24, 0x02   ; 2
    ldi r25, 0x00   ; 0
    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03
    ldd r18, Y+3    ; 0x03
    ldd r19, Y+4    ; 0x04
    ldd r24, Y+1    ; 0x01
    ldd r25, Y+2    ; 0x02
    add r24, r18
    adc r25, r19
    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03

এমন কেউ কি আছেন যে আমাকে বিচ্ছিন্ন করার ফলাফল বুঝতে সাহায্য করতে পারেন?

সম্পাদনা করুন: চরটি ব্যবহার করে সমাবেশটি হয়ে উঠুন:

ldi r24, 0x01
std Y+1, r24
ldi r24, 0x02
std Y+2, r24
ldd r25, Y+2
ldd r24, Y+1
add r24, r25
std Y+2, r24

সেখানে কখন স্ট্যান্ডার্ড নির্দেশনা রয়েছে?

উত্তর:


20

সংক্ষিপ্ত উত্তর: আপনার নিবন্ধগুলি 8-বিট এবং আপনার মানগুলি 16-বিট। সুতরাং এটি তাদের দুটি টুকরা করে পরিচালনা করছে।

দীর্ঘ উত্তর:

    ldi r24, 0x01   ; 1
    ldi r25, 0x00   ; 0

8-বিট রেজিস্টারগুলিতে 16-বিট মান 1 সংরক্ষণ করুন r24, r25 Store

    std Y+2, r25    ; 0x02
    std Y+1, r24    ; 0x01

Y + 1, Y + 2 স্ট্যাকের স্থানে এটি সঞ্চয় করুন।

    ldi r24, 0x02   ; 2
    ldi r25, 0x00   ; 0

8 বিট রেজিস্টারগুলিতে আর -24, আর 25-এ 16 বিট মান 2 সঞ্চয় করুন।

    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03

Y + 3, Y + 4 স্ট্যাকের স্থানে এটি সঞ্চয় করুন।

    ldd r18, Y+3    ; 0x03
    ldd r19, Y+4    ; 0x04
    ldd r24, Y+1    ; 0x01
    ldd r25, Y+2    ; 0x02

এগুলি স্ট্যাক থেকে (r18, r19) এবং (r24, r25) এ অনুলিপি করুন

    add r24, r18
    adc r25, r19

দ্বিতীয় সংযোজন সহ ক্যারি সহ (আর 18, আর 19) যুক্ত করুন (আর 24, আর 25)

    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03

এটি স্ট্যাকের পিছনে সংরক্ষণ করুন।

আপনার আসল সমাবেশ পেতে, দুটি জিনিস চেষ্টা করুন:

  • "চর" ভেরিয়েবল ব্যবহার করুন
  • "-O2" সংকলক বিকল্পটি ব্যবহার করুন

সম্পাদনা করুন : সংকলকটি রেজিস্টারে রাখার পরিবর্তে স্ট্যাকের মধ্যে ভেরিয়েবলগুলি সঞ্চয় করার কারণ হ'ল তারা ডিফল্ট "অটো" স্টোরেজ টাইপের সাথে সঞ্চিত রয়েছে। এটি তাদের নিবন্ধগুলিতে অপ্টিমাইজ করতে পারে তবে এটি "রেজিস্টার" স্টোরেজ ক্লাস দিয়ে ঘোষণা করলেও তা করার দরকার নেই।

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


ধন্যবাদ! এটা এখন আরও স্পষ্ট! প্রশ্নে আমার সম্পাদনা সন্ধান করুন।
ডারককফি

1
আমার সম্পাদনা দেখুন। পাশাপাশি -O2 চেষ্টা করুন। হতে পারে -O3, যদিও এটি ভাঙ্গা কোড তৈরি করতে পারে।
pjc50

3
আমি এম্বেডেড কোড সহ প্রচুর পরিমাণে অতিরিক্ত ধরণের সংজ্ঞায়িত করে যা তাদের আকারের সাথে সুনির্দিষ্ট, যেমন স্বাক্ষরযুক্ত ইনটগুলির জন্য "uint8, uint16, uint32", উদাহরণস্বরূপ। আপনি সর্বদা জানেন যে আপনি কোন ধরণের ভেরিয়েবলের সাথে কাজ করছেন। বিশেষত ছোট এমবেডড, স্বাক্ষরিত, ভাসমান, অপরিজ্ঞাত আকারের "ইনট" / স্বাক্ষরকরণগুলি আপনাকে সর্বোপরি সিপিইউ চক্রের জন্য ব্যয় করবে এবং সবচেয়ে খারাপ সময়ে গুরুতর ত্রুটি ঘটবে।
জন ইউ

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

@ pjc50 -O3ভাঙা কোড তৈরি করতে পারে? [উদ্ধৃতি আবশ্যক] (এবং না, সি কোড যা পূর্বনির্ধারিত আচরণের জন্য আহ্বান জানায় এবং তারপরে কিছু অপ্টিমাইজেশন সেটিং গণনা করা হয় না)
মার্শাল

4

আমি যেমন একটি উদাহরণ কোড পেয়েছি আমি আমার মন্তব্যটির উত্তর দেব - অন্যরা ইতিমধ্যে সমস্যার ব্যাখ্যা দিয়ে গেছে।

আমি এম্বেডেড কোড সহ প্রচুর পরিমাণে অতিরিক্ত ধরণের সংজ্ঞায়িত করে যা তাদের আকারের সাথে সুনির্দিষ্ট, যেমন স্বাক্ষরযুক্ত ইনটগুলির জন্য "uint8, uint16, uint32", উদাহরণস্বরূপ। আপনি সর্বদা জানেন যে আপনি কোন ধরণের ভেরিয়েবলের সাথে কাজ করছেন। বিশেষত ছোট এমবেডড, স্বাক্ষরিত, ভাসমান, অপরিজ্ঞাত আকারের "ইনট" / স্বাক্ষরকরণগুলি আপনাকে সর্বোপরি সিপিইউ চক্রের জন্য ব্যয় করবে এবং সবচেয়ে খারাপ সময়ে গুরুতর ত্রুটি ঘটবে।

আমাদের বর্তমান # ডেফাইনগুলি এখানে:

/*
 * Example - the basic data types from our embedded code
 */
typedef unsigned char       uint8;  /*  8 bits */
typedef unsigned short int  uint16; /* 16 bits */
typedef unsigned long int   uint32; /* 32 bits */

typedef char                int8;   /*  8 bits */
typedef short int           int16;  /* 16 bits */
typedef int                 int32;  /* 32 bits */

typedef volatile int8       vint8;  /*  8 bits */
typedef volatile int16      vint16; /* 16 bits */
typedef volatile int32      vint32; /* 32 bits */

typedef volatile uint8      vuint8;  /*  8 bits */
typedef volatile uint16     vuint16; /* 16 bits */
typedef volatile uint32     vuint32; /* 32 bits */

3
ভাল ধারণা; uint8_t এবং বন্ধুদের এখন মানক অংশ: stackoverflow.com/questions/16937459/...
pjc50

কত সহজ! আমরা কিন্ডাকে প্রকল্পের সাথে উত্তরাধিকারসূত্রে পেয়েছি যা সি 98 ছিল, সুতরাং এটির অফিসিয়াল সংস্করণটি জানা ভাল।
জন ইউ

2

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

ফলস্বরূপ আপনি এখনও মেমরিতে মানগুলি সঞ্চয় করতে পারবেন (যদিও আরও সহজ)। আমি সি তে খুব ভাল নই, তবে আইএমএইচও, কিছু রেজিস্টারকে ভেরিয়েবল বরাদ্দ করার কিছু বিকল্প রয়েছে, আপনি যদি চান যে র্যামের পরিবর্তে কিছু ভেরিয়েবলগুলি রেজিস্টারে থাকতে পারে। কিছুটা এইরকম:

register unsigned char VARNAME asm("r3");

মনে রাখবেন যে এই জাতীয় কৌশলগুলির জন্য সমস্ত রেজিস্টার উপলব্ধ নয়।

সুতরাং, উপসংহার? সমাবেশে আপনার প্রোগ্রাম লিখুন। এগুলি সর্বদা ছোট, দ্রুত এবং পড়া / সমর্থন করা সহজ হবে।


এসেম্বলির সি পড়ার চেয়ে সহজ?
dext0rb

@ dext0rb - হ্যাঁ অবশ্যই যদি আপনি উভয়ই যথেষ্ট জানেন। আপনি যদি কেবল সি জানেন, তবে সমাবেশ এবং অন্য যে কোনও ভাষা পড়তে খুব কঠিন হবে।
জনফাউন্ড

আমি শেষ পয়েন্টের সাথে একমত নই, এসেম্বলারের মধ্যে লেখা প্রোগ্রামগুলি পড়া খুব শক্ত are উপরে বর্ণিত উত্স কোডটি কেবল তুলনা করুন। সি কোডটি অনেক বেশি পরিষ্কার এবং খাটো, পাশাপাশি এটির উদ্দেশ্যও। এই পার্থক্যটি কেবল স্ট্রাক ব্যবহার করার সাথে সাথে বৃদ্ধি পায়।
soandos

@ সানডোস - সি কোডটি ছোট, হ্যাঁ। পরিস্কার? আমি নিশ্চিত না. যদি এটি হয় তবে উপরের প্রশ্নটি মোটেই জিজ্ঞাসা করতে হবে না। আসলে "শর্টনেস" এর দাম হ'ল বিবরণের "অস্পষ্টতা"।
জনফাউন্ড

অবশ্যই, যে লোকটি "আমি সি তে তেমন ভাল নই" বলে খাঁটি সমাবেশের গুণাবলী প্রচার করবেন। : ডি
dext0rb
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.