วัตถุประสงค์ที่แท้จริงและการใช้ EDI & ESI register ในแอสเซมเบลอร์คืออะไร?
ฉันรู้ว่ามันใช้สำหรับการดำเนินการสตริงสำหรับสิ่งหนึ่ง
ใครช่วยยกตัวอย่างได้ไหม
วัตถุประสงค์ที่แท้จริงและการใช้ EDI & ESI register ในแอสเซมเบลอร์คืออะไร?
ฉันรู้ว่ามันใช้สำหรับการดำเนินการสตริงสำหรับสิ่งหนึ่ง
ใครช่วยยกตัวอย่างได้ไหม
คำตอบ:
มีการดำเนินการบางอย่างที่คุณสามารถมีเพียงทำอย่างไรกับ DI / SI (หรือลูกน้องขยายของพวกเขาถ้าคุณไม่ได้เรียนรู้ ASM ในปี 1985) ในจำนวนนี้ ได้แก่
REP STOSB
REP MOVSB
REP SCASB
ซึ่งตามลำดับคือการดำเนินการสำหรับการจัดเก็บการโหลดและการสแกนซ้ำ (= มวล) สิ่งที่คุณทำคือตั้งค่า SI และ / หรือ DI ให้ชี้ไปที่ตัวถูกดำเนินการหนึ่งตัวหรือทั้งสองตัวบางทีอาจจะนับเป็น CX แล้วปล่อยให้ 'er ฉีก นี่คือการดำเนินการที่ทำงานกับจำนวนไบต์ในแต่ละครั้งและเป็นการทำให้ CPU ทำงานโดยอัตโนมัติ เนื่องจากคุณไม่ได้เข้ารหัสลูปอย่างชัดเจนพวกเขาจึงทำสิ่งต่างๆได้อย่างมีประสิทธิภาพ (โดยปกติ) มากกว่าการวนซ้ำด้วยมือ
ในกรณีที่คุณสงสัย: ขึ้นอยู่กับว่าคุณตั้งค่าการทำงานอย่างไรการจัดเก็บซ้ำอาจเป็นเรื่องง่ายๆเช่นการเจาะค่า 0 ลงในบล็อกหน่วยความจำขนาดใหญ่ที่ต่อเนื่องกัน ฉันคิดว่าใช้ MOVSB เพื่อคัดลอกข้อมูลจากบัฟเฟอร์หนึ่ง (ดีกลุ่มไบต์ใด ๆ ) ไปยังอีก และ SCASB ใช้เพื่อค้นหาไบต์ที่ตรงกับเกณฑ์การค้นหาบางอย่าง (ฉันไม่แน่ใจว่ามันค้นหาด้วยความเท่าเทียมกันเท่านั้นหรืออะไร - คุณสามารถค้นหาได้ :))
นั่นคือสิ่งที่ regs เหล่านั้นส่วนใหญ่มีไว้เพื่อ
SI
= ดัชนีแหล่งที่มา
DI
= ดัชนีปลายทาง
ตามที่คนอื่นระบุพวกเขามีการใช้งานพิเศษกับคำแนะนำสตริง สำหรับการเขียนโปรแกรมโหมดจริงที่ES
ลงทะเบียนส่วนจะต้องใช้ด้วยDI
และDS
ด้วยSI
ในขณะที่
movsb es:di, ds:si
SI และ DI สามารถใช้เป็นรีจิสเตอร์ดัชนีวัตถุประสงค์ทั่วไป ตัวอย่างเช่นC
ซอร์สโค้ด
srcp [srcidx++] = argv [j];
รวบรวมเป็น
8B550C mov edx,[ebp+0C]
8B0C9A mov ecx,[edx+4*ebx]
894CBDAC mov [ebp+4*edi-54],ecx
47 inc edi
ที่ebp+12
มีargv
, ebx
เป็นj
และมีedi
srcidx
สังเกตคำสั่งที่สามใช้edi
mulitplied ด้วย 4 และเพิ่มebp
offset ด้วย 0x54 (ตำแหน่งของsrcp
); วงเล็บรอบแอดเดรสระบุทิศทาง
AX
= ตัวสะสม = ตัวสะสม
DX
คำคู่
CX
= ตัวนับ
BX
= ลงทะเบียนฐาน
ดูเหมือนว่าการลงทะเบียนสำหรับวัตถุประสงค์ทั่วไป แต่มีคำสั่งหลายอย่างที่ (โดยไม่คาดคิด?) ใช้อย่างใดอย่างหนึ่ง แต่อันไหน - โดยปริยาย
Opcodes เช่น MOVSB และ MOVSW ที่คัดลอกข้อมูลอย่างมีประสิทธิภาพจากหน่วยความจำที่ ESI ชี้ไปยังหน่วยความจำที่ EDI ชี้ไป ดังนั้น
mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!
นอกเหนือจากการดำเนินการสตริง (MOVS / INS / STOS / CMPS / SCASB / W / D / Q เป็นต้น) ที่กล่าวถึงในคำตอบอื่น ๆ ฉันต้องการเพิ่มว่ายังมีคำแนะนำการประกอบ x86 ที่ "ทันสมัย" เพิ่มเติมซึ่งใช้โดยปริยายที่ EDI / RDI น้อยที่สุด:
คำสั่ง SSE2 MASKMOVDQU
(และ AVX ที่กำลังจะมาถึงVMASKMOVDQU
) เลือกเขียนไบต์จากรีจิสเตอร์ XMM ไปยังหน่วยความจำที่ EDI / RDI ชี้ไป
นอกเหนือจากการลงทะเบียนที่ใช้สำหรับการดำเนินการจำนวนมากแล้วยังมีประโยชน์สำหรับคุณสมบัติของการถูกเก็บรักษาไว้ผ่านการเรียกใช้ฟังก์ชัน (การโทรที่สงวนไว้) ในรูปแบบการโทรแบบ 32 บิต ESI, EDI, EBX, EBP, ESP จะถูกสงวนไว้สำหรับการโทรในขณะที่ EAX, ECX และ EDX จะไม่ถูกสงวนไว้สำหรับการโทร การลงทะเบียนที่สงวนไว้นั้นได้รับการเคารพโดยฟังก์ชันไลบรารี C และค่าจะยังคงอยู่ผ่านการเรียกฟังก์ชันไลบรารี C
Jeff Duntemann ในหนังสือภาษาแอสเซมบลีของเขามีตัวอย่างรหัสแอสเซมบลีสำหรับพิมพ์อาร์กิวเมนต์บรรทัดคำสั่ง รหัสใช้ esi และ edi เพื่อจัดเก็บตัวนับเนื่องจากจะไม่เปลี่ยนแปลงโดยฟังก์ชันไลบรารี C printf สำหรับรีจิสเตอร์อื่น ๆ เช่น eax, ecx, edx ไม่มีการรับประกันว่าจะไม่ใช้ฟังก์ชันไลบรารี C
https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025
ดูหัวข้อ 12.8 วิธีที่ C เห็นอาร์กิวเมนต์บรรทัดคำสั่ง
โปรดทราบว่ารูปแบบการโทร 64 บิตนั้นแตกต่างจากรูปแบบการโทรแบบ 32 บิตและฉันไม่แน่ใจว่าการลงทะเบียนเหล่านี้จะสงวนไว้สำหรับการโทรหรือไม่