x86 32-বিট মেশিন কোড খণ্ড, 1 বাইট
48 dec eax
EAX ইনপুট, EAX এ আউটপুট: 0 সত্য, মিথ্যা জন্য শূন্য নয়। (সত্যের জন্য জেডএফ পতাকা সেটটি ফেলে রাখে, মিথ্যাটির জন্য আনসেট রাখুন, যাতে আপনি পারেন je was_equal)। একটি "বোনাস" হিসাবে, আপনাকে মোড়ানো সম্পর্কে চিন্তা করতে হবে না; 32-বিট x86 কেবল 4GiB মেমরিকে সম্বোধন করতে পারে, তাই আপনি পুরোপুরি মোড়ানো এবং খুঁজে পেতে 1 == 2**32 + 1বা কিছু খুঁজে দেওয়ার জন্য এমকে যথেষ্ট বড় করতে পারবেন না ।
কলযোগ্য ফাংশন করতে, এম বার 0xC3 retপুনরাবৃত্তি করার পরে একটি নির্দেশ যুক্ত করুন 0x48। (মোট গণনাতে গণনা করা হয়নি, কারণ প্রতিযোগিতা করতে সক্ষম হওয়ার জন্য অনেক ভাষার কেবল ফাংশন বডি বা একটি অভিব্যক্তি পুনরাবৃত্তি করা প্রয়োজন)।
প্রোটোটাইপ সঙ্গে গনুহ C থেকে Calleable __attribute__((regparm(1))) int checkeqM(int eax); গনুহ সি এর regparmএক্স 86 ফাংশন বৈশিষ্ট্য , মত -mregparm, প্রথম পূর্ণসংখ্যা ARG পাস EAX ব্যবহার করে।
উদাহরণস্বরূপ, এই সম্পূর্ণ প্রোগ্রামটি 2 টি আরগস নেয় এবং জেআইটি এম এম নির্দেশের কপিগুলি + এ retএকটি বাফারে নিয়ে যায় এবং তারপরে এটিকে ফাংশন হিসাবে ডাকে। (এক্সিকিউটেবল গাদা প্রয়োজন; এর সাথে সংকলন gcc -O3 -m32 -z execstack)
/******* Test harness: JIT into a buffer and call it ******/
// compile with gcc -O3 -no-pie -fno-pie -m32 -z execstack
// or use mprotect or VirtualProtect instead of -z execstack
// or mmap(PROT_EXEC|PROT_READ|PROT_WRITE) instead of malloc
// declare a function pointer to a regparm=1 function
// The special calling convention applies to this function-pointer only
// So main() can still get its args properly, and call libc functions.
// unlike if you compile with -mregparm=1
typedef int __attribute__((regparm(1))) (*eax_arg_funcptr_t)(unsigned arg);
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc<3) return -1;
unsigned N=strtoul(argv[1], NULL, 0), M = strtoul(argv[2], NULL, 0);
char *execbuf = malloc(M+1); // no error checking
memset(execbuf, 0x48, M); // times M dec eax
execbuf[M] = 0xC3; // ret
// Tell GCC we're about to run this data as code. x86 has coherent I-cache,
// but this also stops optimization from removing these as dead stores.
__builtin___clear_cache (execbuf, execbuf+M+1);
// asm("" ::: "memory"); // compiler memory barrier works too.
eax_arg_funcptr_t execfunc = (eax_arg_funcptr_t) execbuf;
int res = execfunc(N);
printf("%u == %u => %d\n", N,M, res );
return !!res; // exit status only takes the low 8 bits of return value
}
ভার্চুয়াল মেমরিতে নন-পিআইই এক্সিকিউটেবলগুলি লোড হয়; একটি বৃহত্তর সংলগ্ন malloc করতে পারেন।
$ gcc -g -O3 -m32 -no-pie -fno-pie -fno-plt -z execstack coderepeat-i386.c
$ time ./a.out 2747483748 2747483748 # 2^31 + 600000100 is close to as big as we can allocate successfully
2747483748 == 2747483748 => 0
real 0m1.590s # on a 3.9GHz Skylake with DDR4-2666
user 0m0.831s
sys 0m0.755s
$ echo $?
0
# perf stat output:
670,816 page-faults # 0.418 M/sec
6,235,285,157 cycles # 3.885 GHz
5,370,142,756 instructions # 0.86 insn per cycle
নোট করুন যে জিএনইউ সি অবজেক্ট মাপগুলি ptrdiff_t(স্বাক্ষরিত 32-বিট) এর চেয়ে বড় সমর্থন করে না , mallocএবং memsetএখনও কাজ করে, তাই এই প্রোগ্রামটি সফল হয়।
এআরএম থাম্ব মেশিন কোড টুকরা, 2 বাইট
3802 subs r0, #2
প্রথম আর্গ ইন r0এবং রিটার্ন ভ্যালু r0হ'ল স্ট্যান্ডার্ড এআরএম কলিং কনভেনশন। এটি পতাকা ( sপ্রত্যয়) সেট করে । মজার ব্যাপার; এর নন -ফ্ল্যাগ-সেটিং সংস্করণটি sub32-বিট প্রশস্ত নির্দেশিকা।
আপনাকে সংযুক্ত করার জন্য প্রয়োজনীয় রিটার্ন নির্দেশিকাটি হ'ল bx lr।
AArch64 মেশিন কোড টুকরা, 4 বাইট
d1001000 sub x0, x0, #0x4
-৪-বিট পূর্ণসংখ্যার জন্য কাজ করে। ইনপুট / আউটপুট ইন x0স্ট্যান্ডার্ড কলিং কনভেনশন অনুযায়ী। int64_t foo(uint64_t);
এআরচ ৪ এর একটি থাম্ব মোড নেই (এখনও), সুতরাং ১ টি নির্দেশনা আমরা সবচেয়ে ভাল।
Lযাওয়ার পরেMসময়গুলি ফিরে আসবে কিনা এর ইনপুটটিNসমান কিনাL*M?