x86-64 মেশিন কোড, 44 বাইট
(একই মেশিন কোডটি 32-বিট মোডেও কাজ করে))
@Daniel Schepler এর উত্তর এই জন্য একটি শুরুর স্থান ছিল, কিন্তু এই অন্তত একটি নতুন আলগোরিদিমিক ধারণা (ঠিক ভাল একই ধারণা golfing নয়) আছে: জন্য ASCII কোড 'B'( 1000010) এবং 'X'( 1011000) সঙ্গে মাস্কিং পর 16 এবং 2 দিতে0b0010010 ।
সুতরাং দশমিক (অ-শূন্য নেতৃস্থানীয় অঙ্ক) এবং অষ্টাল বাদে (অক্ষরের পরে এর '0'চেয়ে কম হয় 'B') বাদ দিয়ে আমরা কেবল বেস = সেট করতে পারি c & 0b0010010এবং অঙ্কের লুপে ঝাঁপিয়ে দিতে পারি।
X86-64 সিস্টেম ভি দিয়ে কলযোগ্য হিসাবে ফলাফলের unsigned __int128 parse_cxx14_int(int dummy, const char*rsi); উচ্চ অর্ধেক থেকে EDX রিটার্ন মান বের করুন ।unsigned __int128tmp>>64
.globl parse_cxx14_int
## Input: pointer to 0-terminated string in RSI
## output: integer in EDX
## clobbers: RAX, RCX (base), RSI (points to terminator on return)
parse_cxx14_int:
xor %eax,%eax # initialize high bits of digit reader
cdq # also initialize result accumulator edx to 0
lea 10(%rax), %ecx # base 10 default
lodsb # fetch first character
cmp $'0', %al
jne .Lentry2
# leading zero. Legal 2nd characters are b/B (base 2), x/X (base 16)
# Or NUL terminator = 0 in base 10
# or any digit or ' separator (octal). These have ASCII codes below the alphabetic ranges
lodsb
mov $8, %cl # after '0' have either digit, apostrophe, or terminator,
cmp $'B', %al # or 'b'/'B' or 'x'/'X' (set a new base)
jb .Lentry2 # enter the parse loop with base=8 and an already-loaded character
# else hex or binary. The bit patterns for those letters are very convenient
and $0b0010010, %al # b/B -> 2, x/X -> 16
xchg %eax, %ecx
jmp .Lentry
.Lprocessdigit:
sub $'0' & (~32), %al
jb .Lentry # chars below '0' are treated as a separator, including '
cmp $10, %al
jb .Lnum
add $('0'&~32) - 'A' + 10, %al # digit value = c-'A' + 10. we have al = c - '0'&~32.
# c = al + '0'&~32. val = m+'0'&~32 - 'A' + 10
.Lnum:
imul %ecx, %edx
add %eax, %edx # accum = accum * base + newdigit
.Lentry:
lodsb # fetch next character
.Lentry2:
and $~32, %al # uppercase letters (and as side effect,
# digits are translated to N+16)
jnz .Lprocessdigit # space also counts as a terminator
.Lend:
ret
ড্যানিয়েলের সংস্করণ পরিবর্তিত ব্লকগুলি (বেশিরভাগ) অন্যান্য নির্দেশাবলীর তুলনায় কম ইন্ডেন্ট করা হয়। এছাড়াও মূল লুপটির নীচের অংশে শর্তযুক্ত শাখা রয়েছে। এটি একটি নিরপেক্ষ পরিবর্তন হিসাবে প্রমাণিত হয়েছিল কারণ কোনও পথই এর শীর্ষে পড়তে পারে না এবং dec ecx / loop .Lentryলুপে প্রবেশের ধারণাটি অষ্টালকে অন্যভাবে পরিচালনা করার পরে জয়ের মতো নয়। কাঠামোর সময় লুপের সাথে ইডিয়োমেটিক আকারে লুপের সাথে এর কম নির্দেশ রয়েছে তবে এটি আমি রেখেছি।
ড্যানিয়েলের সি ++ পরীক্ষার জোতা এই কোডটি দিয়ে -৪-বিট মোডে অপরিবর্তিত কাজ করে, যা তার 32-বিটের উত্তর হিসাবে একই কলিং কনভেনশন ব্যবহার করে।
g++ -Og parse-cxx14.cpp parse-cxx14.s &&
./a.out < tests | diff -u -w - tests.good
প্রকৃত উত্তর হ'ল মেশিন কোড বাইট সহ বিশৃঙ্খলা
0000000000000000 <parse_cxx14_int>:
0: 31 c0 xor %eax,%eax
2: 99 cltd
3: 8d 48 0a lea 0xa(%rax),%ecx
6: ac lods %ds:(%rsi),%al
7: 3c 30 cmp $0x30,%al
9: 75 1c jne 27 <parse_cxx14_int+0x27>
b: ac lods %ds:(%rsi),%al
c: b1 08 mov $0x8,%cl
e: 3c 42 cmp $0x42,%al
10: 72 15 jb 27 <parse_cxx14_int+0x27>
12: 24 12 and $0x12,%al
14: 91 xchg %eax,%ecx
15: eb 0f jmp 26 <parse_cxx14_int+0x26>
17: 2c 10 sub $0x10,%al
19: 72 0b jb 26 <parse_cxx14_int+0x26>
1b: 3c 0a cmp $0xa,%al
1d: 72 02 jb 21 <parse_cxx14_int+0x21>
1f: 04 d9 add $0xd9,%al
21: 0f af d1 imul %ecx,%edx
24: 01 c2 add %eax,%edx
26: ac lods %ds:(%rsi),%al
27: 24 df and $0xdf,%al
29: 75 ec jne 17 <parse_cxx14_int+0x17>
2b: c3 retq
ড্যানিয়েল এর সংস্করণ থেকে অন্য পরিবর্তনগুলি সংরক্ষণ অন্তর্ভুক্ত sub $16, %alঅঙ্ক-লুপ ভিতর থেকে, ব্যবহার করে আরও subপরিবর্তে testসনাক্ত বিভাজক, এবং বর্ণমালা বনাম ডিজিটের অংশ হিসেবে।
ড্যানিয়েলের বিপরীতে নীচের প্রতিটি চরিত্রকে '0'পৃথককারী হিসাবে ধরা হয়, কেবল নয় '\''। (ব্যতীত ' ': and $~32, %al/ jnzআমাদের উভয় লুপগুলিতে স্থানকে টার্মিনেটর হিসাবে বিবেচনা করে, যা কোনও লাইনের শুরুতে পূর্ণসংখ্যার সাথে পরীক্ষার জন্য সম্ভবত সুবিধাজনক।)
%alলুপের অভ্যন্তরে পরিবর্তিত প্রতিটি ক্রিয়াকলাপ ফল দ্বারা নির্ধারিত পতাকা গ্রহণ করে এবং প্রতিটি শাখা পৃথক স্থানে যায় (বা এর মধ্য দিয়ে পড়ে)।