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
প্রত্যয়) সেট করে । মজার ব্যাপার; এর নন -ফ্ল্যাগ-সেটিং সংস্করণটি sub
32-বিট প্রশস্ত নির্দেশিকা।
আপনাকে সংযুক্ত করার জন্য প্রয়োজনীয় রিটার্ন নির্দেশিকাটি হ'ল bx lr
।
AArch64 মেশিন কোড টুকরা, 4 বাইট
d1001000 sub x0, x0, #0x4
-৪-বিট পূর্ণসংখ্যার জন্য কাজ করে। ইনপুট / আউটপুট ইন x0
স্ট্যান্ডার্ড কলিং কনভেনশন অনুযায়ী। int64_t foo(uint64_t);
এআরচ ৪ এর একটি থাম্ব মোড নেই (এখনও), সুতরাং ১ টি নির্দেশনা আমরা সবচেয়ে ভাল।
L
যাওয়ার পরেM
সময়গুলি ফিরে আসবে কিনা এর ইনপুটটিN
সমান কিনাL*M
?