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 পার্স করুন এবং তাদের স্ট্যাকের উপর "চাপুন", যেখানে আমরা সেগুলি ডিফল্ট হিসাবে পপ করি বা শেষটি এখনও সিএলে ব্যবহার করি। স্ট্রিংয়ের শেষটি পড়া মোটেও এড়ানো যায় না।
এছাড়াও, dec
32-বিট মোডে কেবল 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