x86-16 মেশিন কোড (বুদ্বুদর্ট int8_t), 20 19 বাইট
x86-64 / 32 মেশিন কোড (জাম্পডাউনসর্ট) 21 19 বাইট
পরিবর্তণের:
lodsb
/ পেডিয়াগুলি / cmp [si],al
আইডিয়াটির জন্য ধন্যবাদ , এবং এটি যে পয়েন্টার ইনক্রিমেন্ট / রিসেটের সাথে একসাথে রেখেছি যা আমি দেখছিলাম । প্রয়োজন নেই al
/ ah
বৃহত্তর পূর্ণসংখ্যার জন্য আমাদের প্রায় একই কোডটি ব্যবহার করতে দেয়।
নতুন (তবে সম্পর্কিত) অ্যালগরিদম, অনেকগুলি প্রয়োগ পরিবর্তন হয়: বুবলি সিলেকশনসোর্ট বাইটস বা ডিফোর্ডের জন্য একটি ছোট x86-64 প্রয়োগের অনুমতি দেয়; বিরতি এমনকি x86-16 এ (বাইট বা শব্দ)। আমার বাবলসার্টের আকার = 1 তে থাকা বাগটিও এড়িয়ে চলে। নিচে দেখ.
দেখা যাচ্ছে যে আমার বুবলি সিলেকশন বাছাইয়ের সাথে অদলবদলগুলি যতবারই আপনি খুঁজে পান একটি নতুন মিনিট ইতিমধ্যে একটি পরিচিত অ্যালগরিদম, জাম্পডাউন সাজান। এটি বুদ্বুদ সাজানোর ক্ষেত্রে উল্লেখ করা হয়েছে : একটি প্রত্নতাত্ত্বিক অ্যালগরিদমিক বিশ্লেষণ (যেমন কীভাবে চুষে সত্ত্বেও বুদ্বুদ বাছাই জনপ্রিয় হয়েছিল)।
স্থানটিতে 8-বিট স্বাক্ষরিত পূর্ণসংখ্যার সাজান । (সাইন করা হয়নি একই কোড আকার, শুধু পরিবর্তন jge
একটি থেকে jae
)। সদৃশ কোন সমস্যা নয়। আমরা 8-এর (একটি স্মৃতির গন্তব্য সহ) 16-বিট ঘোরানো ব্যবহার করে অদলবদল করি।
বুদ্বুদ বাছাই কর্মক্ষমতা জন্য স্তন্যপান , কিন্তু আমি পড়েছি যে এটি মেশিন কোডে প্রয়োগ করা সবচেয়ে ক্ষুদ্রতম। এটি বিশেষত সত্য বলে মনে হয় যখন সংলগ্ন উপাদানগুলি অদলবদলের জন্য বিশেষ কৌশল আছে ricks এটি বেশিরভাগ ক্ষেত্রে এর একমাত্র সুবিধা, তবে কখনও কখনও (বাস্তব জীবনে এম্বেড হওয়া সিস্টেমে) এটি খুব সংক্ষিপ্ত তালিকার জন্য ব্যবহার করার পক্ষে যথেষ্ট সুবিধা।
আমি কোনও অদলবদলে প্রাথমিক সমাপ্তি বাদ দিয়েছি । আমি উইকিপিডিয়ায় "অপ্টিমাইজড" বাবলসোর্ট লুপটি ব্যবহার করেছি যা এটির n − 1
জন্য দৌড়ানোর সময় শেষ আইটেমগুলির দিকে নজর দেওয়া এড়িয়ে যায়n
সময় , সুতরাং বাইরের লুপের কাউন্টারটি অভ্যন্তরীণ লুপের জন্য উপরের আবদ্ধ।
এনএএসএম তালিকা ( nasm -l /dev/stdout
), বা সরল উত্স
2 address 16-bit bubblesort16_v2:
3 machine ;; inputs: pointer in ds:si, size in in cx
4 code ;; requires: DF=0 (cld)
5 bytes ;; clobbers: al, cx=0
6
7 00000000 49 dec cx ; cx = max valid index. (Inner loop stops 1 before cx, because it loads i and i+1).
8 .outer: ; do{
9 00000001 51 push cx ; cx = inner loop counter = i=max_unsorted_idx
10 .inner: ; do{
11 00000002 AC lodsb ; al = *p++
12 00000003 3804 cmp [si],al ; compare with *p (new one)
13 00000005 7D04 jge .noswap
14 00000007 C144FF08 rol word [si-1], 8 ; swap
15 .noswap:
16 0000000B E2F5 loop .inner ; } while(i < size);
17 0000000D 59 pop cx ; cx = outer loop counter
18 0000000E 29CE sub si,cx ; reset pointer to start of array
19 00000010 E2EF loop .outer ; } while(--size);
20 00000012 C3 ret
22 00000013 size = 0x13 = 19 bytes.
cx
অভ্যন্তরীণ লুপের চারপাশে ধাক্কা / পপ মানে এটি cx
= বহিরাগত_কেক্সের সাথে 0 অবধি চলে।
নোট করুন যে rol r/m16, imm8
কোনও 8086 নির্দেশ নয়, এটি পরে যুক্ত হয়েছিল (186 বা 286), তবে এটি 8086 কোড হওয়ার চেষ্টা করছে না, কেবল 16-বিট x86। যদি এসএসই 4.1 phminposuw
সহায়তা করে, আমি এটি ব্যবহার করব।
এটির একটি 32-বিট সংস্করণ (এখনও 8-বিট ইন্টিজারে কিন্তু 32-বিট পয়েন্টার / কাউন্টার সহ অপারেটিং) 20 বাইট (অপারেন্ড-আকারের উপসর্গ চালু rol word [esi-1], 8
)
বাগ: আকার = 1 কে আকার = 65536 হিসাবে বিবেচনা করা হয়, কারণ কোনও কিছুই আমাদের সিএক্স = 0 সহ বাইরের ডো / তে প্রবেশ করতে বাধা দেয় না। (আপনি সাধারণত jcxz
এটির জন্য ব্যবহার করতেন )) তবে সৌভাগ্যক্রমে 19 বাইট জাম্পডাউন সাজানটি 19 বাইট এবং এতে সমস্যা নেই।
আসল x86-16 20 বাইট সংস্করণ ( পেড 7 জি এর ধারণা ব্যতীত)। স্থান বাঁচাতে অনুমতি দেওয়া হয়েছে, বর্ণনার সাথে এর সম্পাদনা ইতিহাস দেখুন ।
কর্মক্ষমতা
আংশিক-ওভারল্যাপিং স্টোর / পুনরায় লোড (মেমরি-গন্তব্য ঘোরানোর ক্ষেত্রে) আধুনিক x86 সিপিইউগুলিতে (অর্ডার অ্যাটম ব্যতীত) স্টোর-ফরওয়ার্ডিং স্টল তৈরি করে। যখন কোনও উচ্চ মানের উপরের দিকে বুদবুদ হয়, তখন এই অতিরিক্ত লম্বাটি লুপ বহনকারী নির্ভরতা শৃঙ্খলার অংশ। স্টোর / পুনরায় লোড প্রথম স্থানে চুষে পায় (হাসওলে 5 টি চক্রের স্টোর-ফরোয়ার্ডিং ল্যাটেন্সির মতো) তবে একটি ফরোয়ার্ডিং স্টল এটিকে 13 টি চক্রের মতো আরও উপরে নিয়ে আসে। আউট-অফ-অর্ডার এক্সিকিউশনে এটি লুকিয়ে রাখতে সমস্যা হবে।
আরও দেখুন: স্ট্যাক ওভারফ্লো: একই রূপায়নের সাথে এর সংস্করণটির জন্য স্ট্রিং বাছাইয়ের জন্য বুদ্বুদ সাজান , তবে কোনও অদলবদল প্রয়োজন না হলে প্রাথমিক পর্যায়ে। এটি অদলবদল করার জন্য xchg al, ah
/ mov [si], ax
ব্যবহার করে যা 1 বাইট দীর্ঘ এবং কিছু সিপিইউতে আংশিক-নিবন্ধক স্টল তৈরি করে। (তবে এটি মেমরি-ডিএসটি ঘোরার চেয়ে আরও ভাল হতে পারে, যার আবার মানটি লোড করা দরকার)। আমার মন্তব্যে কিছু পরামর্শ আছে ...
x86-64 / x86-32 জাম্পডাউন বাছাই করুন, 19 বাইট (প্রকরণ 32_t সাজান)
X86-64 সিস্টেম ভি কলিং কনভেনশন
int bubblyselectionsort_int32(int dummy, int *array, int dummy, unsigned long size);
(রিটার্ন মান = সর্বোচ্চ (অ্যারে [])) হিসাবে সি ব্যবহার করে কল করা ।
এটি https://en.wikedia.org/wiki/Selection_sort , তবে ন্যূনতম উপাদানটির অবস্থান মনে রাখার পরিবর্তে বর্তমান প্রার্থীকে অ্যারেতে অদলবদল করুন । আপনি একবার ন্যূনতম (অর্ডারডড_রিগেশন) সন্ধান করলে, এটি সাধারণ বাছাই বাছাইয়ের মতো সাজানো অঞ্চলের শেষে সংরক্ষণ করুন। এটি একের পর এক সাজানো অঞ্চল বাড়ায়। ( rsi
কোডটিতে, বাছাই করা অঞ্চলের শেষের এক দিকে ইঙ্গিত করে; lodsd
এটি অগ্রসর হয় এবং মিনিটটি এটিতে mov [rsi-4], eax
আবার জমা করে দেয়))
জাম্প ডাউন সাজান নামটি বুদ্বুদ সাজানোর ক্ষেত্রে ব্যবহৃত হয় : একটি প্রত্নতাত্ত্বিক অ্যালগরিদমিক বিশ্লেষণ । আমি অনুমান করি আমার সাজানটি সত্যিই একটি জাম্প আপ বাছাই, কারণ উচ্চ উপাদানগুলি উপরের দিকে লাফ দেয়, নীচের অংশটিকে সাজানো হয় না, শেষ হয়।
এই এক্সচেঞ্জ ডিজাইনের ফলে অ্যারের অরসোর্টড অংশটি বেশিরভাগ বিপরীত সাজানো ক্রমে শেষ হয়, পরে প্রচুর অদলবদল হয়। (কারণ আপনি একটি বড় প্রার্থী দিয়ে শুরু করেছেন, এবং নিম্ন এবং নিম্ন প্রার্থী দেখতে থাকুন, তাই আপনি অদলবদল করতে থাকুন)) আমি এটিকে "বুদ্বি" বলেছি যদিও এটি উপাদানগুলি অন্য দিক থেকে সরিয়ে দেয়। এটি উপাদানকে যেভাবে সরায় তা পিছনে সন্নিবেশ-সাজানোর মতো কিছুটা। এটি কার্যকরভাবে দেখতে, জিডিবি ব্যবহার display (int[12])buf
করুন, অভ্যন্তরীণ loop
নির্দেশের উপর একটি ব্রেকপয়েন্ট স্থাপন করুন এবং ব্যবহার করুন c
(চালিয়ে যান)। পুনরাবৃত্তি করতে রিটার্ন টিপুন। ("ডিসপ্লে" কমান্ডটি প্রতিবার ব্রেকআপপয়েন্টে চাপলে পুরো অ্যারে রাজ্য মুদ্রণ করতে জিডিবি পায়))
xchg
মেমের সাথে একটি অন্তর্নিহিত lock
উপসর্গ রয়েছে যা এটি অতিরিক্ত ধীর করে তোলে। সম্ভবত একটি দক্ষ লোড / স্টোর অদলবদলের চেয়ে ধীর গতি বাড়ানোর ক্রম সম্পর্কে; xchg m,r
স্কাইলেকে 23 সি থ্রুটপুট প্রতি এক, তবে একটি দক্ষ অদলবস্থার (রেজি, মেমি) জন্য একটি টিএমপি রেগের সাথে লোড / স্টোর / মুভি লোড / স্টোর / মুভ প্রতিটি ঘড়ি প্রতি এক উপাদান স্থানান্তর করতে পারে। এটি একটি এএমডি সিপিইউতে আরও খারাপ অনুপাত হতে পারে যেখানে loop
নির্দেশটি দ্রুত হয় এবং ততটা অভ্যন্তরীণ লুপকে বাধা দেয় না, তবে শাখা মিসগুলি এখনও একটি বড় বাধা হয়ে দাঁড়াবে কারণ অদলবদলগুলি সাধারণ (এবং অদৃশ্য অঞ্চলটি ছোট হওয়ার সাথে সাথে আরও সাধারণ হয়ে উঠবে) )।
2 Address ;; hybrib Bubble Selection sort
3 machine bubblyselectionsort_int32: ;; working, 19 bytes. Same size for int32 or int8
4 code ;; input: pointer in rsi, count in rcx
5 bytes ;; returns: eax = max
6
7 ;dec ecx ; we avoid this by doing edi=esi *before* lodsb, so we do redundant compares
8 ; This lets us (re)enter the inner loop even for 1 element remaining.
9 .outer:
10 ; rsi pointing at the element that will receive min([rsi]..[rsi+rcx])
11 00000000 56 push rsi
12 00000001 5F pop rdi
13 ;mov edi, esi ; rdi = min-search pointer
14 00000002 AD lodsd
16 00000003 51 push rcx ; rcx = inner counter
17 .inner: ; do {
18 ; rdi points at next element to check
19 ; eax = candidate min
20 00000004 AF scasd ; cmp eax, [rdi++]
21 00000005 7E03 jle .notmin
22 00000007 8747FC xchg [rdi-4], eax ; exchange with new min.
23 .notmin:
24 0000000A E2F8 loop .inner ; } while(--inner);
26 ; swap min-position with sorted position
27 ; eax = min. If it's not [rsi-4], then [rsi-4] was exchanged into the array somewhere
28 0000000C 8946FC mov [rsi-4], eax
29 0000000F 59 pop rcx ; rcx = outer loop counter = unsorted elements left
30 00000010 E2EE loop .outer ; } while(--unsorted);
32 00000012 C3 ret
34 00000013 13 .size: db $ - bubblyselectionsort_int32
0x13 = 19 bytes long
জন্য একই কোড আকার int8_t
ব্যবহার: lodsb
/ scasb
, AL
, এবং পরিবর্তন [rsi/rdi-4]
করার -1
। একই মেশিন কোডটি 8/32-বিট উপাদানগুলির জন্য 32-বিট মোডে কাজ করে। 8/16-বিট উপাদানগুলির জন্য 16-বিট মোডে অফসেট পরিবর্তিত হয়ে পুনরায় তৈরি করা দরকার (এবং 16-বিট অ্যাড্রেসিং মোডগুলি আলাদা এনকোডিং ব্যবহার করে)। তবে এখনও সবার জন্য 19 বাইট।
এটি dec ecx
এগিয়ে যাওয়ার আগে যে উপাদানটি সবেমাত্র লোড হয়েছিল তার সাথে তুলনা করে প্রাথমিকটি এড়িয়ে চলে । বাইরের লুপের শেষ পুনরাবৃত্তিতে এটি শেষ উপাদানটি লোড করে, এটি নিজের চেয়ে কম কিনা তা পরীক্ষা করে। এটি এটি আকার = 1 দিয়ে কাজ করতে দেয়, যেখানে আমার বাবলসোর্ট ব্যর্থ হয় (এটি আকার = 65536 হিসাবে বিবেচনা করে)।
আমি এই কলারটি ব্যবহার করে এই সংস্করণটি (জিডিবিতে) পরীক্ষা করেছি: এটি অনলাইনে চেষ্টা করুন! । এটি এটি টিআইওতে চালাতে পারেন তবে অবশ্যই কোনও ডিবাগার বা মুদ্রণ করা যাবে না। তবুও, যেটি _start
এটিকে প্রস্থান-স্থিতি = বৃহত্তম উপাদান = 99 দিয়ে প্রস্থান করে, আপনি দেখতে পাচ্ছেন এটি কাজ করে।
[7 2 4 1] -> [4 2 3 1]
। এছাড়াও, CSV তালিকাটি বন্ধনীগুলির মধ্যে থাকতে পারে? এছাড়াও, নির্দিষ্ট ইনপুট ফর্ম্যাটটি কিছু ভাষার জন্য খুব উপযুক্ত এবং অন্যের পক্ষে খারাপ। এটি কিছু জমা দেওয়ার জন্য ইনপুটকে একটি বড় অংশ পার্সিং করে এবং অন্যদের জন্য অপ্রয়োজনীয় করে তোলে।