พอย่างเข้าปีใหม่ทีไร เราก็จะเห็นกันว่าเหล่าบริษัทน้ำเมาก็จะปฏิบัติตามธรรมเนียมเข็นปฏิทินโป๊กันทุกปี แบบนี้สิ้นปีนี้ผมก็ขอนำเสนอ อะไรที่มันโป๊ๆ เปลือยๆ มั่งดีกว่า (อย่าคิดลึก ยังไงซะมันก็อยู่ในหมวด C++ นะ) โดยไอ้ที่เปลือยๆ ที่ว่าเนี่ย ผมหมายถึงการเขียน nake function หรือถ้าแปลแบบบ้านๆ ก็คือ ฟังก์ชันเปลือยนะแหละ ว่าแต่ nake function มันคืออะไรละ
nake function เป็น function รูปแบบนึง แต่จะต่างจาก function ปกติ ตรงที่มีการใช้คำนำหน้า function ในการประกาศที่ไม่ปกติ โดยจะมี _declspec(naked) นำหน้าชื่อฟังก์ชันเอาไว้ เมื่อประกาศให้ function ใดๆ เป็น nake function แล้ว function นั้นจะตัด header ของ function code ที่ทำหน้าที่จัดการ stack ก่อนที่จะเรียก function นั้นๆ ออกไป และยังจะต้องจัดการข้อมูลทุกอย่างภายใน function เองทั้งหมด (เพราะ code ที่ทำหน้าที่จัดการ stack เอาออกไปแล้ว) จึงแทบจะเรียกได้ว่า nake function เป็น function ที่จะต้องจัดการ stack เองทั้งหมด เพราะเหตุนี้ nake function จึงมักจะอยู่ในรูปของ inline assembly ใน function (จะได้จัดการ stack ได้ง่าย) ยกตัวอย่างเช่น
#include <stdio.h>
int NormalAdd(int param_1,int param_2)
{
_asm
{
mov eax,param_1
add eax,param_2
}
}
_declspec(naked) int NakeAdd(int param_1,int param_2)
{
_asm
{
mov eax,[esp+4]
add eax,[esp+8]
ret
}
}
int main(int argc, char **argv)
{
printf("%d\n",NormalAdd(1,2));
printf("%d\n",NakeAdd(3,4));
return 0;
}
ถึงตอนนี้หลายคนอาจจะบอกว่าอ้าวก็แค่ Inline Function ธรรมดานิ ไม่เห็นจะมีอะไร แต่มันไม่ธรรมดาตรงนี้ครับ ถ้าเรา Debug Program แล้วเปิดดู Disassembly ดู จะพบว่า มี Code บางส่วนหายไปเมื่อมีการประกาศเป็น Nake Function ลองเปรียบเทียบระหว่าง
// NormalAdd เมื่อมองใน Disassembly View
00411F00 push ebp
00411F01 mov ebp,esp
00411F03 sub esp,0C0h
00411F09 push ebx
00411F0A push esi
00411F0B push edi
00411F0C lea edi,[ebp-0C0h]
00411F12 mov ecx,30h
00411F17 mov eax,0CCCCCCCCh
00411F1C rep stos dword ptr es:[edi]
_asm
{
mov eax,param_1
00411F1E mov eax,dword ptr [param_1]
add eax,param_2
00411F21 add eax,dword ptr [param_2]
}
}
00411F24 pop edi
00411F25 pop esi
00411F26 pop ebx
00411F27 add esp,0C0h
00411F2D cmp ebp,esp
00411F2F call @ILT+310(__RTC_CheckEsp) (41113Bh)
00411F34 mov esp,ebp
00411F36 pop ebp
00411F37 ret
// NakeAdd เมื่อมองใน Disassembly View
_declspec(naked) int NakeAdd(int param_1,int param_2)
{
_asm
{
mov eax,[esp+4]
004113D0 mov eax,dword ptr [esp+4]
add eax,[esp+8]
004113D4 add eax,dword ptr [esp+8]
ret
004113D8 ret
จะเห็นได้ว่า Header Function ที่เอาไว้จัดการเกี่ยวกับ Stack ภายใน Function หายเรียบไปเลย
