ปฏิทินโป๊ code เปลือย

No replies
Edkung
Edkung's picture
User offline. Last seen 7 hours 14 min ago. Offline
Joined: 11/29/2009

          พอย่างเข้าปีใหม่ทีไร เราก็จะเห็นกันว่าเหล่าบริษัทน้ำเมาก็จะปฏิบัติตามธรรมเนียมเข็นปฏิทินโป๊กันทุกปี แบบนี้สิ้นปีนี้ผมก็ขอนำเสนอ อะไรที่มันโป๊ๆ เปลือยๆ มั่งดีกว่า (อย่าคิดลึก ยังไงซะมันก็อยู่ในหมวด 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 หายเรียบไปเลย