-১ by
বাইট @ লিনাকে ধন্যবাদ -২ বাইট @ নীলকে ধন্যবাদ
যেহেতু এটি কেবল জেড 80 মেশিন কোড তাই এই একটিতে xxd -r
প্রচুর পরিমাণে অপ্রিন্টেবল রয়েছে , তাই পরিবর্তিতযোগ্য হেক্সডাম্প রাখুন:
00000000: ddb6 2120 10dd b615 280c 003e 62ff 3e65 ..! ....(..>b.>e
00000010: ffff 3e70 ff76 003e 62ff 3e65 ffff 3e70 ..>p.v.>b.>e..>p
00000020: ff76 .v
এটি অনলাইন চেষ্টা করুন! (পাইথনের সম্পূর্ণ পরীক্ষক)
ব্যাখ্যা
z80golf হ'ল অ্যানার্কি গল্ফের অনুমানযুক্ত Z80 মেশিন, যেখানে call $8000
একটি পুটচার, call $8003
একটি গেটচার, halt
দোভাষীকে প্রস্থান করে, আপনার প্রোগ্রামটি স্থাপন করা হয় $0000
এবং অন্য সমস্ত স্মৃতি শূন্যে ভরা হয়। সমাবেশে প্রোগ্রামগুলি বিকিরণ-প্রমাণ তৈরি করা বেশ শক্ত, তবে সাধারণভাবে কার্যকর কৌশলটি এক-বাইট আইডেম্পোটেন্ট নির্দেশাবলী ব্যবহার করছে। উদাহরণ স্বরূপ,
or c ; b1 ; a = a | c
এটি কেবল একটি বাইট, এবং a | c | c == a | c
, সুতরাং কেবল নির্দেশটি পুনরাবৃত্তি করে এটি বিকিরণ-প্রমাণ তৈরি করা যায়। Z80 উপর, একটি 8-বিট অবিলম্বে লোড, দুই বাইট (যেখানে অবিলম্বে দ্বিতীয় বাইটে হয়) যাতে আপনি লোড করতে পারেন কিছু নিবন্ধগুলিতে নির্ভরযোগ্যভাবেও মান । আমি প্রোগ্রামটির শুরুতে এটিই মূলত করেছি, তাই উত্তরের নীচে আমি সংরক্ষণাগারীর দীর্ঘতরগুলিটি বিশ্লেষণ করতে পারি তবে আমি বুঝতে পেরেছিলাম যে এখানে আরও সহজ উপায় রয়েছে।
প্রোগ্রামটিতে দুটি স্বতন্ত্র পে-লোড রয়েছে, যেখানে তাদের মধ্যে একটির বিকিরণের ফলে ক্ষতিগ্রস্থ হতে পারে। আমি বাইটটি সরিয়ে ফেলা হয়েছে কিনা এবং কিছু নিরঙ্কুশ মেমরি ঠিকানার মানগুলি পরীক্ষা করে প্যালোডের দ্বিতীয় অনুলির আগে মুছে ফেলা বাইট ছিল কিনা তা আমি পরীক্ষা করে দেখছি।
প্রথমত, যদি কোনও বিকিরণ পরিলক্ষিত না হয় তবে আমাদের প্রস্থান করতে হবে:
or a, (ix+endbyte) ; dd b6 21 ; a |= memory[ix+0x0021]
jr nz, midbyte ; 20 10 ; jump to a halt instruction if not zero
যদি কোনও বাইট অপসারণ করা হয়, তবে সমস্ত বাইটগুলি স্থানান্তরিত $0020
হবে এবং এতে সর্বশেষটি থাকবে 76
, তাই $0021
শূন্য হবে। কার্যত কোনও অপ্রয়োজনীয়তা না থাকলেও আমরা প্রোগ্রামের শুরুটি ছড়িয়ে দিতে পারি:
- যদি জাম্প অফসেটটি
$10
সরিয়ে ফেলা হয়, তবে বিকিরণটি সঠিকভাবে সনাক্ত হবে, লাফটি নেওয়া হবে না, এবং অফসেট কোনও বিষয় নয়। পরবর্তী নির্দেশের প্রথম বাইটটি গ্রাস করা হবে, তবে এটি বাইট অপসারণ প্রতিরোধী হিসাবে নকশাকৃত করার কারণে এটি কোনও বিষয় নয়।
- যদি জাম্প অপকোড
$20
সরিয়ে ফেলা হয়, তবে জাম্প অফসেটটি $10
ডিকোড হবে djnz $ffe4
(পরবর্তী নির্দেশ বাইটটি অফসেট হিসাবে গ্রহন করবে - উপরে দেখুন), যা একটি লুপ নির্দেশ - হ্রাস বি, এবং ফলাফল শূন্য না হলে লাফ দেয়। কারণ ffe4-ffff
শূন্যে ভরা (nop
গুলি) , এবং প্রোগ্রামের কাউন্টারটি চারপাশে মোড়ানো, এটি প্রোগ্রামের শুরু 256 বার চালাবে এবং শেষ পর্যন্ত অবিরত থাকবে। আমি এই কাজগুলি অবাক।
- সরানো হচ্ছে
$dd
হিসাবে স্নিপেট ডিকোড বাকি করা হবে or (hl) / ld ($1020), hl
, এবং তারপর প্রোগ্রাম পরবর্তী অংশে স্লাইড করুন। or
কোনো গুরুত্বপূর্ণ রেজিস্টার পরিবর্তন হবে না, এবং কারণ ঐ খ এই সময়ে শূন্য হয়, লেখার বের বাতিল করবেন।
- উইন্ডোটি সরিয়ে
$b6
ফেললে বাকীটি ডিকোড হয়ে যাবে ld ($1020), ix
এবং উপরের মতো এগিয়ে যাবে।
- উইন্ডোটি সরিয়ে
$21
ফেললে ডিকোডারটি খাওয়ার ব্যবস্থা করে $20
, djnz
আচরণকে ট্রিগার করে ।
নোট করুন যে ব্যবহার শূন্যের জন্য সংহত চেকের জন্য or a, (ix+*)
দুটি বাইট সংরক্ষণ করে ld a, (**) / and a / and a
।
আমাদের এখনই সিদ্ধান্ত নিতে হবে যে পে-লোডের দুটি অনুলিপি কার্যকর করতে হবে:
or (ix+midbyte) ; dd b6 15
jr z, otherimpl ; 28 0c
nop ; 00
; first payload
ld a, 'b' ; 3e 62
rst $0038 ; ff
ld a, 'e' ; 3e 65
rst $0038 ; ff
rst $0038 ; ff
ld a, 'p' ; 3e 70
rst $0038 ; ff
midbyte:
halt ; 76
otherimpl:
nop ; 00
ld a, 'b' ; 3e 62
; ... ; ...
rst $0038 ; ff
endbyte:
halt ; 76
দুটি অনুলিপি একটি ন্যাপ দ্বারা পৃথক করা হয়েছে, যেহেতু তাদের মধ্যে বেছে নেওয়ার জন্য আপেক্ষিক লাফ ব্যবহার করা হয় এবং বিকিরণ প্রোগ্রামটিকে এমনভাবে স্থানান্তরিত করতে পারে যা গন্তব্যের পরে প্রথম বাইটটি এড়িয়ে যেতে পারে। অতিরিক্তভাবে, ন্যাপটি শূন্য হিসাবে এনকোড করা থাকে, যা স্থানান্তরিত বাইটগুলি সনাক্ত করা সহজ করে। মনে রাখবেন যে স্যুইচটি নিজেই দুর্নীতিগ্রস্থ হলে কোন পে-লোড চয়ন করা উচিত তা বিবেচ্য নয়, কারণ উভয় অনুলিপিই নিরাপদ। আসুন নিশ্চিত হয়ে নিন যে এটি অবিরাম মেমরিতে ঝাঁপ দেবে না যদিও:
- মোছা
$dd
পরের দুটি বাইট ডিকোড হিসাবে তৈরি করবে or (hl) / dec d
। ক্লোবার্স ডি। কোনও বড় কথা নয়।
- মোছা
$b6
হ'ল এর জন্য একটি অনিবন্ধিত দীর্ঘতর এনকোডিং তৈরি করবে dec d
। উপরের মতই.
- মোছা মুছে ফেলা পরিবর্তে অফসেট হিসাবে
$15
পড়বে $28
এবং $0c
নীচে যেমন কার্যকর হবে ততক্ষণে এগিয়ে চলবে ।
- যখন
$28
disappears, $0c
হিসেবে ডিকোড করা হয় inc c
। পে-লোডের যত্ন নেই c
।
- মোছা হচ্ছে
$0c
- এটাই হ'ল ন্যাপ। অন্যথায়, পে-লোডের প্রথম বাইটটি জাম্প অফসেট হিসাবে পড়ত এবং প্রোগ্রামটি অবিচ্ছিন্ন মেমরিতে ঝাঁপিয়ে দিত।
পে লোড নিজেই বেশ সহজ। আমি মনে করি স্ট্রিংয়ের ছোট আকার এই পদ্ধতিরটিকে একটি লুপের চেয়ে ছোট করে তোলে এবং এইভাবে অবস্থান-স্বাধীন করা আরও সহজ। e
মধ্যে beep
পুনরাবৃত্তি, তাই আমি বন্ধ এক শেভ করতে ld a
। এছাড়াও, কারণ মধ্যে সব স্মৃতি $0038
এবং $8000
zeroed হয়, আমি এটা মাধ্যমে পড়া এবং একটি সংক্ষিপ্ত ব্যবহার করতে পারেন rst
এর বৈকল্পিক call
নির্দেশ, যা শুধুমাত্র জন্য কাজ করে $0
, $8
, $10
এবং তাই, আপ$38
।
পুরানো পন্থা
64 বাইট
00000000: 2e3f 3f2e 3f3f 7e7e a7a7 201f 1e2b 2b1e .??.??~~.. ..++.
00000010: 2b2b 6b00 7ea7 2814 003e 62cd 0080 3e65 ++k.~.(..>b...>e
00000020: cd00 80cd 0080 3e70 cd00 8076 003e 62cd ......>p...v.>b.
00000030: 0080 3e65 cd00 80cd 0080 3e70 cd00 8076 ..>e......>p...v
58 বাইট
00000000: 2e39 392e 3939 7e7e a7a7 2019 3a25 00a7 .99.99~~.. .:%..
00000010: 2814 003e 62cd 0080 3e65 cd00 80cd 0080 (..>b...>e......
00000020: 3e70 cd00 8076 003e 62cd 0080 3e65 cd00 >p...v.>b...>e..
00000030: 80cd 0080 3e70 cd00 8076 ....>p...v
53 বাইট
সম্পাদনার ইতিহাসে এটির একটি ব্যাখ্যা রয়েছে তবে এটি খুব আলাদা নয়।
00000000: 3a34 00a7 a720 193a 2000 a728 1400 3e62 :4... .: ..(..>b
00000010: cd00 803e 65cd 0080 cd00 803e 70cd 0080 ...>e......>p...
00000020: 7600 3e62 cd00 803e 65cd 0080 cd00 803e v.>b...>e......>
00000030: 70cd 0080 76 p...v
কি যদি: কোনও বীনের পরিবর্তে খালি খালি আউটপুট ভাল ছিল
1 বাইট
v
halt
প্রোগ্রামটি সাধারণত হয় তবে রেডিয়েশন যদি এটি সরিয়ে দেয় তবে মেমরিটি শূন্যে পূর্ণ হবে, এটি $8000
অসীম সংখ্যক বার কার্যকর করতে, প্রচুর নাল বাইট মুদ্রণ করে।