ฉันพบหนังสือที่น่าทึ่งเล่มนี้ทางออนไลน์ xchg rax, rax โดย xorpd เป็นการรวบรวมปริศนาประกอบ หนังสือเล่มนี้มีตัวอย่างประกอบขนาดสั้น 0x40 โดยไม่มีข้อความ

ฉันเพิ่งเริ่มอ่านมันและมันน่าทึ่งมาก ฉันจะอัปเดตโพสต์บล็อกนี้พร้อมคำอธิบายตัวอย่างที่ฉันสำรวจ

xchg rax,rax — 0x00 คำอธิบาย

คำแนะนำ: เป็นตัวอย่างข้อมูลที่ 0

ตัวอย่างเพียงแสดงวิธีต่างๆ ในการตั้งค่ารีจิสเตอร์เป็น 0 โดยตั้งค่า eax, ebx, ecx, edx, esi, edi และ ebp เป็น 0 ในลำดับเดียวกัน

xchg rax,rax — คำอธิบาย 0x01

ฟีโบนัชชี

xchg rax,rax — คำอธิบาย 0x02

ตั้งค่า rax เป็น 0 หากค่าเริ่มต้นเป็น 0 มิฉะนั้นจะตั้งค่าเป็น 1 เสมอ

xchg rax,rax — คำอธิบาย 0x03

จริงๆ แล้วโค้ดนั้นเป็นวิธีที่ชาญฉลาดในการทำ rax = min(rax, rdx)

sub rdx, rax ; rdx = rdx - rax; CF set if rdx < rax
sbb rcx, rcx ; rcx = all 1 bits if CF was set, 0 otherwise
and rcx, rdx ; rcx = rdx - rax if CF was set, 0 otherwise
add rax, rcx ; rax = rax + (rdx - rax) = rdx if CF was set, unchanged otherwise

เวอร์ชันการแตกแขนงที่อ่านได้มากขึ้นคือ:

cmp rdx, rax
jnc done ; if rdx - rax produced no carry, rax is smaller or equal
mov rax, rdx ; otherwise rdx is the smaller one
done:

ยังคงใช้ CF สำหรับการตรวจสอบโอเวอร์โฟลว์เท่านั้น

จากคำตอบของ Jester ที่นี่

xchg rax,rax — คำอธิบาย 0x04

0x20 ในไบนารี่คือ 00100000

ดังนั้นการ xor ตัวเลขด้วย 0x20 จะพลิกบิตที่สำคัญที่สุดอันดับที่ 5 ทีนี้ หากเราเห็นการแสดงอักขระ ASCII ในรูปแบบไบนารี่ ก็มีสิ่งที่น่าสนใจที่ควรทราบ

A  = 0100 0001
a  = 0110 0001
B  = 0100 0010
b  = 0110 0010

ที่นั่นเราเห็น การพลิกบิตที่ห้าจะเป็นการพลิกตัวพิมพ์ (ล่าง/บน) ของตัวอักษร