การเลือกอาร์กิวเมนต์สี่ตัวลงทะเบียนบน x64 - โดยทั่วไปของ UN * X / Win64
สิ่งหนึ่งที่ควรทราบเกี่ยวกับ x86 คือชื่อรีจิสเตอร์สำหรับการเข้ารหัส "หมายเลข reg" นั้นไม่ชัดเจน ในแง่ของการเข้ารหัสคำสั่ง ( ไบต์MOD R / Mโปรดดูที่http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm ) ให้ลงทะเบียนหมายเลข 0 ... 7 คือ - ตามลำดับ - ?AX
, ?CX
, ?DX
, ?BX
, ?SP
, ?BP
, ,?SI
?DI
ดังนั้นการเลือก A / C / D (regs 0..2) สำหรับค่าส่งคืนและอาร์กิวเมนต์สองตัวแรก (ซึ่งเป็น__fastcall
อนุสัญญา32 บิต "คลาสสิก" ) จึงเป็นตัวเลือกเชิงตรรกะ เท่าที่เกี่ยวข้องกับ 64 บิตจะมีการเรียงลำดับ "ที่สูงกว่า" และทั้ง Microsoft และ UN * X / Linux ใช้สำหรับR8
/ R9
เป็นรายการแรก
การรักษาที่ในใจเลือกที่ไมโครซอฟท์RAX
(ค่าตอบแทน) และRCX
, RDX
, R8
, R9
(หาเรื่อง [0..3]) เป็นตัวเลือกที่เข้าใจถ้าคุณเลือกที่สี่ลงทะเบียนสำหรับข้อโต้แย้ง
ผมไม่ทราบว่าทำไม AMD64 สหประชาชาติ * X ABI เลือกก่อนRDX
RCX
การเลือกอาร์กิวเมนต์หกตัวลงทะเบียนบน x64 - UN * X เฉพาะ
UN * X บนสถาปัตยกรรม RISC ได้ทำการโต้แย้งในการลงทะเบียนโดยเฉพาะสำหรับข้อโต้แย้งหกข้อแรก(นั่นคือ PPC, SPARC, MIPS เป็นอย่างน้อย) ซึ่งอาจเป็นหนึ่งในสาเหตุสำคัญที่นักออกแบบ AMD64 (UN * X) ABI เลือกใช้รีจิสเตอร์หกตัวบนสถาปัตยกรรมนั้นด้วย
ดังนั้นหากคุณต้องการหกลงทะเบียนที่จะผ่านการขัดแย้งในและก็มีเหตุผลที่จะเลือกRCX
, RDX
, R8
และR9
สี่ของพวกเขาซึ่งอีกสองคนที่คุณควรเลือก?
Regs "สูงกว่า" ต้องการไบต์คำนำหน้าคำสั่งเพิ่มเติมเพื่อเลือกดังนั้นจึงมีขนาดคำสั่งที่ใหญ่กว่าดังนั้นคุณจึงไม่ต้องการเลือกตัวเลือกใด ๆ หากคุณมีตัวเลือก ของการลงทะเบียนแบบคลาสสิกเนื่องจากความหมายโดยนัยของRBP
และRSP
สิ่งเหล่านี้ไม่สามารถใช้ได้และโดยRBX
ปกติแล้วจะมีการใช้งานพิเศษบน UN * X (ตารางออฟเซ็ตทั่วโลก) ซึ่งดูเหมือนว่านักออกแบบ AMD64 ABI ไม่ต้องการที่จะเข้ากันไม่ได้โดยไม่จำเป็น
Ergo ทางเลือกเดียวคือRSI
/ RDI
.
ดังนั้นหากคุณต้องรับRSI
/ RDI
เป็นอาร์กิวเมนต์รีจิสเตอร์ข้อโต้แย้งใดที่ควรเป็น
ทำให้พวกเขาarg[0]
และarg[1]
มีข้อดีบางอย่าง ดูความคิดเห็นของ cHao
?SI
และ?DI
เป็นสตริงคำสั่งต้นทาง / ปลายทางตัวถูกดำเนินการและตามที่ cHao กล่าวถึงการใช้เป็นอาร์กิวเมนต์รีจิสเตอร์หมายความว่าด้วยอนุสัญญาการเรียก AMD64 UN * X strcpy()
ฟังก์ชันที่ง่ายที่สุดที่เป็นไปได้ตัวอย่างเช่นประกอบด้วยคำสั่ง CPU สองคำสั่งเท่านั้นrepz movsb; ret
เนื่องจากต้นทาง / เป้าหมาย ที่อยู่ถูกใส่ลงในรีจิสเตอร์ที่ถูกต้องโดยผู้โทร โดยเฉพาะอย่างยิ่งในโค้ด "กาว" ระดับต่ำและคอมไพเลอร์ที่สร้างขึ้น (ลองนึกดูเช่นตัวจัดสรรฮีป C ++ บางตัวเป็นศูนย์เติมอ็อบเจ็กต์บนโครงสร้างหรือหน้าฮีปที่เติมศูนย์เคอร์เนลบนsbrk()
หรือ copy-on-write pagefaults) จำนวนมากของ block copy / fill ดังนั้นจึงมีประโยชน์สำหรับโค้ดที่ใช้บ่อยเพื่อบันทึกคำสั่ง CPU สองหรือสามคำสั่งที่จะโหลดอาร์กิวเมนต์ที่อยู่ต้นทาง / ปลายทางดังกล่าวลงใน การลงทะเบียน "ถูกต้อง"
ดังนั้นในทางสหประชาชาติ * X และ Win64 จะแตกต่างกันเพียง แต่ในการที่สหประชาชาติ * X "prepends" สองอาร์กิวเมนต์เพิ่มเติมในการได้รับการแต่งตั้งอย่างเด็ดเดี่ยวRSI
/ RDI
ลงทะเบียนเพื่อเป็นทางเลือกธรรมชาติในสี่ข้อโต้แย้งในRCX
, RDX
, และR8
R9
นอกเหนือจากนั้น ...
มีความแตกต่างระหว่าง UN * X และ Windows x64 ABI มากกว่าแค่การแมปอาร์กิวเมนต์กับรีจิสเตอร์เฉพาะ สำหรับภาพรวมของ Win64 ตรวจสอบ:
http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
Win64 และ AMD64 UN * X ยังแตกต่างกันอย่างมากในวิธีการใช้ stackspace บน Win64 ตัวอย่างเช่นผู้เรียกต้องจัดสรร stackspace สำหรับอาร์กิวเมนต์ของฟังก์ชันแม้ว่า args 0 ... 3 จะถูกส่งผ่านในรีจิสเตอร์ ในทางกลับกัน UN * X ฟังก์ชัน leaf (เช่นฟังก์ชันที่ไม่เรียกใช้ฟังก์ชันอื่น ๆ ) ไม่จำเป็นต้องจัดสรรสแต็กสเปซเลยหากต้องการไม่เกิน 128 ไบต์ (ใช่คุณเป็นเจ้าของและสามารถใช้ได้ สแต็คจำนวนหนึ่งโดยไม่ต้องจัดสรร ... เว้นแต่คุณจะเป็นรหัสเคอร์เนลซึ่งเป็นแหล่งที่มาของข้อบกพร่องที่ดี) ทั้งหมดนี้เป็นทางเลือกในการเพิ่มประสิทธิภาพโดยเฉพาะเหตุผลส่วนใหญ่สำหรับสิ่งเหล่านี้มีการอธิบายไว้ในการอ้างอิง ABI แบบเต็มที่อ้างอิงจากวิกิพีเดียของผู้โพสต์ต้นฉบับ