x86-64 মেশিন কোড ফাংশন, 53 48 বাইট
পরিবর্তণের:
- বিশেষ ক্ষেত্রে
jzপরিচালনা করতে 64৪-বিট শিফট ব্যবহার না করে শিফটের ওপরে -2 >>(32-0)।
- -3 এর পরিবর্তে জেডএফ-এ ফিরে আসার জন্য 3 টি বাইট সংরক্ষণ করুন
setnz al।
( এটির উপর ভিত্তি করে ড্যানিয়েল শেপলারের ৩২-বিট মেশিন কোড উত্তরও দেখুন , যা আমাদের অন্যান্য কিছু ধারণাগুলি ব্যবহার করতে বিকশিত হয়েছিল I'm আমি এই উত্তরটির নীচে আমার সর্বশেষ সংস্করণটিও অন্তর্ভুক্ত করছি))
সাবনেটে নয় হোস্টের জন্য জেডএফ = 0 , সাবনেটে জেডএফ = 1 প্রদান করে, যাতে আপনি ফলাফলের সাথে শাখা করতে পারেনje host_matches_subnet
X86-64 সিস্টেম ভি কলিং কনভেনশনের সাথে কল করা
bool not_in_subnet(int dummy_rdi, const char *input_rsi);যেন আপনি যুক্ত করে থাকেন setnz al।
ইনপুট স্ট্রিংটিতে হোস্ট এবং নেটওয়ার্ক উভয়ই থাকে, ঠিক 1 অ-অঙ্কের অক্ষর দ্বারা পৃথক। সিআইডিআর প্রস্থের শেষে থাকা মেমরিটিতে কোনও পৃষ্ঠা শেষ হওয়ার আগে কমপক্ষে 3 অ-অঙ্কের বাইট থাকা আবশ্যক। (বেশিরভাগ ক্ষেত্রে যেমন সমস্যা যেমন সেমিডলাইন আরগের মতো হওয়া উচিত নয়) ড্যানিয়েলের 32-বিট সংস্করণটির এই সীমাবদ্ধতা নেই।
আমরা একই আইটভিড-কোয়াড পার্স লুপটি 3 বার চালনা করি, দুটি আইপিভি 4 অ্যাড্রেস পেয়ে এবং /maskএকটি শব্দের উচ্চ বাইটে একটি পূর্ণসংখ্যা হিসাবে পেয়ে যাচ্ছি। (এই কারণেই এখানে পঠনযোগ্য স্মৃতি থাকতে হবে /maskতবে এএসসিআইআই সংখ্যা রয়েছে কিনা তা বিবেচ্য নয়))
আমরা(host ^ subnet) >> (32-mask) সাবনেট এবং হোস্টের মধ্যে কেবলমাত্র পার্থক্য রেখে হোস্ট বিটগুলি পরিবর্তন করতে পারি (যাহা মেলে না এমন)। /0আমাদের 32 টি শিফট করতে হবে এমন বিশেষ কেসটি সমাধান করার জন্য, আমরা কাউন্ট = 0 এ শিফ্টের ওপরে উঠি। ( neg clজেডএফ সেট করে, যা আমরা শাখা করতে পারি এবং আমরা যদি শিফট না করি তবে রিটার্ন মান হিসাবে ছেড়ে যেতে পারি)) নোট করুন 32-mask mod 32 = -mask, এবং x86 স্কেলার শিফটগুলি তাদের গণনাটি মাস্ক & 31বা দ্বারা মাস্ক করে & 63।
line addr machine NASM source. (from nasm -felf64 -l/dev/stdout)
num code bytes
1 %use smartalign
2
3 ;10.4.1.33 10.4.0.0/23 true
4 ;10.4.1.33 10.4.0.0/24 false
5
6 ;; /codegolf/185005/im-in-your-subnets-golfing-your-code
7 %ifidn __OUTPUT_FORMAT__, elf64
8 in_subnet:
9
10 00000000 6A03 push 3
11 00000002 5F pop rdi ; edi = 3 dotted-quads to parse, sort of.
12 .parseloop:
13
14 ;xor ebx,ebx ; doesn't need to be zeroed first; we end up shifting out the original contents
15 ;lea ecx, [rbx+4]
16 00000003 6A04 push 4
17 00000005 59 pop rcx ; rcx = 4 integers in a dotted-quad
18 .quadloop:
19
20 00000006 31D2 xor edx,edx ; standard edx=atoi(rdi) loop terminated by a non-digit char
21 00000008 EB05 jmp .digit_entry
22 .digitloop:
23 0000000A 6BD20A imul edx, 10
24 0000000D 00C2 add dl, al
25 .digit_entry:
26 0000000F AC lodsb
27 00000010 2C30 sub al, '0'
28 00000012 3C09 cmp al, 9
29 00000014 76F4 jbe .digitloop
30 ; al=non-digit character - '0'
31 ; RDI pointing to the next character.
32 ; EDX = integer
33
34 00000016 C1E308 shl ebx, 8
35 00000019 88D3 mov bl, dl ; build a quad 1 byte at a time, ending with the lowest byte
36 0000001B E2E9 loop .quadloop
37
38 0000001D 53 push rbx ; push result to be collected after parsing 3 times
39 0000001E FFCF dec edi
40 00000020 75E1 jnz .parseloop
41
42 00000022 59 pop rcx ; /mask (at the top of a dword)
43 00000023 5A pop rdx ; subnet
44 00000024 58 pop rax ; host
45 00000025 0FC9 bswap ecx ; cl=network bits (reusing the quad parse loop left it in the high byte)
49 00000027 F6D9 neg cl
50 00000029 7404 jz .all_net ; skip the count=32 special case
51
52 0000002B 31D0 xor eax, edx ; host ^ subnet
53 0000002D D3E8 shr eax, cl ; shift out the host bits, keeping only the diff of subnet bits
54
55 .all_net:
56 ; setnz al ; return ZF=1 match, ZF=0 not in subnet
57 0000002F C3 ret
58 00000030 30 .size: db $ - in_subnet
0x30 = 48 bytes
(সর্বশেষ সংস্করণ সহ আপডেট করা হয়নি)
অনলাইনে চেষ্টা করুন!
_startএটির সাথে এটি কল করে argv[1]এবং একটি প্রস্থান স্থিতি ফেরত দেয় including
## on my desktop
$ ./ipv4-subnet "10.4.1.33 10.4.0.0/24" && echo "$? : in subnet" || echo "$? : not in subnet"
not in subnet
$ ./ipv4-subnet "10.4.1.33 10.4.0.0/23" && echo "$? : in subnet" || echo "$? : not in subnet"
in subnet
যদি আপনি কোনও স্থানের পরিবর্তে একটি নতুন লাইন যুক্ত কমান্ড লাইন আরগটি পাস করেন তবে এটি দুর্দান্ত কাজ করে। তবে এটি পরিবর্তে হতে হবে , পাশাপাশি নয়।
x86 32-বিট মেশিন কোড ফাংশন, 38 বাইট
9 টি পূর্ণসংখ্যা করুন -> uint8_t পার্স করুন এবং তাদের স্ট্যাকের উপর "চাপুন", যেখানে আমরা সেগুলি ডিফল্ট হিসাবে পপ করি বা শেষটি এখনও সিএলে ব্যবহার করি। স্ট্রিংয়ের শেষটি পড়া মোটেও এড়ানো যায় না।
এছাড়াও, dec32-বিট মোডে কেবল 1 বাইট।
72 in_subnet:
73 00000000 89E7 mov edi, esp
74 00000002 51 push ecx
75 00000003 51 push ecx ; sub esp,8
76 .byteloop:
77
78 00000004 31C9 xor ecx,ecx ; standard ecx=atoi(rdi) loop terminated by a non-digit char
79 ; runs 9 times: 8 in two dotted-quads, 1 mask length
80 00000006 EB05 jmp .digit_entry
81 .digitloop:
82 00000008 6BC90A imul ecx, 10
83 0000000B 00C1 add cl, al
84 .digit_entry:
85 0000000D AC lodsb
86 0000000E 2C30 sub al, '0'
87 00000010 3C09 cmp al, 9
88 00000012 76F4 jbe .digitloop
89 ; RDI pointing to the next character.
90 ; EDX = integer
91
92 00000014 4F dec edi
93 00000015 880F mov [edi], cl ; /mask store goes below ESP but we don't reload it
94 00000017 39E7 cmp edi, esp
95 00000019 73E9 jae .byteloop
96
97 ;; CL = /mask still there from the last conversion
98 ;; ESP pointing at subnet and host on the stack, EDI = ESP-1
99
100 0000001B 5A pop edx ; subnet
101 0000001C 58 pop eax ; host
102
103 0000001D 31D0 xor eax, edx ; host ^ subnet
104 0000001F F6D9 neg cl ; -mask = (32-mask) mod 32; x86 shifts mask their count
105 00000021 7402 jz .end ; 32-n = 32 special case
106 00000023 D3E8 shr eax, cl
107 .end:
108 ; setz al ; just return in ZF
109 00000025 C3 ret
110 00000026 26 .size: db $ - in_subnet
0x26 = 38 bytes
টেস্ট কলার
113 global _start
114 _start:
115 00000027 8B742408 mov esi, [esp+8] ; argv[1]
116 0000002B E8D0FFFFFF call in_subnet
117 00000030 0F95C3 setnz bl
118 00000033 B801000000 mov eax, 1 ; _exit syscall
119 00000038 CD80 int 0x80