http://atnd.org/events/19963
ÊÙ¶¯²ñ¤ÇÇÛÉÛ¤¹¤ë»ñÎÁ¤Îá¤Âæ¤Ç¤¹¡£
¢¨ ´°À®ÈǤϤ³¤Á¤é ¢Í http://d.hatena.ne.jp/n7shi/20111130
´Ø¿ô¤ÎºÇ½é¤ÈºÇ¸å¤Ë¤¢¤ë¡¢
¥¹¥¿¥Ã¥¯¥Õ¥ì¡¼¥à¤Î³ÎÊݤʤɷè¤Þ¤Ã¤¿½èÍý¡£
Release¤Ç¥¢¥»¥ó¥Ö¥ê½ÐÎÏ
ebp¤Ï´Ø¿ô¤Î¥¹¥¿¥Ã¥¯¥Õ¥ì¡¼¥à¤òÌÀ¼¨¤¹¤ë¥ì¥¸¥¹¥¿¡£
¥Ç¥Ð¥Ã¥°¤Î»þ¤Ë¥í¡¼¥«¥ëÊÑ¿ô¤Ê¤É¤¬ÇÄ°®¤·¤ä¤¹¤¯¤Ê¤ë¡£
¡Ö¥Õ¥ì¡¼¥à¥Ý¥¤¥ó¥¿¡¼¤Ê¤·¡×¤ò͸ú¤Ë¤¹¤ë¡£
(gcc¤Ç¤Ï -fomit-frame-pointer)
ebp¤ò·Ðͳ¤»¤º¤Ëesp¤òľÀܻȤ¦¤è¤¦¤Ë¤Ê¤ë¡£
¥Ç¥£¥¹¥×¥ì¡¼¥¹¥á¥ó¥È¤¬ebp¤ò°Õ¼±¤·¤¿¤â¤Î¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£
¥¹¥¿¥Ã¥¯¤Ï°ì»þŪ¤Ê¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë»ÈÍѤ¹¤ë¥á¥â¥êÎΰè
¶ñÂÎŪ¤Ë¤Ï¥í¡¼¥«¥ëÊÑ¿ô¤ä¸Æ¤Ó½Ð¤·ÍúÎò¤Ê¤É¤¬Æþ¤Ã¤Æ¤¤¤ë
FIFO¥Ð¥Ã¥Õ¥¡¡ÊºÇ¸å¤ËÆþ¤ì¤¿¥Ç¡¼¥¿¤¬ºÇ½é¤Ë¼è¤ê½Ð¤µ¤ì¤ë¡Ë
push/popÌ¿Îá¤ÇÁàºî
eax: 3
ebx: 2
ecx: 1
¥¹¥¿¥Ã¥¯¤Ïesp¤¬»Ø¤·¤Æ¤¤¤ë
Æþ¤ì¤ëÁ°¤Ë¸º¤é¤·¤Æ¡¢½Ð¤·¤¿¸å¤ËÁý¤ä¤¹
Îý½¬: esp=0x10¤È¤·¤ÆÆ°ºî¤ò¥È¥ì¡¼¥¹
´Ø¿ô¤Î´Êñ¤Ê¸Æ¤ÓÊý
¤¢¤é¤«¤¸¤á°ú¿ô¤ËɬÍפÊʬ¥¹¥¿¥Ã¥¯¤ò³ÎÊݤ¹¤ë¼êË¡¤â¤¢¤ë
gcc¤Ç¤Ï´Ø¿ôÁ´ÂΤǰú¿ô¤Ë»È¤¦¥¹¥¿¥Ã¥¯¤ò³ÎÄꤵ¤»¤¿¾å¤Ç¡¢
¥×¥í¥í¡¼¥°¤Ç¤¢¤é¤«¤¸¤á¥¹¥¿¥Ã¥¯¤ò³ÎÊݤ¹¤ë¥³¡¼¥É¤òÅǤ¯¡£
¤½¤Î¤¿¤á¥¢¥»¥ó¥Ö¥ê¤ò½ÐÎϤµ¤»¤Æ¤âpush¤¬½Ð¤Æ¤³¤Ê¤¤¡£
´Ø¿ô¤ò¸Æ¤Ó½Ð¤¹callÌ¿Îá¤ÏÌá¤êÀè¤ò¥¹¥¿¥Ã¥¯¤ËÀѤà
°ú¿ô¤òÀѤó¤Ç¸Æ¤Ó½Ð¤·¤¿¾ì¹ç¤Î¥¹¥¿¥Ã¥¯¹½Â¤
esp+0: Ìá¤êÀè
esp+4: 2
esp+8: 3
¤½¤Î¤¿¤á¸Æ¤Ó½Ð¤·Àè¤Ç°ú¿ô¤ò [esp+4], [esp+8] ¤È¤·¤Æ¼èÆÀ¤Ç¤¤ë¡£
°ú¿ô¤ò¤·¤ÆÊÖ¤¹´Ø¿ô¤Ï°Ê²¼¤ÎÄ̤ꡣ
_declspec(naked): ¥×¥í¥í¡¼¥°¤È¥¨¥Ô¥í¡¼¥°¤Î¾Êά¡ÊVC++ÀìÍÑ¡Ë
gcc¤Ë¤Ïnaked¤È¤¤¤¦attribute¤¬¤¢¤ë¤¬¡¢x86¤Ë¤Ï̤Âбþ
´Ø¿ô´Ý¤´¤È¥¤¥ó¥é¥¤¥ó¥¢¥»¥ó¥Ö¥é¤Ç½ñ¤¯¡ÊVC++¤Ç¤Ï¤Ç¤¤Ê¤¤¡Ë
¥¢¥»¥ó¥Ö¥é¤òIntel·Á¼°¤Ç½ñ¤¤¤Æ¤¤¤ë¤¿¤á¥ª¥×¥·¥ç¥ó¤¬É¬Í×
g++ -masm=intel 03.cpp
test2¤Ëextern "C"¤òÉÕ¤±¤Æ¤¤¤ë¤Î¤Ï¥Þ¥ó¥°¥ê¥ó¥°Âкö
ÉÕ¤±¤Ê¤¤¾ì¹ç¤Ï¤³¤ó¤Ê´¶¤¸
¥Þ¥ó¥°¥ê¥ó¥°µ¬Â§¤ÎÊѲ½¤ËÂбþ¤Ç¤¤Ê¤¤¤Î¤ÇÈò¤±¤¿¡£
¥Ç¥Þ¥ó¥°¥ë¤ÎÎã¡ÊÀèƬ¤Î_¤òÍî¤È¤·¤Æ¤«¤éÅϤ¹¡Ë
ÀΤÏñ¤Ë¥á¥â¥ê¤Ë¥³¡¼¥É¤ò½ñ¤¹þ¤à¤À¤±¤Ç½ÐÍè¤Æ¤¤¤¿
º£¤Ï¥á¥â¥êÊݸî¡ÊNX¥Ó¥Ã¥È¡Ë¤¬Æ¯¤¯¤¿¤á¤³¤Î¥³¡¼¥É¤ÏÍî¤Á¤ë¡£
¥Ò¡¼¥×¤ä¥¹¥¿¥Ã¥¯¤Ç¤Î¥³¡¼¥É¼Â¹Ô¤âƱÍÍ¡£
¢¨ÁÛÄê³°¤Î²Õ½ê¤Ç¥³¡¼¥É¤òÆ°¤«¤¹¤Î¤Ï¥Þ¥ë¥¦¥§¥¢¤Î¾ïÅå¼êÃÊ¡£
ÌÀ¼¨Åª¤Ë¼Â¹Ô²Äǽ°À¤òÉÕÍ¿¤·¤¿¥Ú¡¼¥¸¤ò³ÎÊݤ·¤Æ¥³¡¼¥É¤ò¥³¥Ô¡¼¤¹¤ë¡£
https://gist.github.com/1225880 (raw.cpp)
int test(int, int);
¤³¤Î´Ø¿ô¤Î¥Ý¥¤¥ó¥¿·¿¤Ï°Ê²¼¤ÎÄ̤ꡣ
int (*)(int, int)
̾Á°¤ÎÉôʬ¤¬ (*) ¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£
¾å¤ÎÎã¤Ç¤Ï¤³¤Î·¿¤¬reinterpret_cast¤Ç»È¤ï¤ì¤Æ¤¤¤ë¡£
¥Þ¥·¥ó¥³¡¼¥É¤Ï¤É¤¦¤ä¤Ã¤ÆÀ¸À®¤¹¤ë¤Î¤«¡©
¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤È¼ê·Ú¡£
herumi¤µ¤ó¤Ë¤è¤ë¥¤¥ó¥é¥¤¥ó¥¢¥»¥ó¥Ö¥é´¶³Ð¤ÇJIT¤Ç¤¤ë¥é¥¤¥Ö¥é¥ê
http://homepage1.nifty.com/herumi/soft/xbyak.html
¥Ø¥Ã¥À¤òinclude¤¹¤ë¤À¤±¤Ç»ÈÍѲÄǽ
https://gist.github.com/1225880 (xbyak.cpp)
¥Ð¥¤¥Ê¥ê¤ò³Îǧ¤¹¤ë¤¿¤á¤Ë¥À¥ó¥×¤·¤Æ¤ß¤ë¡£
¤³¤Î¼ê¤Î¥é¥¤¥Ö¥é¥ê¤Ï GNU lightning ¤Ê¤É¿§¡¹¤¢¤ë¡£
°Ê²¼¤Îµ»ö¤Ë¤Þ¤È¤á¤é¤ì¤Æ¤¤¤ë¡£
Brainf*ck¤Ç³Ø¤Ö¥¹¥¯¥ê¥×¥È¸À¸ì½èÍý·Ï¹â®²½¡£
http://d.hatena.ne.jp/hogelog/20100914/p1
; test(2, 3);
push 3
push 2
call _test
add esp, 8
_test:
; test(2, 3);
push 3
push 2
call _test
_test:
¥Ý¥¤¥ó¥¿¤Î¥¢¥¹¥¿¡¼¤ÎÁ°¤Ë¸Æ¤Ó½Ð¤·µ¬Ìó¤ò½ñ¤¯¡£
int(_stdcall *p)(int, int) = test;
´Êñ¤Ê³ÎǧÊýË¡¤È¤·¤Æ¡¢·¿¿äÏÀ¤µ¤»¤Æ¥Ä¡¼¥ë¥Á¥Ã¥×¤Ë½Ð¤¹ÊýË¡¤¬¤¢¤ë¡£
auto p = test;
¾åÎã¤Îp¤Ë¥Þ¥¦¥¹¥Ý¥¤¥ó¥¿¤òÅö¤Æ¤Æ¥Ä¡¼¥ë¥Á¥Ã¥×¤ò³Îǧ¤¹¤ë¡£
; test(2, 3);
mov edx, 3
mov ecx, 2
call _test
_test:
; reinterpret_cast<Test *>(2)->test(3);
mov ecx, 2
push 3
call ?test@Test@@QAEHH@Z
; struct Test { int test(int a) { return a; } };
?test@Test@@QAEHH@Z:
; reinterpret_cast<Test *>(2)->test(3);
push 3
push 2
call __ZN4Test4testEi
add esp, 8
; struct Test { int test(int a) { return a; } };
__ZN4Test4testEi:
[Ìä] stdcall¤Î´Ø¿ô¤ò¥µ¥ó¥¯¤Çcdecl¤ËÊÑ´¹¤·¤Æ¤¯¤À¤µ¤¤¡£
²óÅúÎã
´Ø¿ô¤òÅϤ·¤Æ¸Æ¤Ö¡£
static¥á¥ó¥Ð¤âƱ¤¸¤è¤¦¤Ë°·¤¨¤ë¡£
·¿¤¬Æ±¤¸¤Ê¤Î¤Ç¡¢Æ±¤¸´Ø¿ô¤ËÅϤ·¤Æ¸Æ¤Ó½Ð¤»¤ë¡£
¹½Ê¸¤¬Ìñ²ð¡£
auto¤¬¤Ê¤¤¤ÈÈó¾ï¤ËÌÌÅÝ¡£
Èó¥á¥ó¥Ð´Ø¿ô¤Î¥Ý¥¤¥ó¥¿¤ò¼è¤ë¤È¤¤Ë¤Ï & ¤¬¾Êά¤Ç¤¤ë¤¬¡¢
¥á¥ó¥Ð´Ø¿ô¤Ç¤Ï¾Êά¤Ç¤¤Ê¤¤¡£
²¼¤ÎÎã¤Ç¤Ïf1¤Èf2¤ÏƱ¤¸¡£
¸Æ¤Ó½Ð¤·»þ¤Î»²¾ÈÇí¤¬¤·¤Ë¤Ä¤¤¤Æ¤âƱÍÍ¡£
¤È¤¤¤¦¤è¤êC++¤Ç¤Ï .* ¤Ç1¤Ä¤Î±é»»»Ò¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤·¡¢
¤½¤¦¤Ç¤Ê¤¤¤È¤¿¤À¤Î¥á¥ó¥Ð¥¢¥¯¥»¥¹¤È¶èÊ̤¬ÉÕ¤«¤Ê¤¤¡£
static¤ÎÍ̵¤Ç¸ß´¹À¤¬¤Ê¤¯¤Ê¤ë¡£·¿¤â¥¯¥é¥¹¤Ë°Í¸¤¹¤ë¡£
https://gist.github.com/1273084
f1 != f2 != (f3 == f4)
¤È¤ê¤¢¤¨¤ºÆ±¤¸·¿¤È¤·¤Æ°·¤¦¤Ë¤Ï¤É¤¦¤¹¤ë¤«¡£
´Ø¿ô¤Î¤è¤¦¤Ë¿¶Éñ¤¦¥¯¥é¥¹¡£
C++11¤Ç¤Ï¥é¥à¥À¼°¤Ë¤è¤ê´Êñ¤Ë´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤¬ºî¤ì¤ë¡£
°Ê²¼¤Ît¤Ï¥é¥à¥À¼°¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¡£
ɸ½à¥é¥¤¥Ö¥é¥ê¤Ë¤Ï std::function ¤È¤¤¤¦
´Ø¿ô¥Ý¥¤¥ó¥¿¤Î¤è¤¦¤Ë»È¤¦´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤¬¤¢¤ë¡£
std::bind()¤ä¥é¥à¥À¼°¤Ê¤É¤Ç¥á¥ó¥Ð´Ø¿ô¤òÅϤ»¤ë¡£
¤³¤ì¤ò»È¤¦¤È¥á¥ó¥Ð¡¦Èó¥á¥ó¥Ð¤òÅý¹ç¤·¤Æ°·¤¨¤ë¤è¤¦¤Ë¤Ê¤ë¡£
https://gist.github.com/1273115
Èæ³Ó¤Î¤¿¤áF#¤Ë°Ü¿¢¡£
d1, d2, d3, d4¤Ï¤¹¤Ù¤ÆƱ¤¸·¿: unit->unit
¥³¡¼¥É¤¬C++¤ÇÊĤ¸¤Æ¤¤¤ë¤Ê¤é´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤Ç½¼Ê¬¡£
¤·¤«¤·OS¤ÎAPI¤Ç´Ø¿ô¥Ý¥¤¥ó¥¿·¿¤¬»ØÄꤵ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ê¤É¡¢
´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤ò¤½¤Î¤Þ¤Þ»È¤¨¤Ê¤¤¥±¡¼¥¹¤¬¤¢¤ë¡£
JIT¤Ç¥é¥Ã¥Ñ¡¼¤òºî¤Ã¤Æ¤·¤Þ¤¨¤Ð²ò·è¡ª
https://gist.github.com/1225997
void (*getPtr())();
VC++¤Îthiscall¤Ç¤Ï¸Æ¤Ó½Ð¤·À褬°ú¿ô¤Î¥¹¥¿¥Ã¥¯¤òÊÒÉÕ¤±¤ë¤¿¤á¡¢
¥µ¥ó¥¯¤Ç¤Ïcdecl¤È¤ÎÊÑ´¹¤¬É¬ÍפȤʤ롣
https://gist.github.com/1273062
void (*getPtr())(TA1)
¥µ¥ó¥¯¤Ë°ú¿ô¤òËä¤á¹þ¤á¤ÐÉôʬŬÍѤ¬²Äǽ¡£
¤·¤«¤·¤³¤ì¤Ï¤ä¤í¤¦¤È»×¤¨¤Ð½ÐÍè¤ë¡¢ÄøÅ٤Υͥ¿¡£
std::bind¤ÇÉôʬŬÍѤ·¤Æ¤«¤é¥µ¥ó¥¯¤ËÆþ¤ì¤¿Êý¤¬¥¹¥Þ¡¼¥È¡£
¤³¤Î¤è¤¦¤Ë²Äǽ¤Ê¸Â¤êC++¤ÎÈÏ°ÏÆâ¤Ç°·¤Ã¤Æ¡¢¥µ¥ó¥¯¤ÏºÇ½ª¼êÃÊ¡£
¥¥ã¥×¥Á¥ã¤òÉôʬŬÍѤÇɽ¸½¤¹¤ì¤Ð¡¢¥µ¥ó¥¯¤Ç¥¯¥í¡¼¥¸¥ã¤¬ºî¤ì¤ë¡£
https://gist.github.com/1226147
¤³¤ì¤ÏÆȼ«¤Ë¸À¸ì¤òºî¤ë¾ì¹ç¤Ï»È¤¨¤ë¼êË¡¤À¤È»×¤¦¤¬¡¢
¸À¸ì»ÅÍͤǥ¯¥í¡¼¥¸¥ã¤ò»ý¤ÄC++11¤Ç´º¤¨¤Æ¤ä¤ë°ÕÌ£¤ÏÇö¤¤¡£
ÉáÄ̤ËC++¤Çºî¤Ã¤¿¥¯¥í¡¼¥¸¥ã¤ò¥µ¥ó¥¯¤ÇÊñ¤ó¤ÀÊý¤¬¥·¥ó¥×¥ë¡£
https://gist.github.com/1273073
[Ìä] Windows¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¿÷·Á¤ò²þ¤¤·¤Æ¡¢°Ê²¼¤ò¥á¥ó¥Ð´Ø¿ô¤Ë¤·¤Æ¤¯¤À¤µ¤¤¡£
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
¢
class Window {
public:
https://gist.github.com/1226294
¥¤¥Ù¥ó¥È¥Ï¥ó¥É¥é¤ò´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È²½¤·¤Æ°Ñ¾ù¥â¥Ç¥ë²½¡£
¤³¤ì¤Ç¼«Æ°Åª¤Ë¥á¥ó¥Ð¤ÎÊý¤ËÂåÆþ¤µ¤ì¤ë¡£
WM_COMMAND¤ò°Ñ¾ù²½
¤¢¤Þ¤ê½¤Àµ¤·¤Ê¤¤¥Ø¥Ã¥À¤Ïstdafx.h¤Ë²¡¤·¹þ¤à¤È¥Ó¥ë¥É¤¬Â®¤¯¤Ê¤ë¡£
Window¥¯¥é¥¹¤Îpublic¥á¥ó¥Ð¤ËÄɲÃ
¢¨list¤ËÆþ¤ì¤ë¤³¤È¤Ç¥Þ¥ë¥Á¥¥ã¥¹¥È¤ò²Äǽ¤Ë¤·¤Æ¤¤¤ë¡£
Window::WndProc¤ÇÂбþ
¢¨for each¤ÏVC++¤ÎÆȼ«³ÈÄ¥¤Ê¤Î¤Ç¡¢Å¬µ¹½¤Àµ¤·¤Æ¤¯¤À¤µ¤¤¡£
¥¤¥Ù¥ó¥È¤òÀßÄê
WM_PAINT¤ò°Ñ¾ù²½
Window¥¯¥é¥¹¤Îpublic¥á¥ó¥Ð¤ËÄɲÃ
Window::WndProc¤ÇÂбþ
¥¤¥Ù¥ó¥È¤òÀßÄê
»Í³Ñ¤¬É½¼¨¤µ¤ì¤ë¡£
¥Þ¥¦¥¹¥Ü¥¿¥ó´Ø·¸¤Î¥á¥Ã¥»¡¼¥¸¤ò°Ñ¾ù²½¡£
stdafx.h¤ËÄɲÃ
Window¥¯¥é¥¹¤Îpublic¥á¥ó¥Ð¤ËÄɲÃ
Window¥¯¥é¥¹¤Îprotected¥á¥ó¥Ð¤ËÄɲÃ
Window::WndProc¤ÇÂбþ
¤³¤³¤Þ¤Ç¤Î¥½¡¼¥¹¡£
https://gist.github.com/1273003
¤Á¤ç¤Ã¤ÈŤ¤¤Î¤Ç¡¢¥½¡¼¥¹¤òʬ³ä¤·¤ÆÀ°Íý¡£
https://gist.github.com/1274679
Window.h
Window.cpp
win32thunk.cpp (¥×¥í¥¸¥§¥¯¥È̾¤Ë¤è¤ê°Û¤Ê¤ë)
¿§¡¹¤ÈÆͤùþ¤ß¤É¤³¤í¤Ï¤¢¤ë¤È»×¤¤¤Þ¤¹¤¬¡¢
º£²ó¤Ï¥¯¥é¥¹¥é¥¤¥Ö¥é¥ê¤òºî¤ë¤Î¤¬ÌÜŪ¤Ç¤Ï¤Ê¤¤¤Î¤Ç¡¢
ŬÅö¤Ë¸«Ä̤·¤òÎɤ¯¤¹¤ëÄøÅÙ¤Ëα¤á¤Æ¤¤¤Þ¤¹¡£
[Ìä] ÉÁ²è¤µ¤ì¤Æ¤¤¤ë»Í³Ñ¤ò¥É¥é¥Ã¥°¤ÇÆ°¤«¤»¤ë¤è¤¦¤Ë¤·¤Æ¤¯¤À¤µ¤¤¡£
¥Ò¥ó¥È
https://gist.github.com/1226666
¼¡¤Î¤è¤¦¤Ê´Ø¿ô¤¬¤¢¤Ã¤¿¤È¤¹¤ë¡£
Ä̾ºÇ½é¤Îreturn°Ê¹ß¤ÏÅþã¤Ç¤¤Ê¤¤¥³¡¼¥É¤È¤·¤Æ°·¤ï¤ì¤ë¡£
¤³¤ì¤¬¤â¤·¡¢¸Æ¤Ð¤ì¤ëÅ٤˼¡¤Ë¿Ê¤à¤È¤·¤¿¤é¤É¤¦¤À¤í¤¦¤«¡£
¤³¤Î¤è¤¦¤Ê¥â¥Ç¥ë¤ò¡Ö·Ñ³¡×¤È¸Æ¤Ó¡¢
·Ñ³¤ò´Þ¤à´Ø¿ô¤ò¥³¥ë¡¼¥Á¥ó¤È¸Æ¤Ö¡£
ñ½ã¤Ë¼ÂÁõ¤·¤¿¤À¤±¤À¤È¡¢°ìÅÙ¤·¤«¸Æ¤Ù¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¦¡£
¢¨¾å¤ÎÎã¤Ç¤ÏÆóÅÙ¤È1¤¬ÊÖ¤»¤Ê¤¯¤Ê¤ë¡£
¤½¤Î¤¿¤á´Ø¿ô¤ËÂФ¹¤ë¥¤¥ó¥¹¥¿¥ó¥¹¤È¤¤¤¦¹Í¤¨Êý¤òƳÆþ¤¹¤ë¡£
°Ê²¼¤Ïµ¼»÷¥³¡¼¥É¡£
C#¤Ç¤Ïyield¤È¤·¤Æ·Ñ³¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¡£
yield¤ò´Þ¤à¥á¥½¥Ã¥É¤Ï¥¤¥ó¥¹¥¿¥ó¥¹¤òÊÖ¤¹¡£
Python¤Ç¤Ï¥¸¥§¥Í¥ì¡¼¥¿¤È¸Æ¤Ð¤ì¤Æ¤¤¤ë¡£
C#/Python¤È¤â¤Ë¼Â¹Ô·ë²Ì¤Ï°Ê²¼¤ÎÄ̤ꡣ
·Ñ³¤ò¤É¤¦¼ÂÁõ¤¹¤ë¤«¤ò¸«¤Æ¤¤¤¯¡£
setjmp/longjmp¤Ç¥¹¥¿¥Ã¥¯¤ò´¬¤Ì᤹Îã¡£
¼¡¤ÎÎã¤Ç¤Ï¤¿¤Þ¤¿¤Þ°ú¿ô¤Î¥¢¥É¥ì¥¹¤¬°ìÃפ·¤¿¤¿¤á¤¹¤êÂؤï¤ë¡£
&s: 0013FE98, s: 00415758; test
&a: 0013FE98, a: 0
&s: 0013FE98, s: 00000000; (null)
end
RAII¤Ï½èÍý·Ï°Í¸
[VC++]
t1
t3
t2
[g++]
t2
¤³¤Î°ã¤¤¤Ï·Ñ³¤ò°·¤¦¾å¤ÇÌñ²ð¡£
C#¤ÇƱ¤¸¤â¤Î¤ò½ñ¤¤¤ÆÈæ³Ó¡£
¾¯¤·¤º¤Ä³ÈÄ¥¤·¤Æ¤¤¤¯¤¿¤á¤Ë¡¢¤Þ¤º¤Ï¼«Á°¼ÂÁõ¤·¤Æ¤ß¤ë¡£
https://gist.github.com/1257249
¥ì¥¸¥¹¥¿¤ò¹½Â¤ÂΤËÊݸ¤·¤Æ¤¤¤ë¤À¤±¡£
RAII¤Ï̵»ë¤·¤Æ¤¤¤ë¤Î¤Çg++¤ÈƱ¤¸·ë²Ì¤È¤Ê¤ë¡£
ñ½ã¤Ësetjmp/longjmp¤ÇÃæÃǤ·¤¿½èÍý¤òºÆ³«¤¹¤ë¤È
¥¹¥¿¥Ã¥¯¤¬Ç˲õ¤µ¤ì¤ë¤¿¤á¥í¡¼¥«¥ëÊÑ¿ô¤äÌá¤êÀ褬ÉÔÄê¡£
¥¹¥¿¥Ã¥¯¤Î¾ÃÈñ¤òÍÞ¤¨¤ë¤¿¤áRelease¥Ó¥ë¥É¤Ç³Îǧ¡£
¥¹¥¿¥Ã¥¯¤¬Ç˲õ¤µ¤ì¤Æ¤¤¤ë¡£
Éü¸µÍѥХåե¡¤òÄɲá£
¥¹¥¿¥Ã¥¯ÂàÈòÍÑ´Ø¿ô¡£
¥µ¥ó¥×¥ë¤ò²þ¤¡£
¥¹¥¿¥Ã¥¯¤¬Àµ¾ï¤ËÊݸ¤µ¤ì¤Æ¤¤¤ë¤³¤È¤ò³Îǧ¡£
¥í¡¼¥«¥ëÊÑ¿ô¤ò»È¤Ã¤Æ¤âÂç¾æÉס£
¼Â¹Ô·ë²Ì
Ìá¤êÀ褬ÊÝ»ý¤µ¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¤¿¤á¡¢½ªÎ»ÄÌÃΤÏÉÔÍס£
¸Æ¤Ó½Ð¤·¸µ¤Ç¤¤Á¤ó¤È·Ñ³¤µ¤ì¤ë¡£
https://gist.github.com/1259601
¼Â¹Ô·ë²Ì
¥Ð¥Ã¥Õ¥¡¤òÁê¸ß¤Ë¸Æ¤Ó¹ç¤¦¤Î¤Ïʬ¤«¤ê¤Ë¤¯¤¤¤Î¤Ç´Êά²½¤ò»î¤ß¤ë¡£
https://gist.github.com/1271852
¤³¤ì¤ò»È¤Ã¤ÆÎã¤ò½ñ¤Ä¾¤¹¤È°Ê²¼¤ÎÄ̤ꡣ
°ÊÁ°¤Ïlongjmp¤ÇÃͤòÅϤ·¤Æ¤¤¤¿¤¿¤á0¤¬ÆÃÊÌ°·¤¤¤µ¤ì¤Æ¤¤¤¿¤¬¡¢
ÃͤȾõÂÖ¤òʬΥ¤·¤¿¤¿¤¿¤á0¤âÌäÂê¤Ê¤¯ÅϤ»¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¡£
Àè¤Û¤É¤Î¼ÂÁõ¤Ï»öÁ°¤ËCoroutine¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÄêµÁ¤·¤Æ¡¢
yield¤¬¤½¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤ËÇû¤é¤ì¤Æ¤¤¤ë¡£
¤³¤ì¤Ç¤Ï³Ê¹¥°¤¤¤Î¤Çyield()¤òʸ̮°Í¸¤ÇÆÈΩ¤µ¤»¤Æ¤ß¤ë¡£
https://gist.github.com/1271857
¤³¤ì¤ò»È¤¨¤ÐÈó¾ï¤Ë¤¹¤Ã¤¤ê½ñ¤±¤ë¡£
RAII¤â»È¤¨¤ë¡£
https://gist.github.com/1258016
¼Â¹Ô·ë²Ì
°ã¤¦³¬Áؤ«¤é¸Æ¤Ö¤Èͽ´ü¤·¤Ê¤¤·ë²Ì¤È¤Ê¤ë¡£
Debug¤Ç¤ÏɽÌ̲½¤·¤Ê¤¤¤Î¤ÇRelease¤Ç¥Ó¥ë¥É¡£
https://gist.github.com/1273598
¸Æ¤Ó½Ð¤·¸µ¤Î¥¹¥¿¥Ã¥¯¤Ë°Í¸¤¹¤ë¤¿¤á¡¢
test2()¤«¤é¸Æ¤Ð¤ì¤¿¥³¥ë¡¼¥Á¥ó¤ÏÀµ¾ï¤ËÆ°ºî¤·¤Ê¤¤¡£
¤Á¤Ê¤ß¤Ëf¤ò´Ø¿ô¥Ý¥¤¥ó¥¿¤ËÊѹ¹¤¹¤ë¤ÈDebug¥Ó¥ë¥É¤Ç¤âÍî¤Á¤ë¡£
¤¿¤À¤·Íî¤Á¤ë¥¿¥¤¥ß¥ó¥°¤Ï¿¾¯°Û¤Ê¤ë¡£
¥³¥ë¡¼¥Á¥ó¤¬»ÈÍѤ¹¤ë¥¹¥¿¥Ã¥¯¤ò¤½¤Î¤Þ¤ÞÀѤà¤Î¤Ç¤Ï¤Ê¤¯¡¢
ÆÃÄê¤ÎÎΰè¤Ë¼è¤Ã¤Æ´ÉÍý¤¹¤ë¤³¤È¤ÇÌäÂê¤ò²ò·è¤¹¤ë¡£
̵¸ÂºÆµ¢¤Ç¥¹¥¿¥Ã¥¯¤Î¸Â³¦¤òõ¤ë¡£
¼Â¹Ô·ë²Ì¤Ï°Ê²¼¤ÎÄ̤ꡣ
¢¨´Ä¶¤Ë¤è¤Ã¤ÆÃͤϰۤʤë¤È»×¤ï¤ì¤ë¡£
¥¹¥¿¥Ã¥¯¤Î¸Â³¦¤¬Ìó1MB¤À¤È¤¤¤¦¤³¤È¤¬Ê¬¤«¤ë¡£
¤³¤ÎÃͤÏPE¥Ø¥Ã¥À¤Ë½ñ¤¤¤Æ¤¢¤ë¡£
VC++2010¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤÏ0x100000(1MB)¡£
¥¹¥¿¥Ã¥¯¤ò¤¢¤ëÄøÅÙ¶õ¤±¤Æ¥³¥ë¡¼¥Á¥ó¤ò¼Â¹Ô¤¹¤ë¡£
¶õ¤±¤¿¥¹¥¿¥Ã¥¯¤ÎÀèƬ¤ò¥á¥ó¥Ð¤Ë»Ä¤·¤Æ¤ª¤¯¡£
¥í¡¼¥«¥ë¤ËµðÂç¤ÊÇÛÎó¤ò³ÎÊݤ·¤Ê¤¤¸Â¤ê¡¢
32KB¤â¥¹¥¿¥Ã¥¯¤ò¾ÃÈñ¤¹¤ë¤³¤È¤Ï¾¯¤Ê¤¤¤È»×¤¦¡£
Ç°¤Î¤¿¤á·Ñ³»þ¤Ë¥¹¥¿¥Ã¥¯¤òÆͤÇˤäƤ¤¤Ê¤¤¤«¥Á¥§¥Ã¥¯¤¹¤ë¡£
¶õ¤±¤¿¥¹¥¿¥Ã¥¯¤òÊݸ¤¹¤ë¤È̵Â̤ʤΤǡ¢
¥á¥ó¥Ð¤Ë»Ä¤·¤¿¥¹¥¿¥Ã¥¯¤Î¥¢¥É¥ì¥¹¤ò»È¤¦¡£
ÌäÂêÅÀ¤È¤·¤ÆÁ°·Ç¤·¤¿¥³¡¼¥É¤¬°ì¸«Àµ¾ï¤ËÆ°¤¯¡£
¥³¥ë¡¼¥Á¥óÆâ¤Î¥ë¡¼¥×¤Î¾å¸Â¤ò5¤«¤é0¤Ë¤¹¤ë¤È°Û¾ïÆ°ºî¤¹¤ë¡£
https://gist.github.com/1273606
¥³¥ë¡¼¥Á¥ó¤òÈ´¤±¤ë¤È¤¤Ë¥¹¥¿¥Ã¥¯¤¬²õ¤ì¤ë¡£
¥³¥ë¡¼¥Á¥ó¤ò¸Æ¤ó¤Ç¤¤¤ëÉôʬ¤ò¸«¤ë¤È¡¢
½ªÎ»»þ¤Ï¤½¤Î¤Þ¤Þή¤ìÍî¤Á¤ë¤³¤È¤ò´üÂÔ¤·¤Æ¤¤¤ë¡£
Ê̤γ¬Áؤ«¤é¸Æ¤Ö¤ÈÉüµ¢»þ¤Îebp¤¬¿©¤¤°ã¤¦¤¿¤á¡¢
¥í¡¼¥«¥ëÊÑ¿ô¤¬Àµ¾ï¤Ë»²¾È¤Ç¤¤º¤Ë¥¨¥é¡¼¤È¤Ê¤ë¡£
¥³¥ë¡¼¥Á¥ó¤ò¥é¥Ã¥Ñ¡¼·Ðͳ¤Ç¸Æ¤ó¤Ç½ªÎ»ÄÌÃΤ¹¤ì¤Ð²ò·è¡£
https://gist.github.com/1271829
º£¤Þ¤Ç½¤Àµ¤âƱ»þ¤Ë¹Ô¤¦¤¿¤á1¤Ä¤Î¥½¡¼¥¹¤ËÁ´Éô½ñ¤¤¤Æ¤¤¤¿¡£
½¤Àµ¤¬Íî¤ÁÃ夤¤¿¤Î¤Ç¥½¡¼¥¹¤òʬ³ä¤·¤ÆÀ°Íý¡£
https://gist.github.com/1274612
Coroutine.h
Coroutine.cpp
·¿¤¬¼Â¹Ô»þȽÄê¤Î¤¿¤á¡¢·¿»ØÄê¤ò´Ö°ã¤¨¤ë¤ÈÆ°¤«¤Ê¤¤¤Î¤ÇÃí°Õ¡£
¥³¥ë¡¼¥Á¥ó¤Î·Ñ³»þ¤Ë°ú¿ô¡ÊÁêÅö¡Ë¤òÅϤ¹ÊýË¡¡£
value¤ò½ñ¤´¹¤¨¤ë¤Èyield¤Ç¤½¤ÎÃͤ¬Ìᤵ¤ì¤ë¡£
¢¨¤¢¤é¤«¤¸¤á¤³¤ì¤¬¤Ç¤¤ë¤è¤¦¤Ë¹Íθ¤·¤¿»ÅÍÍ¡£
¤³¤ì°Ê³°¤ÎÊýË¡¤ò¤¤¤¯¤Ä¤«¾Ò²ð¤¹¤ë¡£
¥¯¥í¡¼¥¸¥ã¤Ç¥í¡¼¥«¥ëÊÑ¿ô¤ò¥¥ã¥×¥Á¥ã¡£
´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤òÅϤ¹¤È¥¤¥ó¥¹¥¿¥ó¥¹¤¬ºî¤é¤ì¤Æ¡¢
°ú¿ô¤È¤·¤Æ¥á¥ó¥Ð¤ò¤¤¤¸¤ëÌÜŪ¤ÏãÀ®¤Ç¤¤Ê¤¤¡£
¤¢¤Þ¤ê»È¤¤Æ»¤Ï¤Ê¤¤¤¬¡¢¥Ï¥Þ¤ë²ÄǽÀ¤¬¤¢¤ë¤¿¤á¾Ò²ð¡£
¤¢¤ë°ÕÌ£¥¸¥§¥Í¥ì¡¼¥¿¤Ã¤Ý¤¤¡£
¤·¤«¤·³°Éô¤«¤éÃͤòÁàºî¤Ç¤¤Ê¤¤¤Ê¤é¡¢
ñ½ã¤Ë¥í¡¼¥«¥ëÊÑ¿ô¤Ç¥«¥¦¥ó¥È¤·¤¿Êý¤¬Îɤ¤¡£
¥µ¥ó¥¯¤È°Ñ¾ù¤òƳÆþ¤·¤¿Win32¤Ë·Ñ³¤òÁȤ߹ç¤ï¤»¤ë¡£
¥¤¥Ù¥ó¥È¥É¥ê¥Ö¥ó¤Ç¾õÂÖ¤òÊÝ»ý¤·¤Æ¤¤¤ëÉôʬ¤Î¿Þ¼¨¡£
°ìÏ¢¤Îή¤ì¤¬Ê¬ÃǤµ¤ì¤Æ¤¤¤ë¡£
¡ù¢ª{}
¡ù¢ª{}
¡ù¢ª{}
¥¤¥Ù¥ó¥È´Ö¤Ç¾õÂÖ¤ò¶¦Í¤¹¤ë¤¿¤á¥Õ¥é¥°¤ÎÎबɬÍפȤʤ롣
¥Ñ¥Ã¥·¥Ö¡Ê¥×¥Ã¥·¥å·¿¡Ë¤Ê¥³¡¼¥É¡£
¤³¤ì¤ò¥¢¥¯¥Æ¥£¥Ö¡Ê¥×¥ë·¿¡Ë¤Ê·Á¤ËÊÑ´¹¤¹¤ë¤È¡¢
¾õÂÖ¤Ïʬ´ô¤ä¥í¡¼¥«¥ëÊÑ¿ô¤Ë²¡¤·¹þ¤à¤³¤È¤¬¤Ç¤¤ë¡£
·Ñ³¤Ï¤Ê¤ë¤Ù¤¯¥é¥¤¥Ö¥é¥ê¦¤Ë±£¤¹¤È»È¤¤¤ä¤¹¤¯¤Ê¤ë¡£
Á°²ó¤ÎÌäÂê¤Ç»ÈÍѤ·¤¿Win32¥×¥í¥°¥é¥à¤ò³ÈÄ¥¤¹¤ë¡£
Coroutine.h¤ÈCoroutine.cpp¤ò¥×¥í¥¸¥§¥¯¥È¤ËÄɲá£
stdafx.h¤ËÄɲá£
Coroutine.cpp¤Ç¤Ïstdafx.h¤òinclude¤¹¤ë¡£
¤³¤ì¤ÇCoroutine¥¯¥é¥¹¤ÎÄɲäϴ°Î»¡£
¥É¥é¥Ã¥°¤ò¥³¥ë¡¼¥Á¥ó¤Ç´Æ»ë¡£
https://gist.github.com/1275118
¤â¤¦¾¯¤·¥³¡¼¥É¤òÀ°Íý¤¹¤ë¡£
https://gist.github.com/1275258
Coroutine¥¯¥é¥¹¤ò³ÈÄ¥¤·¤Æ´¬¤Ì᤻¤ë¤è¤¦¤Ë¤¹¤ë¡£
¥Ï¥ó¥É¥é¤È¤Î¶¨Ä´Æ°ºî¤òÃê½Ð¤·¤Æ¥¯¥é¥¹²½¤¹¤ë¡£
´¬¤Ìᤷ¤òÍøÍѤ·¤Æ̵¸Â¥ë¡¼¥×¤òÇÓ½ü¤·¤Æ¤¤¤ë¡£
¤³¤ì¤ò»È¤Ã¤Æ¥Ï¥ó¥É¥é¤ò½ñ¤Ä¾¤¹¡£
¥µ¥ó¥¯¡¦°Ñ¾ù¡¦·Ñ³¤ò»È¤Ã¤¿¥¤¥Ù¥ó¥È¥Ï¥ó¥É¥ê¥ó¥°¤¬´°À®¡£
¤³¤ì¤¬º£²óÄ󼨤·¤¿¤«¤Ã¤¿¥â¥Ç¥ë¡£
²ó¤ê¤«¤éºî¤Ã¤Æ¤¤¤¿¤Î¤Ç·ë¹½Ä¹¤¤Æ»¤Î¤ê¤À¤Ã¤¿¤±¤É¡¢
¤Ç¤¤¿¤â¤Î¤òÍøÍѤ¹¤ë¤À¤±¤Ê¤é¥·¥ó¥×¥ë¤À¤È»×¤¦¡£
Ê£¿ô¤Î¹àÌܤò°·¤¨¤ë¤è¤¦¤Ë¤·¤Æ¤ß¤ë¡£
https://gist.github.com/1275467
¤Á¤é¤Ä¤¤¬·ã¤·¤¤¤¬¡¢Âкö¤Ë¤Ï¥À¥Ö¥ë¥Ð¥Ã¥Õ¥¡¤¬É¬Íס£
º£²ó¤Ï¥µ¥ó¥¯¤È·Ñ³¤¬¥á¥¤¥ó¤Ê¤Î¤ÇÀâÌÀ¤Ï¸«Á÷¤ë¡£
º£²ó·ÇºÜ¤·¤¿¥µ¥ó¥×¥ë¥³¡¼¥É¤Ï¤¹¤Ù¤ÆCC0¤ÇÄ󶡤·¤Þ¤¹¡£
º£²ó¤ä¤Ã¤¿¤è¤¦¤ÊÆâÍƤòÊÙ¶¯¤¹¤ë¤Ë¤Ï¡¢
´û¸¤Î¥³¥ó¥Ñ¥¤¥é¤Î½ÐÎϤòÅð¤ß¸«¤·¤Ê¤¬¤é¡¢
¼«Ê¬¤Ç¥³¥ó¥Ñ¥¤¥é¤òºî¤Ã¤Æ¤ß¤ë¤Î¤¬Îɤ¤¤È»×¤¤¤Þ¤¹¡£
¥µ¥ó¥¯
¥³¥ë¡¼¥Á¥ó
ÊÙ¶¯²ñ¤ÇÇÛÉÛ¤¹¤ë»ñÎÁ¤Îá¤Âæ¤Ç¤¹¡£
¢¨ ´°À®ÈǤϤ³¤Á¤é ¢Í http://d.hatena.ne.jp/n7shi/20111130
- ±Ññ¸ì¤È¤·¤Æ¤ÏÆä˰ÕÌ£¤¬¤Ê¤¤¡£
- Algol 60¤Ç¥¢¥É¥ì¥¹¤òÃÙ±äɾ²Á¤¹¤ë¤¿¤á¤ËƳÆþ¡£
- PE¤Ç¤âDLL¤«¤é¥¤¥ó¥Ý¡¼¥È¤·¤¿´Ø¿ô¤Î¥¢¥É¥ì¥¹¤¬¥µ¥ó¥¯¤ËÆþ¤ë¡£
- 16¥Ó¥Ã¥È¥³¡¼¥É¤È32¥Ó¥Ã¥È¥³¡¼¥É¤ÎÊÑ´¹¤â¥µ¥ó¥¯¤È¸Æ¤Ð¤ì¤ë¡£
- º£²ó¤Ï¼Â¹Ô»þ¤Ë¥¢¥É¥ì¥¹¤òÊÑ´¹¤¹¤ëµ¡¹½¤ò¤Þ¤È¤á¤Æ¥µ¥ó¥¯¤È¸Æ¤Ö¡£
- ¥µ¥ó¥¯¤ÎÀ¸À®¤ÏOS¤äCPU¤Ë°Í¸¤¹¤ë¡£
- º£²ó¤Ïi386(32bit x86)¤Ë¾ÇÅÀ¤ò¹Ê¤ë¡£
- ¸Å¤¤API¤Ø¤Î¥³¡¼¥ë¥Ð¥Ã¥¯¤äÆȼ«¸À¸ì¤Î¼ÂÁõ¤Ë¤ÏÍÍÑ¡£
- ½ã¿è¤ÊC++¤ÎÏÈÆâ¤Ç¤Ï¤¢¤Þ¤ê»È¤¦Í¾ÃϤϤʤ¤¡£
´Ø¿ô¤ÎºÇ½é¤ÈºÇ¸å¤Ë¤¢¤ë¡¢
¥¹¥¿¥Ã¥¯¥Õ¥ì¡¼¥à¤Î³ÎÊݤʤɷè¤Þ¤Ã¤¿½èÍý¡£
int test(int a, int b) { return a + b; }
Release¤Ç¥¢¥»¥ó¥Ö¥ê½ÐÎÏ
_test PROC ; ¥×¥í¥í¡¼¥° push ebp mov ebp, esp ; ËÜÂÎ mov eax, DWORD PTR 12[ebp] add eax, DWORD PTR 8[ebp] ; ¥¨¥Ô¥í¡¼¥° pop ebp ret 0 _test ENDP
ebp¤Ï´Ø¿ô¤Î¥¹¥¿¥Ã¥¯¥Õ¥ì¡¼¥à¤òÌÀ¼¨¤¹¤ë¥ì¥¸¥¹¥¿¡£
¥Ç¥Ð¥Ã¥°¤Î»þ¤Ë¥í¡¼¥«¥ëÊÑ¿ô¤Ê¤É¤¬ÇÄ°®¤·¤ä¤¹¤¯¤Ê¤ë¡£
¡Ö¥Õ¥ì¡¼¥à¥Ý¥¤¥ó¥¿¡¼¤Ê¤·¡×¤ò͸ú¤Ë¤¹¤ë¡£
(gcc¤Ç¤Ï -fomit-frame-pointer)
_test PROC mov eax, DWORD PTR 12[esp-4] add eax, DWORD PTR 8[esp-4] ret 0 _test ENDP
ebp¤ò·Ðͳ¤»¤º¤Ëesp¤òľÀܻȤ¦¤è¤¦¤Ë¤Ê¤ë¡£
¥Ç¥£¥¹¥×¥ì¡¼¥¹¥á¥ó¥È¤¬ebp¤ò°Õ¼±¤·¤¿¤â¤Î¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£
- 12[esp-4] ¢ª 8[esp]
- 8[esp-4] ¢ª 4[esp]
¥¹¥¿¥Ã¥¯¤Ï°ì»þŪ¤Ê¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë»ÈÍѤ¹¤ë¥á¥â¥êÎΰè
¶ñÂÎŪ¤Ë¤Ï¥í¡¼¥«¥ëÊÑ¿ô¤ä¸Æ¤Ó½Ð¤·ÍúÎò¤Ê¤É¤¬Æþ¤Ã¤Æ¤¤¤ë
FIFO¥Ð¥Ã¥Õ¥¡¡ÊºÇ¸å¤ËÆþ¤ì¤¿¥Ç¡¼¥¿¤¬ºÇ½é¤Ë¼è¤ê½Ð¤µ¤ì¤ë¡Ë
push/popÌ¿Îá¤ÇÁàºî
push dword 1 push dword 2 push dword 3 pop eax pop ebx pop ecx
eax: 3
ebx: 2
ecx: 1
¥¹¥¿¥Ã¥¯¤Ïesp¤¬»Ø¤·¤Æ¤¤¤ë
Æþ¤ì¤ëÁ°¤Ë¸º¤é¤·¤Æ¡¢½Ð¤·¤¿¸å¤ËÁý¤ä¤¹
sub esp, 4 mov dword [esp], 1 sub esp, 4 mov dword [esp], 2 sub esp, 4 mov dword [esp], 3 mov eax, [esp] add esp, 4 mov ebx, [esp] add esp, 4 mov ecx, [esp] add esp, 4
Îý½¬: esp=0x10¤È¤·¤ÆÆ°ºî¤ò¥È¥ì¡¼¥¹
´Ø¿ô¤Î´Êñ¤Ê¸Æ¤ÓÊý
; test(2, 3); push 3 push 2 call test add esp, 8
- °ú¿ô¤Ï¸å¤í¤«¤épush¤¹¤ë
- eax¤Ë·ë²Ì¤¬Æþ¤ë
- push¤·¤¿Ê¬¤Î¥¹¥¿¥Ã¥¯¤Ï add esp, 8 ¤ÇÌᤷ¤Æ¤¤¤ë
- pop¤ò»È¤ï¤Ê¤¤¤Î¤ÏÃͤò¼Î¤Æ¤ë¤«¤é
- ¤³¤Î¤è¤¦¤Ëesp¤¬¤Á¤ç¤³¤Á¤ç¤³Æ°¤¯¤È¤¡¢ebp¤Ç¤Î¸ÇÄê¤Ë°ÕÌ£¤¬½Ð¤ë
¤¢¤é¤«¤¸¤á°ú¿ô¤ËɬÍפÊʬ¥¹¥¿¥Ã¥¯¤ò³ÎÊݤ¹¤ë¼êË¡¤â¤¢¤ë
sub esp, 8 mov [esp+4], 3 mov [esp], 2 call test add esp, 8
gcc¤Ç¤Ï´Ø¿ôÁ´ÂΤǰú¿ô¤Ë»È¤¦¥¹¥¿¥Ã¥¯¤ò³ÎÄꤵ¤»¤¿¾å¤Ç¡¢
¥×¥í¥í¡¼¥°¤Ç¤¢¤é¤«¤¸¤á¥¹¥¿¥Ã¥¯¤ò³ÎÊݤ¹¤ë¥³¡¼¥É¤òÅǤ¯¡£
¤½¤Î¤¿¤á¥¢¥»¥ó¥Ö¥ê¤ò½ÐÎϤµ¤»¤Æ¤âpush¤¬½Ð¤Æ¤³¤Ê¤¤¡£
´Ø¿ô¤ò¸Æ¤Ó½Ð¤¹callÌ¿Îá¤ÏÌá¤êÀè¤ò¥¹¥¿¥Ã¥¯¤ËÀѤà
- call test == push eip; jmp test¡Êµ¼»÷¥³¡¼¥É¡Ë
- ret == pop edx; jmp edx
- CPU¤Ë¤è¤Ã¤Æ¤Ïµ¼»÷¥³¡¼¥ÉÁêÅö¤ÎÌ¿Îá¤òÌÀ¼¨Åª¤Ë½ñ¤¯¤â¤Î¤¬¤¢¤ë
- ¾ÜºÙ¤Ïºä°æ¤µ¤ó¤¬Ëܤò¼¹É®Ãæ
http://kozos.jp/books/asm/
°ú¿ô¤òÀѤó¤Ç¸Æ¤Ó½Ð¤·¤¿¾ì¹ç¤Î¥¹¥¿¥Ã¥¯¹½Â¤
push 3 push 2 call test
esp+0: Ìá¤êÀè
esp+4: 2
esp+8: 3
¤½¤Î¤¿¤á¸Æ¤Ó½Ð¤·Àè¤Ç°ú¿ô¤ò [esp+4], [esp+8] ¤È¤·¤Æ¼èÆÀ¤Ç¤¤ë¡£
°ú¿ô¤ò¤·¤ÆÊÖ¤¹´Ø¿ô¤Ï°Ê²¼¤ÎÄ̤ꡣ
test: mov eax, [esp+4] add eax, [esp+8] ret
_declspec(naked): ¥×¥í¥í¡¼¥°¤È¥¨¥Ô¥í¡¼¥°¤Î¾Êά¡ÊVC++ÀìÍÑ¡Ë
#include <stdio.h> int test1(int a, int b) { return a + b; } _declspec(naked) int test2(int a, int b) { _asm { mov eax, 4[esp] add eax, 8[esp] ret } } int main() { printf("test1(2, 3): %d\n", test1(2, 3)); printf("test2(2, 3): %d\n", test2(2, 3)); }
gcc¤Ë¤Ïnaked¤È¤¤¤¦attribute¤¬¤¢¤ë¤¬¡¢x86¤Ë¤Ï̤Âбþ
´Ø¿ô´Ý¤´¤È¥¤¥ó¥é¥¤¥ó¥¢¥»¥ó¥Ö¥é¤Ç½ñ¤¯¡ÊVC++¤Ç¤Ï¤Ç¤¤Ê¤¤¡Ë
#include <stdio.h> int test1(int a, int b) { return a + b; } extern "C" int test2(int, int); asm( "_test2:\n" " mov eax, dword ptr [esp+4]\n" " add eax, dword ptr [esp+8]\n" " ret\n"); int main() { printf("test1(2, 3): %d\n", test1(2, 3)); printf("test2(2, 3): %d\n", test2(2, 3)); }
¥¢¥»¥ó¥Ö¥é¤òIntel·Á¼°¤Ç½ñ¤¤¤Æ¤¤¤ë¤¿¤á¥ª¥×¥·¥ç¥ó¤¬É¬Í×
g++ -masm=intel 03.cpp
test2¤Ëextern "C"¤òÉÕ¤±¤Æ¤¤¤ë¤Î¤Ï¥Þ¥ó¥°¥ê¥ó¥°Âкö
ÉÕ¤±¤Ê¤¤¾ì¹ç¤Ï¤³¤ó¤Ê´¶¤¸
int test2(int, int); asm( "__Z5test2ii:\n" " mov eax, dword ptr [esp+4]\n" " add eax, dword ptr [esp+8]\n" " ret\n");
¥Þ¥ó¥°¥ê¥ó¥°µ¬Â§¤ÎÊѲ½¤ËÂбþ¤Ç¤¤Ê¤¤¤Î¤ÇÈò¤±¤¿¡£
*** ¤ª¤Þ¤±
¥Ç¥Þ¥ó¥°¥ë¤ÎÎã¡ÊÀèƬ¤Î_¤òÍî¤È¤·¤Æ¤«¤éÅϤ¹¡Ë
ÀΤÏñ¤Ë¥á¥â¥ê¤Ë¥³¡¼¥É¤ò½ñ¤¹þ¤à¤À¤±¤Ç½ÐÍè¤Æ¤¤¤¿
#include <stdio.h> unsigned char testf[] = { 0x8b, 0x44, 0x24, 0x04, // mov eax, [esp+4] 0x03, 0x44, 0x24, 0x08, // add eax, [esp+8] 0xc3 // ret }; int main() { auto test = reinterpret_cast<int(*)(int, int)>(&testf); printf("test(2, 3): %d\n", test(2, 3)); }
º£¤Ï¥á¥â¥êÊݸî¡ÊNX¥Ó¥Ã¥È¡Ë¤¬Æ¯¤¯¤¿¤á¤³¤Î¥³¡¼¥É¤ÏÍî¤Á¤ë¡£
¥Ò¡¼¥×¤ä¥¹¥¿¥Ã¥¯¤Ç¤Î¥³¡¼¥É¼Â¹Ô¤âƱÍÍ¡£
¢¨ÁÛÄê³°¤Î²Õ½ê¤Ç¥³¡¼¥É¤òÆ°¤«¤¹¤Î¤Ï¥Þ¥ë¥¦¥§¥¢¤Î¾ïÅå¼êÃÊ¡£
*** NXÂкö
ÌÀ¼¨Åª¤Ë¼Â¹Ô²Äǽ°À¤òÉÕÍ¿¤·¤¿¥Ú¡¼¥¸¤ò³ÎÊݤ·¤Æ¥³¡¼¥É¤ò¥³¥Ô¡¼¤¹¤ë¡£
https://gist.github.com/1225880 (raw.cpp)
#include <windows.h> #include <stdio.h> #include <string.h> unsigned char testf[] = { 0x8b, 0x44, 0x24, 0x04, // mov eax, [esp+4] 0x03, 0x44, 0x24, 0x08, // add eax, [esp+8] 0xc3 // ret }; int main() { auto page = VirtualAlloc(nullptr, sizeof(testf), MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(page, testf, sizeof(testf)); auto test = reinterpret_cast<int(*)(int, int)>(page); printf("test(2, 3): %d\n", test(2, 3)); VirtualFree(page, 0, MEM_RELEASE); }
*** ´Ø¿ô¥Ý¥¤¥ó¥¿·¿¤Î¥³¥Ä¤ß¤¿¤¤¤Ê¤â¤Î¡£
int test(int, int);
¤³¤Î´Ø¿ô¤Î¥Ý¥¤¥ó¥¿·¿¤Ï°Ê²¼¤ÎÄ̤ꡣ
int (*)(int, int)
̾Á°¤ÎÉôʬ¤¬ (*) ¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£
¾å¤ÎÎã¤Ç¤Ï¤³¤Î·¿¤¬reinterpret_cast¤Ç»È¤ï¤ì¤Æ¤¤¤ë¡£
¥Þ¥·¥ó¥³¡¼¥É¤Ï¤É¤¦¤ä¤Ã¤ÆÀ¸À®¤¹¤ë¤Î¤«¡©
¥é¥¤¥Ö¥é¥ê¤ò»È¤¦¤È¼ê·Ú¡£
- Xbyak(¥«¥¤¥Ó¥ã¥Ã¥¯)
herumi¤µ¤ó¤Ë¤è¤ë¥¤¥ó¥é¥¤¥ó¥¢¥»¥ó¥Ö¥é´¶³Ð¤ÇJIT¤Ç¤¤ë¥é¥¤¥Ö¥é¥ê
http://homepage1.nifty.com/herumi/soft/xbyak.html
¥Ø¥Ã¥À¤òinclude¤¹¤ë¤À¤±¤Ç»ÈÍѲÄǽ
https://gist.github.com/1225880 (xbyak.cpp)
#include <stdio.h> #include "xbyak/xbyak.h" struct TestFunc : public Xbyak::CodeGenerator { TestFunc() { mov(eax, ptr[esp+4]); add(eax, ptr[esp+8]); ret(); } }; int main() { TestFunc testf; auto test = reinterpret_cast<int(*)(int, int)>( const_cast<Xbyak::uint8 *>(testf.getCode())); printf("test(2, 3): %d\n", test(2, 3)); }
¥Ð¥¤¥Ê¥ê¤ò³Îǧ¤¹¤ë¤¿¤á¤Ë¥À¥ó¥×¤·¤Æ¤ß¤ë¡£
¤³¤Î¼ê¤Î¥é¥¤¥Ö¥é¥ê¤Ï GNU lightning ¤Ê¤É¿§¡¹¤¢¤ë¡£
°Ê²¼¤Îµ»ö¤Ë¤Þ¤È¤á¤é¤ì¤Æ¤¤¤ë¡£
Brainf*ck¤Ç³Ø¤Ö¥¹¥¯¥ê¥×¥È¸À¸ì½èÍý·Ï¹â®²½¡£
http://d.hatena.ne.jp/hogelog/20100914/p1
- C declare
- ÉáÄ̤ËÄêµÁ¤·¤¿´Ø¿ô¤Ï¤¹¤Ù¤Æ¤³¤ì: int test(int, int);
- VC++¤Ç¤Ï¥ª¥×¥·¥ç¥ó¤Ç¥Ç¥Õ¥©¥ë¥È¤òÊѹ¹¤Ç¤¤ë: C/C++ ¢ª ¾ÜºÙÀßÄê
- °ú¿ô¤Ï¸å¤í¤«¤é¥¹¥¿¥Ã¥¯¤ËÀѤߡ¢Ìá¤êÃͤÏeax¤ÇÊÖ¤¹
- ¥¹¥¿¥Ã¥¯¤Ï¸Æ¤Ó½Ð¤·Â¦¤ÇÌ᤹
- º£¤Þ¤Ç°úÍѤ·¤¿Îã¤âcdecl
; test(2, 3);
push 3
push 2
call _test
add esp, 8
_test:
mov eax, [esp+4] add eax, [esp+8] ret
- standard call
- Win32API¤Îɸ½à¸Æ¤Ó½Ð¤·µ¬Ìó¡£
- °ú¿ô¤Ï¸å¤í¤«¤é¥¹¥¿¥Ã¥¯¤ËÀѤߡ¢Ìá¤êÃͤÏeax¤ÇÊÖ¤¹
- ¥¹¥¿¥Ã¥¯¤Ï¸Æ¤Ó½Ð¤µ¤ì¤¿Â¦¤ÇÌ᤹¡£
- x86¤Ç¤Ïret¤Ë°ú¿ô¤òÅϤ·¤Æ¥¹¥¿¥Ã¥¯¤òÌ᤹¤³¤È¤¬¤Ç¤¤ë¡£
; test(2, 3);
push 3
push 2
call _test
_test:
mov eax, [esp+4] add eax, [esp+8] ret 8
- °ú¿ô¤¬¥¼¥í¤Î¤È¤¤Ïcdecl¤ÈƱ¤¸
- ²ÄÊÑĹ°ú¿ô¤¬»È¤¨¤Ê¤¤
- Win32API¤Îwsprintf()¤Ïcdecl
- w¤ÏWindows¤Ç¥ï¥¤¥É¤Ç¤Ï¤Ê¤¤¡£printf¤Î¥ï¥¤¥ÉÈǤÏswprintf()¤ÇÊÌʪ¡£
*** ´Ø¿ô¥Ý¥¤¥ó¥¿
¥Ý¥¤¥ó¥¿¤Î¥¢¥¹¥¿¡¼¤ÎÁ°¤Ë¸Æ¤Ó½Ð¤·µ¬Ìó¤ò½ñ¤¯¡£
int(_stdcall *p)(int, int) = test;
´Êñ¤Ê³ÎǧÊýË¡¤È¤·¤Æ¡¢·¿¿äÏÀ¤µ¤»¤Æ¥Ä¡¼¥ë¥Á¥Ã¥×¤Ë½Ð¤¹ÊýË¡¤¬¤¢¤ë¡£
auto p = test;
¾åÎã¤Îp¤Ë¥Þ¥¦¥¹¥Ý¥¤¥ó¥¿¤òÅö¤Æ¤Æ¥Ä¡¼¥ë¥Á¥Ã¥×¤ò³Îǧ¤¹¤ë¡£
- ½èÍý·Ï¤Ë¤è¤Ã¤Æµ¬Ì󤬰ۤʤ롣VC++¤Ègcc¤ÏƱ¤¸¡£
- Borland·Ï¤Ç¤Ï¤è¤¯»È¤ï¤ì¤Æ¤¤¤¿¡£
- VC++¤Ç¤ÏºÇ½é¤Î2¤Ä¤Î°ú¿ô¤òECX, EDX¡¢»Ä¤ê¤ò¥¹¥¿¥Ã¥¯¤ÇÅϤ¹¡£
- ¥¹¥¿¥Ã¥¯¤Ï¸Æ¤Ó½Ð¤µ¤ì¤¿Â¦¤ÇÌ᤹¡£
; test(2, 3);
mov edx, 3
mov ecx, 2
call _test
_test:
mov eax, ecx add eax, edx ret
- °ú¿ô¤¬¥¼¥í¤Î¤È¤¤Ïcdecl¤ÈƱ¤¸
- ²ÄÊÑĹ°ú¿ô¤¬»È¤¨¤Ê¤¤
- °ú¿ô¤ò¥ì¥¸¥¹¥¿ÅϤ·¤¹¤ë¤Î¤ÏRISC¤äx64¤Ë»÷¤Æ¤¤¤ë
- ¥¤¥ó¥¹¥¿¥ó¥¹¥á¥ó¥Ð´Ø¿ô¤Î¸Æ¤Ó½Ð¤·µ¬Ìó
- ½èÍý·Ï¤Ë¤è¤Ã¤Æµ¬Ì󤬰ۤʤë
- VC++¤Ç¤Ïthis¥Ý¥¤¥ó¥¿¤òECX¡¢°ú¿ô¤ò¥¹¥¿¥Ã¥¯¤ÇÅϤ¹¡£
- ¥¹¥¿¥Ã¥¯¤Ï¸Æ¤Ó½Ð¤µ¤ì¤¿Â¦¤ÇÌ᤹¡£²ÄÊÑĹ°ú¿ô¤Ï¸Æ¤Ó½Ð¤·¤¿Â¦¤ÇÌ᤹¡£
; reinterpret_cast<Test *>(2)->test(3);
mov ecx, 2
push 3
call ?test@Test@@QAEHH@Z
; struct Test { int test(int a) { return a; } };
?test@Test@@QAEHH@Z:
mov eax, [esp+4] ret 4
- g++¤ÏºÇ½é¤Î°ú¿ô¤È¤·¤Æthis¤òÅϤ¹cdecl
- int Test::foo(int a) ð int foo(Test *this, int a)
- ¸å½Ò¤Îthiscall¤ËÂФ¹¤ë¥µ¥ó¥¯¤ÏÊ̤˼ÂÁõ¤¹¤ëɬÍפ¬¤¢¤ë
; reinterpret_cast<Test *>(2)->test(3);
push 3
push 2
call __ZN4Test4testEi
add esp, 8
; struct Test { int test(int a) { return a; } };
__ZN4Test4testEi:
mov eax, [esp+8] ret
[Ìä] stdcall¤Î´Ø¿ô¤ò¥µ¥ó¥¯¤Çcdecl¤ËÊÑ´¹¤·¤Æ¤¯¤À¤µ¤¤¡£
¶ñÂÎŪ¤Ë¤Ï¡¢°Ê²¼¤ÎConv¤òXbyak¤Ç¼ÂÁõ¤·¤Æ¤¯¤À¤µ¤¤¡£
#include <stdio.h> #include "xbyak/xbyak.h" void call(int(*p)(int, int), int a, int b) { printf("%d\n", p(a, b)); } int _stdcall test(int a, int b) { return a + b; } int main() { Conv c(test); auto f = reinterpret_cast<int(*)(int, int)>( const_cast<Xbyak::uint8 *>(c.getCode())); call(f, 2, 3); }
²óÅúÎã
struct Conv : public Xbyak::CodeGenerator { Conv(int(_stdcall *p)(int, int)) { push(ptr[esp+8]); push(ptr[esp+8]); call(p); ret(); } };
´Ø¿ô¤òÅϤ·¤Æ¸Æ¤Ö¡£
#include <stdio.h> void test(int a) { printf("%d\n", a); } int main() { auto f = test; f(1); }
static¥á¥ó¥Ð¤âƱ¤¸¤è¤¦¤Ë°·¤¨¤ë¡£
#include <stdio.h> struct Test { static void show(int n) { printf("%d\n", n); } }; int main() { auto f = Test::show; f(1); }
·¿¤¬Æ±¤¸¤Ê¤Î¤Ç¡¢Æ±¤¸´Ø¿ô¤ËÅϤ·¤Æ¸Æ¤Ó½Ð¤»¤ë¡£
#include <stdio.h> void test(int a) { printf("%d\n", a); } struct Test { static void show(int n) { printf("%d\n", n); } }; void call(void (*f)(int), int a) { f(a); } int main() { call(test, 1); call(Test::show, 1); }
¹½Ê¸¤¬Ìñ²ð¡£
#include <stdio.h> struct Test { int n; Test(int n) : n(n) {} void show() { printf("%d\n", n); } }; int main() { Test t(1); auto f = &Test::show; (t.*f)(); }
auto¤¬¤Ê¤¤¤ÈÈó¾ï¤ËÌÌÅÝ¡£
void (Test::*f)() = &Test::show;
Èó¥á¥ó¥Ð´Ø¿ô¤Î¥Ý¥¤¥ó¥¿¤ò¼è¤ë¤È¤¤Ë¤Ï & ¤¬¾Êά¤Ç¤¤ë¤¬¡¢
¥á¥ó¥Ð´Ø¿ô¤Ç¤Ï¾Êά¤Ç¤¤Ê¤¤¡£
²¼¤ÎÎã¤Ç¤Ïf1¤Èf2¤ÏƱ¤¸¡£
void test(); struct Test { void test(); } t; ¡û auto f1 = test; ¡û auto f2 = &test; ¡ß auto f3 = Test::test; ¡û auto f4 = &Test::test;
¸Æ¤Ó½Ð¤·»þ¤Î»²¾ÈÇí¤¬¤·¤Ë¤Ä¤¤¤Æ¤âƱÍÍ¡£
¤È¤¤¤¦¤è¤êC++¤Ç¤Ï .* ¤Ç1¤Ä¤Î±é»»»Ò¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤·¡¢
¤½¤¦¤Ç¤Ê¤¤¤È¤¿¤À¤Î¥á¥ó¥Ð¥¢¥¯¥»¥¹¤È¶èÊ̤¬ÉÕ¤«¤Ê¤¤¡£
¡û f2(); ¡û (*f2)(); ¡ß (t.f4)(); ¡û (t.*f4)();
static¤ÎÍ̵¤Ç¸ß´¹À¤¬¤Ê¤¯¤Ê¤ë¡£·¿¤â¥¯¥é¥¹¤Ë°Í¸¤¹¤ë¡£
https://gist.github.com/1273084
#include <stdio.h> struct Test1 { int n; Test1(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test2 { int n; Test2(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test3 { static void show() { printf("?\n"); } }; void show() { printf("!\n"); } void call(void (*f)()) { f(); } int main() { Test1 t1(1); Test2 t2(2); auto f1 = &Test1::show; auto f2 = &Test2::show; auto f3 = &Test3::show; auto f4 = &show; (t1.*f1)(); (t2.*f2)(); (*f3)(); (*f4)(); call(f3); call(f4); }
f1 != f2 != (f3 == f4)
- ¥¤¥ó¥¹¥¿¥ó¥¹¥á¥ó¥Ð¤È¥¯¥é¥¹¥á¥ó¥Ð¤Ï°·¤¤¤¬°Û¤Ê¤ë¡£
- ¥¯¥é¥¹¥á¥ó¥Ð¡Êstatic¡Ë¤ÈÈó¥á¥ó¥Ð¤ÏƱ¤¸°·¤¤¡£Æ±¤¸¤è¤¦¤Ëcall()¤ËÅϤ»¤ë¡£
- ¥¤¥ó¥¹¥¿¥ó¥¹¥á¥ó¥Ð¤Ï·¿¤Ë¥¯¥é¥¹Ì¾¤¬Æþ¤ë¤¿¤á¡¢f1¤Èf2¤Ï·¿¤¬°Û¤Ê¤ë¡£
¤È¤ê¤¢¤¨¤ºÆ±¤¸·¿¤È¤·¤Æ°·¤¦¤Ë¤Ï¤É¤¦¤¹¤ë¤«¡£
´Ø¿ô¤Î¤è¤¦¤Ë¿¶Éñ¤¦¥¯¥é¥¹¡£
#include <stdio.h> struct Test { int n; Test(int n) : n(n) {} void operator()() { printf("%d\n", n); } }; int main() { Test t(1); t(); }
C++11¤Ç¤Ï¥é¥à¥À¼°¤Ë¤è¤ê´Êñ¤Ë´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤¬ºî¤ì¤ë¡£
°Ê²¼¤Ît¤Ï¥é¥à¥À¼°¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¡£
#include <stdio.h> int main() { int n = 1; auto t = [n] { printf("%d\n", n); }; t(); }
ɸ½à¥é¥¤¥Ö¥é¥ê¤Ë¤Ï std::function ¤È¤¤¤¦
´Ø¿ô¥Ý¥¤¥ó¥¿¤Î¤è¤¦¤Ë»È¤¦´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤¬¤¢¤ë¡£
std::bind()¤ä¥é¥à¥À¼°¤Ê¤É¤Ç¥á¥ó¥Ð´Ø¿ô¤òÅϤ»¤ë¡£
¤³¤ì¤ò»È¤¦¤È¥á¥ó¥Ð¡¦Èó¥á¥ó¥Ð¤òÅý¹ç¤·¤Æ°·¤¨¤ë¤è¤¦¤Ë¤Ê¤ë¡£
https://gist.github.com/1273115
#include <functional> #include <stdio.h> struct Test1 { int n; Test1(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test2 { int n; Test2(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test3 { static void show() { printf("?\n"); } }; void show() { printf("!\n"); } void call(const std::function<void()> &f) { f(); } int main() { Test1 t1(1); Test2 t2(2); auto f1 = std::bind(&Test1::show, &t1); auto f2 = [&] { t2.show(); }; auto f3 = Test3::show; auto f4 = show; call(f1); call(f2); call(f3); call(f4); }
*** ¤ª¤Þ¤±
Èæ³Ó¤Î¤¿¤áF#¤Ë°Ü¿¢¡£
type Test1(n) = member x.show() = printfn "%d" n type Test2(n) = member x.show() = printfn "%d" n type Test3 = static member show() = printfn "?" let show() = printfn "!" let call f = f() let t1 = new Test1(1) let t2 = new Test2(2) let d1 = t1.show let d2 = fun() -> t2.show() let d3 = Test3.show let d4 = show call d1 call d2 call d3 call d4
d1, d2, d3, d4¤Ï¤¹¤Ù¤ÆƱ¤¸·¿: unit->unit
¥³¡¼¥É¤¬C++¤ÇÊĤ¸¤Æ¤¤¤ë¤Ê¤é´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤Ç½¼Ê¬¡£
¤·¤«¤·OS¤ÎAPI¤Ç´Ø¿ô¥Ý¥¤¥ó¥¿·¿¤¬»ØÄꤵ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ê¤É¡¢
´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤ò¤½¤Î¤Þ¤Þ»È¤¨¤Ê¤¤¥±¡¼¥¹¤¬¤¢¤ë¡£
JIT¤Ç¥é¥Ã¥Ñ¡¼¤òºî¤Ã¤Æ¤·¤Þ¤¨¤Ð²ò·è¡ª
https://gist.github.com/1225997
#include <stdio.h> #include "xbyak/xbyak.h" template <class T> struct Delegate : public Xbyak::CodeGenerator { Delegate(T *t, void (T::*p)()) { mov(ecx, reinterpret_cast<intptr_t>(t)); jmp(*reinterpret_cast<void **>(&p)); } void (*getPtr())() { return reinterpret_cast<void (*)()>( const_cast<Xbyak::uint8 *>(getCode())); } }; struct Test1 { int n; Test1(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test2 { int n; Test2(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test3 { static void show() { printf("?\n"); } }; void show() { printf("!\n"); } void call(void (*f)()) { f(); } int main() { Test1 t1(1); Test2 t2(2); Delegate<Test1> d1(&t1, &Test1::show); Delegate<Test2> d2(&t2, &Test2::show); call(d1.getPtr()); call(d2.getPtr()); call(Test3::show); call(show); }
- ¥á¥ó¥Ð´Ø¿ô¥Ý¥¤¥ó¥¿¤Ë¥¤¥ó¥¹¥¿¥ó¥¹¤òËä¤á¹þ¤ó¤Ç´Ø¿ô¥Ý¥¤¥ó¥¿¤ËÊÑ´¹¡£
- ¤³¤ÎJIT¥é¥Ã¥Ñ¡¼¤¬º£²ó¤Î¥á¥¤¥ó¥Æ¡¼¥Þ¤Ç¤¢¤ë¥µ¥ó¥¯¡£
- gcc¤Ç¤Ïthiscall¤¬°Û¤Ê¤ë¤¿¤á¤½¤Î¤Þ¤Þ¤Ç¤ÏÆ°¤«¤Ê¤¤¡£
*** ´Ø¿ô¥Ý¥¤¥ó¥¿¤òÊÖ¤¹´Ø¿ô
void (*getPtr())();
- getPtr() ¤¬´Ø¿ô̾¤È°ú¿ô¤Ç¡¢¤½¤ì°Ê³°¤Î void (*)() ¤¬Ìá¤êÃͤη¿¡£
- void (*f)() ¤ÏÊÑ¿ô¤Ç¡¢f¤ÎÉôʬ¤Ë°ú¿ô¤òÉÕ¤±¤¿¤é´Ø¿ô¡£
VC++¤Îthiscall¤Ç¤Ï¸Æ¤Ó½Ð¤·À褬°ú¿ô¤Î¥¹¥¿¥Ã¥¯¤òÊÒÉÕ¤±¤ë¤¿¤á¡¢
¥µ¥ó¥¯¤Ç¤Ïcdecl¤È¤ÎÊÑ´¹¤¬É¬ÍפȤʤ롣
https://gist.github.com/1273062
#include <stdio.h> #include "xbyak/xbyak.h" template <class T, class TA1> struct Thunk : public Xbyak::CodeGenerator { Thunk(T *t, void (T::*p)(TA1)) { mov(ecx, reinterpret_cast<intptr_t>(t)); push(ptr[esp+4]); call(*reinterpret_cast<void **>(&p)); ret(); } void (*getPtr())(TA1) { return reinterpret_cast<void (*)(TA1)>( const_cast<Xbyak::uint8 *>(getCode())); } }; struct Test { int n; Test(int n) : n(n) {} void show(int n2) { printf("%d, %d\n", n, n2); } }; void show(int n) { printf("%d\n", n); } void call(void (*f)(int), int n) { f(n); } int main() { Test t(1); Thunk<Test, int> thunk(&t, &Test::show); call(thunk.getPtr(), 2); call(show, 3); }
void (*getPtr())(TA1)
- getPtr()¤¬´Ø¿ô̾¤È°ú¿ô
- ¤½¤ì°Ê³°¤Î void (*)(TA1) ¤¬Ìá¤êÃͤη¿
¥µ¥ó¥¯¤Ë°ú¿ô¤òËä¤á¹þ¤á¤ÐÉôʬŬÍѤ¬²Äǽ¡£
#include <stdio.h> #include "xbyak/xbyak.h" struct Bind : public Xbyak::CodeGenerator { Bind(int(*f)(int, int), int a) { push(a); push(ptr[esp+8]); call(reinterpret_cast<void *>(f)); add(esp, 8); ret(); } int(*getPtr())(int) { return reinterpret_cast<int(*)(int)>( const_cast<Xbyak::uint8 *>(getCode())); } }; int add(int a, int b) { return a + b; } void call(int(*p)(int), int a) { printf("%d\n", p(a)); } int main() { Bind inc(add, 1); call(inc.getPtr(), 2); }
¤·¤«¤·¤³¤ì¤Ï¤ä¤í¤¦¤È»×¤¨¤Ð½ÐÍè¤ë¡¢ÄøÅ٤Υͥ¿¡£
std::bind¤ÇÉôʬŬÍѤ·¤Æ¤«¤é¥µ¥ó¥¯¤ËÆþ¤ì¤¿Êý¤¬¥¹¥Þ¡¼¥È¡£
#include <functional> #include <stdio.h> #include "xbyak/xbyak.h" template <class T, class TA1, class TR> struct Thunk : public Xbyak::CodeGenerator { Thunk(T *f) { mov(ecx, reinterpret_cast<intptr_t>(f)); push(ptr[esp+4]); auto p = &T::operator(); call(*reinterpret_cast<void **>(&p)); ret(); } TR(*getPtr())(TA1) { return reinterpret_cast<TR(*)(TA1)>( const_cast<Xbyak::uint8 *>(getCode())); } }; int add(int a, int b) { return a + b; } void call(int(*p)(int), int a) { printf("%d\n", p(a)); } int main() { std::function<int(int)> inc = std::bind(add, std::placeholders::_1, 1); Thunk<decltype(inc), int, int> thunk(&inc); call(thunk.getPtr(), 2); }
¤³¤Î¤è¤¦¤Ë²Äǽ¤Ê¸Â¤êC++¤ÎÈÏ°ÏÆâ¤Ç°·¤Ã¤Æ¡¢¥µ¥ó¥¯¤ÏºÇ½ª¼êÃÊ¡£
¥¥ã¥×¥Á¥ã¤òÉôʬŬÍѤÇɽ¸½¤¹¤ì¤Ð¡¢¥µ¥ó¥¯¤Ç¥¯¥í¡¼¥¸¥ã¤¬ºî¤ì¤ë¡£
https://gist.github.com/1226147
#include <functional> #include <stdio.h> #include "xbyak/xbyak.h" void call(void (*f)()) { f(); } int main() { int a = 1; struct _ : public Xbyak::CodeGenerator { _(int *a) { push(reinterpret_cast<intptr_t>(a)); call(reinterpret_cast<void *>(run)); add(esp, 4); ret(); } static void run(int &a) { printf("%d\n", a++); } } closure(&a); auto f = reinterpret_cast<void (*)()>( const_cast<Xbyak::uint8 *>(closure.getCode())); f(); f(); call(f); }
¤³¤ì¤ÏÆȼ«¤Ë¸À¸ì¤òºî¤ë¾ì¹ç¤Ï»È¤¨¤ë¼êË¡¤À¤È»×¤¦¤¬¡¢
¸À¸ì»ÅÍͤǥ¯¥í¡¼¥¸¥ã¤ò»ý¤ÄC++11¤Ç´º¤¨¤Æ¤ä¤ë°ÕÌ£¤ÏÇö¤¤¡£
ÉáÄ̤ËC++¤Çºî¤Ã¤¿¥¯¥í¡¼¥¸¥ã¤ò¥µ¥ó¥¯¤ÇÊñ¤ó¤ÀÊý¤¬¥·¥ó¥×¥ë¡£
https://gist.github.com/1273073
#include <functional> #include <stdio.h> #include "xbyak/xbyak.h" template <class T> struct Thunk : public Xbyak::CodeGenerator { Thunk(T *f) { mov(ecx, reinterpret_cast<intptr_t>(f)); auto p = &T::operator(); jmp(*reinterpret_cast<void **>(&p)); } void (*getPtr())() { return reinterpret_cast<void (*)()>( const_cast<Xbyak::uint8 *>(getCode())); } }; void call(void (*f)()) { f(); } int main() { int a = 1; auto f = [&] { printf("%d\n", a++); }; f(); f(); Thunk<decltype(f)> thunk(&f); auto f2 = thunk.getPtr(); f2(); call(f2); }
[Ìä] Windows¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¿÷·Á¤ò²þ¤¤·¤Æ¡¢°Ê²¼¤ò¥á¥ó¥Ð´Ø¿ô¤Ë¤·¤Æ¤¯¤À¤µ¤¤¡£
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
¢
class Window {
public:
ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);};
- ¥á¥ó¥Ð¤ÏŬµ¹Äɲ䷤Ƥ¯¤À¤µ¤¤¡£
- CALLBACK¤Ïstdcall¤ò°ÕÌ£¤·¤Þ¤¹¡£
https://gist.github.com/1226294
--- win32thunk.cpp.orig +++ win32thunk.cpp @@ -3,6 +3,7 @@ #include "stdafx.h" #include "win32thunk.h" +#include "xbyak/xbyak.h" #define MAX_LOADSTRING 100 @@ -12,11 +13,25 @@ TCHAR szWindowClass[MAX_LOADSTRING]; // ¥á¥¤¥ó ¥¦¥£¥ó¥É¥¦ ¥¯¥é¥¹Ì¾ // ¤³¤Î¥³¡¼¥É ¥â¥¸¥å¡¼¥ë¤Ë´Þ¤Þ¤ì¤ë´Ø¿ô¤ÎÀë¸À¤òžÁ÷¤·¤Þ¤¹: -ATOM MyRegisterClass(HINSTANCE hInstance); -BOOL InitInstance(HINSTANCE, int); -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); +template <class T, class TA1, class TA2, class TA3, class TA4, class TR> +struct StdCallThunk : public Xbyak::CodeGenerator { + void init(T *t, TR(T::*p)(TA1, TA2, TA3, TA4)) { + mov(ecx, reinterpret_cast<intptr_t>(t)); + jmp(*reinterpret_cast<void **>(&p)); + } +}; + +class Window { +protected: + StdCallThunk<Window, HWND, UINT, WPARAM, LPARAM, LRESULT> wndProc; +public: + ATOM MyRegisterClass(HINSTANCE hInstance); + BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); + LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +}; + int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, @@ -32,10 +47,11 @@ // ¥°¥í¡¼¥Ð¥ëʸ»úÎó¤ò½é´ü²½¤·¤Æ¤¤¤Þ¤¹¡£ LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_WIN32THUNK, szWindowClass, MAX_LOADSTRING); - MyRegisterClass(hInstance); + Window win; + win.MyRegisterClass(hInstance); // ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î½é´ü²½¤ò¼Â¹Ô¤·¤Þ¤¹: - if (!InitInstance (hInstance, nCmdShow)) + if (!win.InitInstance (hInstance, nCmdShow)) { return FALSE; } @@ -70,14 +86,16 @@ // Àµ¤·¤¤·Á¼°¤Î¾®¤µ¤¤¥¢¥¤¥³¥ó¤ò¼èÆÀ¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¤Ë¤Ï¡¢ // ¤³¤Î´Ø¿ô¤ò¸Æ¤Ó½Ð¤·¤Æ¤¯¤À¤µ¤¤¡£ // -ATOM MyRegisterClass(HINSTANCE hInstance) +ATOM Window::MyRegisterClass(HINSTANCE hInstance) { + wndProc.init(this, &Window::WndProc); + WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = WndProc; + wcex.lpfnWndProc = (WNDPROC)wndProc.getCode(); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; @@ -101,7 +119,7 @@ // ¤³¤Î´Ø¿ô¤Ç¡¢¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤Ç¥¤¥ó¥¹¥¿¥ó¥¹ ¥Ï¥ó¥É¥ë¤òÊݸ¤·¡¢ // ¥á¥¤¥ó ¥×¥í¥°¥é¥à ¥¦¥£¥ó¥É¥¦¤òºîÀ®¤ª¤è¤Óɽ¼¨¤·¤Þ¤¹¡£ // -BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +BOOL Window::InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; @@ -131,7 +149,7 @@ // WM_DESTROY - Ãæ»ß¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤·¤ÆÌá¤ë // // -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +LRESULT Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps;
¥¤¥Ù¥ó¥È¥Ï¥ó¥É¥é¤ò´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È²½¤·¤Æ°Ñ¾ù¥â¥Ç¥ë²½¡£
- ¥Ï¥ó¥É¥ë¤Ï¤¢¤Á¤³¤Á¤Ç»È¤¦¤Î¤Ç¡¢Window¥¯¥é¥¹¤Îpublic¥á¥ó¥Ð¤ËÄɲá£
- Window::InitInstance()¤Ç¥í¡¼¥«¥ëÊÑ¿ô¤ÎÀë¸À¤òºï½ü¡£
¤³¤ì¤Ç¼«Æ°Åª¤Ë¥á¥ó¥Ð¤ÎÊý¤ËÂåÆþ¤µ¤ì¤ë¡£
--- win32thunk.cpp.orig +++ win32thunk.cpp @@ -27,6 +27,7 @@ protected: StdCallThunk<Window, HWND, UINT, WPARAM, LPARAM, LRESULT> wndProc; public: + HWND hWnd; ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); @@ -121,8 +122,6 @@ // BOOL Window::InitInstance(HINSTANCE hInstance, int nCmdShow) { - HWND hWnd; - hInst = hInstance; // ¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤Ë¥¤¥ó¥¹¥¿¥ó¥¹½èÍý¤ò³ÊǼ¤·¤Þ¤¹¡£ hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
WM_COMMAND¤ò°Ñ¾ù²½
¤¢¤Þ¤ê½¤Àµ¤·¤Ê¤¤¥Ø¥Ã¥À¤Ïstdafx.h¤Ë²¡¤·¹þ¤à¤È¥Ó¥ë¥É¤¬Â®¤¯¤Ê¤ë¡£
// TODO: ¥×¥í¥°¥é¥à¤ËɬÍפÊÄɲåإåÀ¡¼¤ò¤³¤³¤Ç»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£ +#include <list> +#include <functional> +#include "xbyak/xbyak.h"
Window¥¯¥é¥¹¤Îpublic¥á¥ó¥Ð¤ËÄɲÃ
¢¨list¤ËÆþ¤ì¤ë¤³¤È¤Ç¥Þ¥ë¥Á¥¥ã¥¹¥È¤ò²Äǽ¤Ë¤·¤Æ¤¤¤ë¡£
std::list<std::function<bool(int, int)>> Command;
Window::WndProc¤ÇÂбþ
¢¨for each¤ÏVC++¤ÎÆȼ«³ÈÄ¥¤Ê¤Î¤Ç¡¢Å¬µ¹½¤Àµ¤·¤Æ¤¯¤À¤µ¤¤¡£
case WM_COMMAND: for each (auto f in Command) if (f(LOWORD(wParam), HIWORD(wParam))) return 0; return DefWindowProc(hWnd, message, wParam, lParam);
¥¤¥Ù¥ó¥È¤òÀßÄê
win.Command.push_back([&](int id, int e)->bool { // ÁªÂò¤µ¤ì¤¿¥á¥Ë¥å¡¼¤Î²òÀÏ: switch (id) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), win.hWnd, About); return true; case IDM_EXIT: DestroyWindow(win.hWnd); return true; } return false; });
WM_PAINT¤ò°Ñ¾ù²½
Window¥¯¥é¥¹¤Îpublic¥á¥ó¥Ð¤ËÄɲÃ
std::list<std::function<void(HDC)>> Paint;
Window::WndProc¤ÇÂбþ
case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: ÉÁ²è¥³¡¼¥É¤ò¤³¤³¤ËÄɲ䷤Ƥ¯¤À¤µ¤¤... for each (auto f in Paint) f(hdc); EndPaint(hWnd, &ps); break;
¥¤¥Ù¥ó¥È¤òÀßÄê
win.Paint.push_back([&](HDC hdc) { auto oldPen = (HPEN)SelectObject(hdc, GetStockObject(BLACK_PEN)); auto oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(GRAY_BRUSH)); Rectangle(hdc, 10, 10, 40, 40); SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); });
»Í³Ñ¤¬É½¼¨¤µ¤ì¤ë¡£
¥Þ¥¦¥¹¥Ü¥¿¥ó´Ø·¸¤Î¥á¥Ã¥»¡¼¥¸¤ò°Ñ¾ù²½¡£
stdafx.h¤ËÄɲÃ
#include <windowsx.h>
Window¥¯¥é¥¹¤Îpublic¥á¥ó¥Ð¤ËÄɲÃ
std::list<std::function<void(int, int, int, WPARAM)>> MouseDown, MouseUp; std::list<std::function<void(int, int, WPARAM)>> MouseMove;
Window¥¯¥é¥¹¤Îprotected¥á¥ó¥Ð¤ËÄɲÃ
void OnMouseDown(int button, WPARAM wParam, LPARAM lParam) { int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); for each (auto f in MouseDown) f(button, x, y, wParam); } void OnMouseUp(int button, WPARAM wParam, LPARAM lParam) { int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); for each (auto f in MouseUp) f(button, x, y, wParam); }
Window::WndProc¤ÇÂбþ
case WM_LBUTTONDOWN: OnMouseDown(1, wParam, lParam); break; case WM_RBUTTONDOWN: OnMouseDown(2, wParam, lParam); break; case WM_MBUTTONDOWN: OnMouseDown(3, wParam, lParam); break; case WM_XBUTTONDOWN: OnMouseDown(3 + HIWORD(wParam), LOWORD(wParam), lParam); break; case WM_LBUTTONUP: OnMouseUp(1, wParam, lParam); break; case WM_RBUTTONUP: OnMouseUp(2, wParam, lParam); break; case WM_MBUTTONUP: OnMouseUp(3, wParam, lParam); break; case WM_XBUTTONUP: OnMouseUp(3 + HIWORD(wParam), LOWORD(wParam), lParam); break; case WM_MOUSEMOVE: for each (auto f in MouseMove) f(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), wParam); break;
¤³¤³¤Þ¤Ç¤Î¥½¡¼¥¹¡£
https://gist.github.com/1273003
¤Á¤ç¤Ã¤ÈŤ¤¤Î¤Ç¡¢¥½¡¼¥¹¤òʬ³ä¤·¤ÆÀ°Íý¡£
https://gist.github.com/1274679
Window.h
#pragma once #include <list> #include <functional> #include <string> #include <windows.h> #include "xbyak/xbyak.h" template <class T, class TA1, class TA2, class TA3, class TA4, class TR> struct StdCallThunk : public Xbyak::CodeGenerator { void init(T *t, TR(T::*p)(TA1, TA2, TA3, TA4)) { mov(ecx, reinterpret_cast<intptr_t>(t)); jmp(*reinterpret_cast<void **>(&p)); } }; typedef std::basic_string<TCHAR> tstring; class Window { protected: HINSTANCE hInst; tstring windowClass; StdCallThunk<Window, HWND, UINT, WPARAM, LPARAM, LRESULT> wndProc; void OnMouseDown(int button, WPARAM wParam, LPARAM lParam); void OnMouseUp(int button, WPARAM wParam, LPARAM lParam); public: HWND hWnd; ATOM MyRegisterClass(HINSTANCE hInstance, const tstring &windowClass); BOOL InitInstance(const tstring &title, int nCmdShow); LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); std::list<std::function<bool(int, int)>> Command; std::list<std::function<void(HDC)>> Paint; std::list<std::function<void(int, int, int, WPARAM)>> MouseDown, MouseUp; std::list<std::function<void(int, int, WPARAM)>> MouseMove; };
Window.cpp
#include "stdafx.h" #include "resource.h" void Window::OnMouseDown(int button, WPARAM wParam, LPARAM lParam) { int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); for each (auto f in MouseDown) f(button, x, y, wParam); } void Window::OnMouseUp(int button, WPARAM wParam, LPARAM lParam) { int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); for each (auto f in MouseUp) f(button, x, y, wParam); } // // ´Ø¿ô: Window::MyRegisterClass() // // ÌÜŪ: ¥¦¥£¥ó¥É¥¦ ¥¯¥é¥¹¤òÅÐÏ¿¤·¤Þ¤¹¡£ // // ¥³¥á¥ó¥È: // // ¤³¤Î´Ø¿ô¤ª¤è¤Ó»È¤¤Êý¤Ï¡¢'RegisterClassEx' ´Ø¿ô¤¬Äɲ䵤줿 // Windows 95 ¤è¤êÁ°¤Î Win32 ¥·¥¹¥Æ¥à¤È¸ß´¹¤µ¤»¤ë¾ì¹ç¤Ë¤Î¤ßɬÍפǤ¹¡£ // ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤¬¡¢´ØÏ¢ÉÕ¤±¤é¤ì¤¿ // Àµ¤·¤¤·Á¼°¤Î¾®¤µ¤¤¥¢¥¤¥³¥ó¤ò¼èÆÀ¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¤Ë¤Ï¡¢ // ¤³¤Î´Ø¿ô¤ò¸Æ¤Ó½Ð¤·¤Æ¤¯¤À¤µ¤¤¡£ // ATOM Window::MyRegisterClass(HINSTANCE hInstance, const tstring &windowClass) { hInst = hInstance; this->windowClass = windowClass; wndProc.init(this, &Window::WndProc); WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)wndProc.getCode(); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32THUNK)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32THUNK); wcex.lpszClassName = windowClass.c_str(); wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // // ´Ø¿ô: Window::InitInstance(HINSTANCE, int) // // ÌÜŪ: ¥¤¥ó¥¹¥¿¥ó¥¹ ¥Ï¥ó¥É¥ë¤òÊݸ¤·¤Æ¡¢¥á¥¤¥ó ¥¦¥£¥ó¥É¥¦¤òºîÀ®¤·¤Þ¤¹¡£ // // ¥³¥á¥ó¥È: // // ¤³¤Î´Ø¿ô¤Ç¡¢¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤Ç¥¤¥ó¥¹¥¿¥ó¥¹ ¥Ï¥ó¥É¥ë¤òÊݸ¤·¡¢ // ¥á¥¤¥ó ¥×¥í¥°¥é¥à ¥¦¥£¥ó¥É¥¦¤òºîÀ®¤ª¤è¤Óɽ¼¨¤·¤Þ¤¹¡£ // BOOL Window::InitInstance(const tstring &title, int nCmdShow) { hWnd = CreateWindow(windowClass.c_str(), title.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // ´Ø¿ô: Window::WndProc(HWND, UINT, WPARAM, LPARAM) // // ÌÜŪ: ¥á¥¤¥ó ¥¦¥£¥ó¥É¥¦¤Î¥á¥Ã¥»¡¼¥¸¤ò½èÍý¤·¤Þ¤¹¡£ // // WM_COMMAND - ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó ¥á¥Ë¥å¡¼¤Î½èÍý // WM_PAINT - ¥á¥¤¥ó ¥¦¥£¥ó¥É¥¦¤ÎÉÁ²è // WM_DESTROY - Ãæ»ß¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤·¤ÆÌá¤ë // // LRESULT Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: for each (auto f in Command) if (f(LOWORD(wParam), HIWORD(wParam))) return 0; return DefWindowProc(hWnd, message, wParam, lParam); case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: ÉÁ²è¥³¡¼¥É¤ò¤³¤³¤ËÄɲ䷤Ƥ¯¤À¤µ¤¤... for each (auto f in Paint) f(hdc); EndPaint(hWnd, &ps); break; case WM_LBUTTONDOWN: OnMouseDown(1, wParam, lParam); break; case WM_RBUTTONDOWN: OnMouseDown(2, wParam, lParam); break; case WM_MBUTTONDOWN: OnMouseDown(3, wParam, lParam); break; case WM_XBUTTONDOWN: OnMouseDown(3 + HIWORD(wParam), LOWORD(wParam), lParam); break; case WM_LBUTTONUP: OnMouseUp(1, wParam, lParam); break; case WM_RBUTTONUP: OnMouseUp(2, wParam, lParam); break; case WM_MBUTTONUP: OnMouseUp(3, wParam, lParam); break; case WM_XBUTTONUP: OnMouseUp(3 + HIWORD(wParam), LOWORD(wParam), lParam); break; case WM_MOUSEMOVE: for each (auto f in MouseMove) f(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), wParam); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
win32thunk.cpp (¥×¥í¥¸¥§¥¯¥È̾¤Ë¤è¤ê°Û¤Ê¤ë)
// win32thunk.cpp : ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¥¨¥ó¥È¥ê ¥Ý¥¤¥ó¥È¤òÄêµÁ¤·¤Þ¤¹¡£ // #include "stdafx.h" #include "win32thunk.h" static tstring LoadTString(HINSTANCE hInstance, UINT uID) { const int buflen = 256; TCHAR buf[buflen]; LoadString(hInstance, uID, buf, buflen); return buf; } // ¤³¤Î¥³¡¼¥É ¥â¥¸¥å¡¼¥ë¤Ë´Þ¤Þ¤ì¤ë´Ø¿ô¤ÎÀë¸À¤òžÁ÷¤·¤Þ¤¹: INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: ¤³¤³¤Ë¥³¡¼¥É¤òÁÞÆþ¤·¤Æ¤¯¤À¤µ¤¤¡£ MSG msg; HACCEL hAccelTable; Window win; win.MyRegisterClass(hInstance, LoadTString(hInstance, IDC_WIN32THUNK)); win.Command.push_back([&](int id, int e)->bool { // ÁªÂò¤µ¤ì¤¿¥á¥Ë¥å¡¼¤Î²òÀÏ: switch (id) { case IDM_ABOUT: DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), win.hWnd, About); return true; case IDM_EXIT: DestroyWindow(win.hWnd); return true; } return false; }); win.Paint.push_back([&](HDC hdc) { auto oldPen = (HPEN)SelectObject(hdc, GetStockObject(BLACK_PEN)); auto oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(GRAY_BRUSH)); Rectangle(hdc, 10, 10, 40, 40); SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); }); // ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î½é´ü²½¤ò¼Â¹Ô¤·¤Þ¤¹: if (!win.InitInstance(LoadTString(hInstance, IDS_APP_TITLE), nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32THUNK)); // ¥á¥¤¥ó ¥á¥Ã¥»¡¼¥¸ ¥ë¡¼¥×: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // ¥Ð¡¼¥¸¥ç¥ó¾ðÊó¥Ü¥Ã¥¯¥¹¤Î¥á¥Ã¥»¡¼¥¸ ¥Ï¥ó¥É¥é¡¼¤Ç¤¹¡£ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
¿§¡¹¤ÈÆͤùþ¤ß¤É¤³¤í¤Ï¤¢¤ë¤È»×¤¤¤Þ¤¹¤¬¡¢
º£²ó¤Ï¥¯¥é¥¹¥é¥¤¥Ö¥é¥ê¤òºî¤ë¤Î¤¬ÌÜŪ¤Ç¤Ï¤Ê¤¤¤Î¤Ç¡¢
ŬÅö¤Ë¸«Ä̤·¤òÎɤ¯¤¹¤ëÄøÅÙ¤Ëα¤á¤Æ¤¤¤Þ¤¹¡£
[Ìä] ÉÁ²è¤µ¤ì¤Æ¤¤¤ë»Í³Ñ¤ò¥É¥é¥Ã¥°¤ÇÆ°¤«¤»¤ë¤è¤¦¤Ë¤·¤Æ¤¯¤À¤µ¤¤¡£
¥Ò¥ó¥È
- ºÆÉÁ²èÍ×µá: InvalidateRect(hWnd, nullptr, true);
https://gist.github.com/1226666
POINT pb = { 10, 10 }; win.Paint.push_back([&](HDC hdc) { auto oldPen = (HPEN)SelectObject(hdc, GetStockObject(BLACK_PEN)); auto oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(GRAY_BRUSH)); Rectangle(hdc, pb.x, pb.y, pb.x + 40, pb.y + 40); SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); }); bool sel = false; POINT pd, pb2; win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { if (pb.x <= x && x <= pb.x + 40 && pb.y <= y && y <= pb.y + 40) { pd.x = x; pd.y = y; pb2 = pb; sel = true; } }); win.MouseMove.push_back([&](int x, int y, WPARAM) { if (sel) { pb.x = pb2.x + (x - pd.x); pb.y = pb2.y + (y - pd.y); InvalidateRect(win.hWnd, nullptr, true); } }); win.MouseUp.push_back([&](int, int, int, WPARAM) { sel = false; });
¼¡¤Î¤è¤¦¤Ê´Ø¿ô¤¬¤¢¤Ã¤¿¤È¤¹¤ë¡£
int test() { return 1; return 2; return 3; }
Ä̾ºÇ½é¤Îreturn°Ê¹ß¤ÏÅþã¤Ç¤¤Ê¤¤¥³¡¼¥É¤È¤·¤Æ°·¤ï¤ì¤ë¡£
¤³¤ì¤¬¤â¤·¡¢¸Æ¤Ð¤ì¤ëÅ٤˼¡¤Ë¿Ê¤à¤È¤·¤¿¤é¤É¤¦¤À¤í¤¦¤«¡£
printf("%d\n", test()); // 1 printf("%d\n", test()); // 2 printf("%d\n", test()); // 3
¤³¤Î¤è¤¦¤Ê¥â¥Ç¥ë¤ò¡Ö·Ñ³¡×¤È¸Æ¤Ó¡¢
·Ñ³¤ò´Þ¤à´Ø¿ô¤ò¥³¥ë¡¼¥Á¥ó¤È¸Æ¤Ö¡£
ñ½ã¤Ë¼ÂÁõ¤·¤¿¤À¤±¤À¤È¡¢°ìÅÙ¤·¤«¸Æ¤Ù¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¦¡£
¢¨¾å¤ÎÎã¤Ç¤ÏÆóÅÙ¤È1¤¬ÊÖ¤»¤Ê¤¯¤Ê¤ë¡£
¤½¤Î¤¿¤á´Ø¿ô¤ËÂФ¹¤ë¥¤¥ó¥¹¥¿¥ó¥¹¤È¤¤¤¦¹Í¤¨Êý¤òƳÆþ¤¹¤ë¡£
°Ê²¼¤Ïµ¼»÷¥³¡¼¥É¡£
auto t1 = new test; printf("%d\n", t1()); // 1 printf("%d\n", t1()); // 2 auto t2 = new test; printf("%d\n", t2()); // 1
C#¤Ç¤Ïyield¤È¤·¤Æ·Ñ³¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¡£
yield¤ò´Þ¤à¥á¥½¥Ã¥É¤Ï¥¤¥ó¥¹¥¿¥ó¥¹¤òÊÖ¤¹¡£
using System; using System.Collections.Generic; class Test { static IEnumerable<int> test() { yield return 1; yield return 2; yield return 3; } static void Main() { var t1 = test().GetEnumerator(); if (t1.MoveNext()) Console.WriteLine(t1.Current); if (t1.MoveNext()) Console.WriteLine(t1.Current); var t2 = test().GetEnumerator(); if (t2.MoveNext()) Console.WriteLine(t2.Current); } }
Python¤Ç¤Ï¥¸¥§¥Í¥ì¡¼¥¿¤È¸Æ¤Ð¤ì¤Æ¤¤¤ë¡£
def test(): yield 1 yield 2 yield 3 t1 = test() print t1.next() print t1.next() t2 = test() print t2.next()
C#/Python¤È¤â¤Ë¼Â¹Ô·ë²Ì¤Ï°Ê²¼¤ÎÄ̤ꡣ
·Ñ³¤ò¤É¤¦¼ÂÁõ¤¹¤ë¤«¤ò¸«¤Æ¤¤¤¯¡£
setjmp/longjmp¤Ç¥¹¥¿¥Ã¥¯¤ò´¬¤Ì᤹Îã¡£
#include <stdio.h> #include <setjmp.h> jmp_buf jb; int main() { if (setjmp(jb) == 0) { printf("setjmp\n"); printf("test\n"); longjmp(jb, 1); printf("never reach here\n"); } printf("longjmp done.\n"); }
- °ì¸«²áµî¤ËÌá¤Ã¤¿¤è¤¦¤Ë¸«¤¨¤ë¡£
- ¥ì¥¸¥¹¥¿¤òÌᤷ¤Æ³¹Ô¤¹¤ë¤À¤±¤Ç¡¢¾õÂÖ¤¬Êݸ¤µ¤ì¤Æ¤¤¤ë¤ï¤±¤Ç¤Ï¤Ê¤¤¡£
¼¡¤ÎÎã¤Ç¤Ï¤¿¤Þ¤¿¤Þ°ú¿ô¤Î¥¢¥É¥ì¥¹¤¬°ìÃפ·¤¿¤¿¤á¤¹¤êÂؤï¤ë¡£
#include <stdio.h> #include <setjmp.h> jmp_buf jb; void test1(const char *s) { setjmp(jb); printf("&s: %p, s: %p; %s\n", &s, s, s); } void test2(int a) { printf("&a: %p, a: %d\n", &a, a); longjmp(jb, 0); } int main() { test1("test"); test2(0); printf("end\n"); }
&s: 0013FE98, s: 00415758; test
&a: 0013FE98, a: 0
&s: 0013FE98, s: 00000000; (null)
end
- a¤ÎÃͤ¬¤½¤Î¤Þ¤Þs°·¤¤¤µ¤ì¤Æ³¹Ô¡£
- main()¤ÎÃæ¤Îή¤ì¤Ë¤Ï±Æ¶Á¤·¤Ê¤¤¡£
- ²áµî¤ËÌá¤Ã¤¿¤ï¤±¤Ç¤Ï¤Ê¤¤¤Î¤¬¤ï¤«¤ë¤È»×¤¦¡£
- ͽ´ü¤·¤Ê¤¤Æ°ºî¤ò°ú¤µ¯¤³¤¹²ÄǽÀ¤¬¤¢¤ë¤¿¤á´í¸±¡£
- ²¼°Ì¹½Â¤¤«¤é¾å°Ì¤ËÌá¤ë¤è¤¦¤Ê»È¤¤Êý¤¬¿ä¾©¤µ¤ì¤ë¡£
RAII¤Ï½èÍý·Ï°Í¸
#include <stdio.h> #include <setjmp.h> jmp_buf jb; class Test { const char *s; public: Test(const char *s) : s(s) {} ~Test() { printf("%s\n", s); } }; void test() { Test t1("t1"); longjmp(jb, 1); } int main() { Test t2("t2"); if (setjmp(jb) == 0) { Test t3("t3"); test(); } }
[VC++]
t1
t3
t2
[g++]
t2
¤³¤Î°ã¤¤¤Ï·Ñ³¤ò°·¤¦¾å¤ÇÌñ²ð¡£
- ½èÍý¤òÅÓÃæ¤ÇÈ´¤±¤ÆǤ°Õ¤ËºÆ³«¤Ç¤¤ë¹½Â¤¤ò¥³¥ë¡¼¥Á¥ó¤È¸Æ¤Ö¡£
- setjmp/longjmp¤ò¸ò¸ß¤Ë¸Æ¤Ù¤Ð¥³¥ë¡¼¥Á¥ó¤¬¼ÂÁõ¤Ç¤¤ë¡£
#include <stdio.h> #include <setjmp.h> jmp_buf jb1, jb2; int i; void test() { for (i = 1; i <= 10; i++) if (setjmp(jb2) == 0) longjmp(jb1, i); longjmp(jb1, -1); } int main() { int value = setjmp(jb1); if (value == 0) test(); else if (value > 0) { printf("%d\n", value); longjmp(jb2, 1); } }
- Windows¤Ç¤Ï¥Õ¥¡¥¤¥Ð¡¼¤È¤·¤ÆOS¤Ç¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ë¡£
- ¥¹¥¿¥Ã¥¯¤¬Ê̤˳ÎÊݤµ¤ì¤ë¤¿¤á¥í¡¼¥«¥ëÊÑ¿ô¤äRAII¤ÎÌäÂê¤â¤Ê¤¤¡£
- OS¤Îµ¡Ç½¤ò»È¤¦¤È¸¶Íý¤ÎÀâÌÀ¤Ë¤Ê¤é¤Ê¤¤¤Î¤Çº£²ó¤Ï»ÈÍѤ·¤Ê¤¤¡£
- °ìöȴ¤±¤¿½èÍý¤ËÌá¤ë¤³¤È¤ò¡Ö·Ñ³¡×¤È¸Æ¤Ö¡£
- test()Æâ¤Çsetjmp(jb2)¤È¤·¤ÆÊݸ¤·¤¿¥³¥ó¥Æ¥¥¹¥È¤ËÌá¤Ã¤Æ¤¤¤ë¡£
*** ¥í¡¼¥«¥ëÊÑ¿ô
- ·Ñ³¤·¤¿ºÝ¤Ë¥í¡¼¥«¥ëÊÑ¿ô¤ÏÉüµ¢¤·¤Ê¤¤¡£
- i¤ò¥í¡¼¥«¥ëÊÑ¿ô¤Ë¤¹¤ë¤È¸íÆ°ºî¤¹¤ë¡£
#include <setjmp.h> jmp_buf jb1, jb2; -int i; void test() { + int i; for (i = 1; i <= 10; i++) if (setjmp(jb2) == 0) longjmp(jb1, i);
- ¥í¡¼¥«¥ëÊÑ¿ô¤Ç¤¹¤é¼º¤ï¤ì¤ë¤¿¤á¡¢RAII¤ÏÏÀ³°¡£
- ´Ø¿ô¤«¤é¤ÎÌá¤êÀè¤âÊݸ¤µ¤ì¤Ê¤¤¤¿¤á¡¢test()¤ÎºÇ¸å¤Ïlongjmp()¤ÇÈ´¤±¤ë¡£
*** C#
C#¤ÇƱ¤¸¤â¤Î¤ò½ñ¤¤¤ÆÈæ³Ó¡£
class Program { static IEnumerable<int> test() { for (int i = 1; i <= 10; i++) yield return i; } static void Main(string[] args) { foreach (var i in test()) Console.WriteLine(i); } }
¾¯¤·¤º¤Ä³ÈÄ¥¤·¤Æ¤¤¤¯¤¿¤á¤Ë¡¢¤Þ¤º¤Ï¼«Á°¼ÂÁõ¤·¤Æ¤ß¤ë¡£
https://gist.github.com/1257249
#include <stdio.h> typedef struct { unsigned long eip, esp, ebp, ebx, edi, esi; } myjmp_buf; _declspec(naked) int mysetjmp(myjmp_buf *jbuf) { _asm { mov edx, [esp+4] mov eax, [esp] mov [edx ], eax mov [edx+ 4], esp mov [edx+ 8], ebp mov [edx+12], ebx mov [edx+16], edi mov [edx+20], esi xor eax, eax ret } } _declspec(naked) void mylongjmp(myjmp_buf *jbuf, int value) { _asm { mov eax, [esp+ 8] mov edx, [esp+ 4] mov ecx, [edx ] mov esp, [edx+ 4] mov ebp, [edx+ 8] mov ebx, [edx+12] mov edi, [edx+16] mov esi, [edx+20] mov [esp], ecx ret } } myjmp_buf jb; int main() { if (mysetjmp(&jb) == 0) { printf("setjmp\n"); printf("test\n"); mylongjmp(&jb, 1); printf("never reach here\n"); } printf("longjmp done.\n"); }
¥ì¥¸¥¹¥¿¤ò¹½Â¤ÂΤËÊݸ¤·¤Æ¤¤¤ë¤À¤±¡£
RAII¤Ï̵»ë¤·¤Æ¤¤¤ë¤Î¤Çg++¤ÈƱ¤¸·ë²Ì¤È¤Ê¤ë¡£
- setjmp/longjmp¤Ç¤Î¥¹¥¿¥Ã¥¯¤Î¾ÃÈñ¤ò¸º¤é¤¹¤¿¤áfastcall²½¡£
- ¥á¥â¥ê¥¢¥¯¥»¥¹¤ò¸º¤é¤¹¤¿¤áret¤òjmp¤Ë½ñ¤´¹¤¨¡£
- ¤¤¤¤Ê¤êpop¤ÇÌá¤êÀè¤ò¼èÆÀ¤·¤Æ¤«¤éesp¤òÊݸ¤·¤Æ¤ª¤¯¡£
typedef struct { unsigned long eip, esp, ebp, ebx, edi, esi; } myjmp_buf; _declspec(naked) int _fastcall mysetjmp(myjmp_buf *jbuf) { _asm { pop edx mov [ecx ], edx mov [ecx+ 4], esp mov [ecx+ 8], ebp mov [ecx+12], ebx mov [ecx+16], edi mov [ecx+20], esi xor eax, eax jmp edx } } _declspec(naked) void _fastcall mylongjmp(myjmp_buf *jbuf, int value) { _asm { mov eax, edx mov esp, [ecx+ 4] mov ebp, [ecx+ 8] mov ebx, [ecx+12] mov edi, [ecx+16] mov esi, [ecx+20] jmp dword ptr [ecx] } }
ñ½ã¤Ësetjmp/longjmp¤ÇÃæÃǤ·¤¿½èÍý¤òºÆ³«¤¹¤ë¤È
¥¹¥¿¥Ã¥¯¤¬Ç˲õ¤µ¤ì¤ë¤¿¤á¥í¡¼¥«¥ëÊÑ¿ô¤äÌá¤êÀ褬ÉÔÄê¡£
#include <stdio.h> myjmp_buf jb1, jb2; int i, *p; void test() { for (i = 1; i <= 10; i++) if (mysetjmp(&jb2) == 0) { for (p = (int *)jb2.esp; p < (int *)jb1.esp; p++) printf("%p: %p\n", p, *p); mylongjmp(&jb1, i); } mylongjmp(&jb1, -1); } int main() { int value = mysetjmp(&jb1); if (value == 0) test(); else if (value > 0) { printf("%d\n", value); mylongjmp(&jb2, 1); } }
¥¹¥¿¥Ã¥¯¤Î¾ÃÈñ¤òÍÞ¤¨¤ë¤¿¤áRelease¥Ó¥ë¥É¤Ç³Îǧ¡£
¥¹¥¿¥Ã¥¯¤¬Ç˲õ¤µ¤ì¤Æ¤¤¤ë¡£
Éü¸µÍѥХåե¡¤òÄɲá£
typedef struct { unsigned long eip, esp, ebp, ebx, edi, esi; void *stack; int length; } myjmp_buf; _declspec(naked) int _fastcall mysetjmp(myjmp_buf *jbuf) { _asm { pop edx mov [ecx ], edx mov [ecx+ 4], esp mov [ecx+ 8], ebp mov [ecx+12], ebx mov [ecx+16], edi mov [ecx+20], esi xor eax, eax mov [ecx+24], eax mov [ecx+28], eax jmp edx } } _declspec(naked) void _fastcall mylongjmp(myjmp_buf *jbuf, int value) { _asm { mov eax, edx mov edx, ecx mov esp, [edx+ 4] mov edi, esp mov esi, [edx+24] mov ecx, [edx+28] cld rep movsb mov ebp, [edx+ 8] mov ebx, [edx+12] mov edi, [edx+16] mov esi, [edx+20] jmp dword ptr [edx] } }
¥¹¥¿¥Ã¥¯ÂàÈòÍÑ´Ø¿ô¡£
#include <string.h> #include <vector> void save_stack(std::vector<char> *dest, unsigned long last, myjmp_buf *callee) { callee->length = last - callee->esp; dest->resize(callee->length); callee->stack = &(*dest)[0]; memcpy(callee->stack, (void *)callee->esp, callee->length); }
¥µ¥ó¥×¥ë¤ò²þ¤¡£
#include <stdio.h> myjmp_buf jb1, jb2; std::vector<char> stack; int i, *p; void test() { for (i = 1; i <= 10; i++) if (mysetjmp(&jb2) == 0) { save_stack(&stack, jb1.esp, &jb2); for (p = (int *)jb2.esp; p < (int *)jb1.esp; p++) printf("%p: %p\n", p, *p); mylongjmp(&jb1, i); } mylongjmp(&jb1, -1); } int main() { int value = mysetjmp(&jb1); if (value == 0) test(); else if (value > 0) { printf("%d\n", value); mylongjmp(&jb2, 1); } }
¥¹¥¿¥Ã¥¯¤¬Àµ¾ï¤ËÊݸ¤µ¤ì¤Æ¤¤¤ë¤³¤È¤ò³Îǧ¡£
¥í¡¼¥«¥ëÊÑ¿ô¤ò»È¤Ã¤Æ¤âÂç¾æÉס£
myjmp_buf jb1, jb2; std::vector<char> stack; -int i, *p; +int *p; void test() { - for (i = 1; i <= 10; i++) + for (int i = 1; i <= 10; i++) if (mysetjmp(&jb2) == 0) { save_stack(&stack, jb1.esp, &jb2); for (p = (int *)jb2.esp; p < (int *)jb1.esp; p++)
¼Â¹Ô·ë²Ì
Ìá¤êÀ褬ÊÝ»ý¤µ¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¤¿¤á¡¢½ªÎ»ÄÌÃΤÏÉÔÍס£
¸Æ¤Ó½Ð¤·¸µ¤Ç¤¤Á¤ó¤È·Ñ³¤µ¤ì¤ë¡£
https://gist.github.com/1259601
#include <stdio.h> myjmp_buf jb1, jb2; std::vector<char> stack; void test() { for (int i = 1; i <= 10; i++) if (mysetjmp(&jb2) == 0) { save_stack(&stack, jb1.esp, &jb2); mylongjmp(&jb1, i); } } int main() { int value = mysetjmp(&jb1); if (value == 0) { test(); printf("end\n"); } else if (value > 0) { printf("%d\n", value); mylongjmp(&jb2, 1); } }
¼Â¹Ô·ë²Ì
¥Ð¥Ã¥Õ¥¡¤òÁê¸ß¤Ë¸Æ¤Ó¹ç¤¦¤Î¤Ïʬ¤«¤ê¤Ë¤¯¤¤¤Î¤Ç´Êά²½¤ò»î¤ß¤ë¡£
https://gist.github.com/1271852
#include <functional> #include <vector> template <class T> class Coroutine { myjmp_buf caller, callee; std::vector<char> stack; std::function<void()> f; int status; public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { if (mysetjmp(&caller)) return true; switch (status) { case 0: status = 1; f(); status = 3; break; case 2: mylongjmp(&callee, 1); } return false; } T yield(T value) { this->value = value; if (mysetjmp(&callee) == 0) { status = 2; save_stack(&stack, caller.esp, &callee); mylongjmp(&caller, 1); } return this->value; } };
¤³¤ì¤ò»È¤Ã¤ÆÎã¤ò½ñ¤Ä¾¤¹¤È°Ê²¼¤ÎÄ̤ꡣ
#include <stdio.h> Coroutine<int> cr; void test() { for (int i = 0; i <= 5; i++) cr.yield(i); } int main() { cr = test; while (cr()) printf("%d\n", cr.value); printf("end\n"); }
°ÊÁ°¤Ïlongjmp¤ÇÃͤòÅϤ·¤Æ¤¤¤¿¤¿¤á0¤¬ÆÃÊÌ°·¤¤¤µ¤ì¤Æ¤¤¤¿¤¬¡¢
ÃͤȾõÂÖ¤òʬΥ¤·¤¿¤¿¤¿¤á0¤âÌäÂê¤Ê¤¯ÅϤ»¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¡£
Àè¤Û¤É¤Î¼ÂÁõ¤Ï»öÁ°¤ËCoroutine¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÄêµÁ¤·¤Æ¡¢
yield¤¬¤½¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤ËÇû¤é¤ì¤Æ¤¤¤ë¡£
¤³¤ì¤Ç¤Ï³Ê¹¥°¤¤¤Î¤Çyield()¤òʸ̮°Í¸¤ÇÆÈΩ¤µ¤»¤Æ¤ß¤ë¡£
https://gist.github.com/1271857
#include <functional> #include <vector> #include <stack> class CoroutineBase { public: virtual ~CoroutineBase() {} }; static std::stack<CoroutineBase *> coroutines; template <class T> class Coroutine : public CoroutineBase { myjmp_buf caller, callee; std::vector<char> stack; std::function<void()> f; int status; public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { if (mysetjmp(&caller)) return true; switch (status) { case 0: status = 1; coroutines.push(this); f(); coroutines.pop(); status = 3; break; case 2: coroutines.push(this); mylongjmp(&callee, 1); } return false; } T yield(T value) { if (coroutines.top() == this) { coroutines.pop(); status = 2; this->value = value; if (mysetjmp(&callee) == 0) { save_stack(&stack, caller.esp, &callee); mylongjmp(&caller, 1); } } return this->value; } }; template <class T> T yield(T value) { auto cr = dynamic_cast<Coroutine<T> *>(coroutines.top()); return cr ? cr->yield(value) : T(); }
¤³¤ì¤ò»È¤¨¤ÐÈó¾ï¤Ë¤¹¤Ã¤¤ê½ñ¤±¤ë¡£
#include <stdio.h> void test() { for (int i = 0; i <= 5; i++) yield(i); } int main() { Coroutine<int> cr = test; while (cr()) printf("%d\n", cr.value); printf("end\n"); }
RAII¤â»È¤¨¤ë¡£
https://gist.github.com/1258016
#include <stdio.h> class Test { const char *s; public: Test(const char *s) : s(s) {} ~Test() { printf("%s\n", s); } }; void test() { Test t("test()"); for (int i = 0; i <= 5; i++) yield(i); } int main() { Test t("main()"); Coroutine<int> cr = test; while (cr()) printf("%d\n", cr.value); printf("end\n"); }
¼Â¹Ô·ë²Ì
°ã¤¦³¬Áؤ«¤é¸Æ¤Ö¤Èͽ´ü¤·¤Ê¤¤·ë²Ì¤È¤Ê¤ë¡£
Debug¤Ç¤ÏɽÌ̲½¤·¤Ê¤¤¤Î¤ÇRelease¤Ç¥Ó¥ë¥É¡£
https://gist.github.com/1273598
#include <stdio.h> void test() { for (int i = 0; i <= 5; i++) yield(i); printf("test: done\n"); } Coroutine<int> cr = test; void test2() { if (cr()) printf("test2: %d\n", cr.value); } int main() { if (cr()) printf("main: %d\n", cr.value); test2(); if (cr()) printf("main: %d\n", cr.value); }
¸Æ¤Ó½Ð¤·¸µ¤Î¥¹¥¿¥Ã¥¯¤Ë°Í¸¤¹¤ë¤¿¤á¡¢
test2()¤«¤é¸Æ¤Ð¤ì¤¿¥³¥ë¡¼¥Á¥ó¤ÏÀµ¾ï¤ËÆ°ºî¤·¤Ê¤¤¡£
- ¿Þ¼¨
¤Á¤Ê¤ß¤Ëf¤ò´Ø¿ô¥Ý¥¤¥ó¥¿¤ËÊѹ¹¤¹¤ë¤ÈDebug¥Ó¥ë¥É¤Ç¤âÍî¤Á¤ë¡£
¤¿¤À¤·Íî¤Á¤ë¥¿¥¤¥ß¥ó¥°¤Ï¿¾¯°Û¤Ê¤ë¡£
template <class T> class Coroutine : public CoroutineBase { myjmp_buf caller, callee; std::vector<char> stack; - std::function<void()> f; + void (*f)(); int status; public:
¥³¥ë¡¼¥Á¥ó¤¬»ÈÍѤ¹¤ë¥¹¥¿¥Ã¥¯¤ò¤½¤Î¤Þ¤ÞÀѤà¤Î¤Ç¤Ï¤Ê¤¯¡¢
ÆÃÄê¤ÎÎΰè¤Ë¼è¤Ã¤Æ´ÉÍý¤¹¤ë¤³¤È¤ÇÌäÂê¤ò²ò·è¤¹¤ë¡£
- Ä̾¥¹¥¿¥Ã¥¯¤Ï1ËÜ
- ¥Õ¥¡¥¤¥Ð¡¼¤ä¥¹¥ì¥Ã¥É¤Ç¥¹¥¿¥Ã¥¯¤ò¿·ÀߤǤ¤ë
- ¼«Á°¼ÂÁõ¤Ç¸¶Íý¤òõ¤ë¤Î¤¬ÌÜŪ¤Î¤¿¤áº£²ó¤Ï»ÈÍѤ·¤Ê¤¤
̵¸ÂºÆµ¢¤Ç¥¹¥¿¥Ã¥¯¤Î¸Â³¦¤òõ¤ë¡£
#include <stdio.h> void test() { int a; printf("\r&a: %p ", &a); fflush(stdout); test(); } int main() { int a; printf("&a: %p\n", &a); test(); return 0; }
¼Â¹Ô·ë²Ì¤Ï°Ê²¼¤ÎÄ̤ꡣ
¢¨´Ä¶¤Ë¤è¤Ã¤ÆÃͤϰۤʤë¤È»×¤ï¤ì¤ë¡£
- 0x13ff78 - 0x44d4c = 0xfb22c ð 1004.5KB
¥¹¥¿¥Ã¥¯¤Î¸Â³¦¤¬Ìó1MB¤À¤È¤¤¤¦¤³¤È¤¬Ê¬¤«¤ë¡£
¤³¤ÎÃͤÏPE¥Ø¥Ã¥À¤Ë½ñ¤¤¤Æ¤¢¤ë¡£
- IMAGE_OPTIONAL_HEADER32::SizeOfStackReserve
VC++2010¤Î¥Ç¥Õ¥©¥ë¥ÈÃͤÏ0x100000(1MB)¡£
¥¹¥¿¥Ã¥¯¤ò¤¢¤ëÄøÅÙ¶õ¤±¤Æ¥³¥ë¡¼¥Á¥ó¤ò¼Â¹Ô¤¹¤ë¡£
¶õ¤±¤¿¥¹¥¿¥Ã¥¯¤ÎÀèƬ¤ò¥á¥ó¥Ð¤Ë»Ä¤·¤Æ¤ª¤¯¡£
std::vector<char> stack; std::function<void()> f; int status; + unsigned long last; public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { + if (status == 0) _alloca(32 * 1024); if (mysetjmp(&caller)) return true; switch (status) { case 0: + last = caller.esp; status = 1; coroutines.push(this); f();
¥í¡¼¥«¥ë¤ËµðÂç¤ÊÇÛÎó¤ò³ÎÊݤ·¤Ê¤¤¸Â¤ê¡¢
32KB¤â¥¹¥¿¥Ã¥¯¤ò¾ÃÈñ¤¹¤ë¤³¤È¤Ï¾¯¤Ê¤¤¤È»×¤¦¡£
Ç°¤Î¤¿¤á·Ñ³»þ¤Ë¥¹¥¿¥Ã¥¯¤òÆͤÇˤäƤ¤¤Ê¤¤¤«¥Á¥§¥Ã¥¯¤¹¤ë¡£
status = 3; break; case 2: + if (caller.esp < callee.esp) + return false; coroutines.push(this); mylongjmp(&callee, 1); }
¶õ¤±¤¿¥¹¥¿¥Ã¥¯¤òÊݸ¤¹¤ë¤È̵Â̤ʤΤǡ¢
¥á¥ó¥Ð¤Ë»Ä¤·¤¿¥¹¥¿¥Ã¥¯¤Î¥¢¥É¥ì¥¹¤ò»È¤¦¡£
status = 2; this->value = value; if (mysetjmp(&callee) == 0) { - save_stack(&stack, caller.esp, &callee); + save_stack(&stack, last, &callee); mylongjmp(&caller, 1); } }
ÌäÂêÅÀ¤È¤·¤ÆÁ°·Ç¤·¤¿¥³¡¼¥É¤¬°ì¸«Àµ¾ï¤ËÆ°¤¯¡£
¥³¥ë¡¼¥Á¥óÆâ¤Î¥ë¡¼¥×¤Î¾å¸Â¤ò5¤«¤é0¤Ë¤¹¤ë¤È°Û¾ïÆ°ºî¤¹¤ë¡£
https://gist.github.com/1273606
#include <stdio.h> void test() { - for (int i = 0; i <= 5; i++) + for (int i = 0; i <= 0; i++) yield(i); printf("test: done\n"); }
¥³¥ë¡¼¥Á¥ó¤òÈ´¤±¤ë¤È¤¤Ë¥¹¥¿¥Ã¥¯¤¬²õ¤ì¤ë¡£
¥³¥ë¡¼¥Á¥ó¤ò¸Æ¤ó¤Ç¤¤¤ëÉôʬ¤ò¸«¤ë¤È¡¢
½ªÎ»»þ¤Ï¤½¤Î¤Þ¤Þή¤ìÍî¤Á¤ë¤³¤È¤ò´üÂÔ¤·¤Æ¤¤¤ë¡£
case 0: status = 1; coroutines.push(this); f(); coroutines.pop(); status = 3; break;
Ê̤γ¬Áؤ«¤é¸Æ¤Ö¤ÈÉüµ¢»þ¤Îebp¤¬¿©¤¤°ã¤¦¤¿¤á¡¢
¥í¡¼¥«¥ëÊÑ¿ô¤¬Àµ¾ï¤Ë»²¾È¤Ç¤¤º¤Ë¥¨¥é¡¼¤È¤Ê¤ë¡£
- ¿Þ¼¨
¥³¥ë¡¼¥Á¥ó¤ò¥é¥Ã¥Ñ¡¼·Ðͳ¤Ç¸Æ¤ó¤Ç½ªÎ»ÄÌÃΤ¹¤ì¤Ð²ò·è¡£
- ¿Þ¼¨
https://gist.github.com/1271829
int status; unsigned long last; + void exec() { + f(); + mylongjmp(&caller, 2); + } + public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { if (status == 0) _alloca(32 * 1024); - if (mysetjmp(&caller)) return true; + switch (mysetjmp(&caller)) { + case 1: + return true; + case 2: + coroutines.pop(); + status = 3; + return false; + } switch (status) { case 0: last = caller.esp; status = 1; coroutines.push(this); - f(); - coroutines.pop(); - status = 3; - break; + exec(); case 2: if (caller.esp < callee.esp) return false;
º£¤Þ¤Ç½¤Àµ¤âƱ»þ¤Ë¹Ô¤¦¤¿¤á1¤Ä¤Î¥½¡¼¥¹¤ËÁ´Éô½ñ¤¤¤Æ¤¤¤¿¡£
½¤Àµ¤¬Íî¤ÁÃ夤¤¿¤Î¤Ç¥½¡¼¥¹¤òʬ³ä¤·¤ÆÀ°Íý¡£
https://gist.github.com/1274612
Coroutine.h
#pragma once #include <vector> #include <functional> #include <stack> typedef struct { unsigned long eip, esp, ebp, ebx, edi, esi; void *stack; int length; } myjmp_buf; extern int _fastcall mysetjmp(myjmp_buf *jbuf); extern void _fastcall mylongjmp(myjmp_buf *jbuf, int value); extern void save_stack(std::vector<char> *dest, unsigned long last, myjmp_buf *callee); class CoroutineBase { public: virtual ~CoroutineBase(); }; extern std::stack<CoroutineBase *> coroutines; template <class T> class Coroutine : public CoroutineBase { myjmp_buf caller, callee; std::vector<char> stack; std::function<void()> f; int status; unsigned long last; void exec() { f(); mylongjmp(&caller, 2); } public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { if (status == 0) _alloca(32 * 1024); switch (mysetjmp(&caller)) { case 1: return true; case 2: coroutines.pop(); status = 3; return false; } switch (status) { case 0: last = caller.esp; status = 1; coroutines.push(this); exec(); case 2: if (caller.esp < callee.esp) return false; coroutines.push(this); mylongjmp(&callee, 1); } return false; } T yield(T value) { if (coroutines.top() == this) { coroutines.pop(); status = 2; this->value = value; if (mysetjmp(&callee) == 0) { save_stack(&stack, last, &callee); mylongjmp(&caller, 1); } } return this->value; } }; template <class T> T yield(T value) { auto cr = dynamic_cast<Coroutine<T> *>(coroutines.top()); return cr ? cr->yield(value) : T(); }
Coroutine.cpp
#include "Coroutine.h" _declspec(naked) int _fastcall mysetjmp(myjmp_buf *jbuf) { _asm { pop edx mov [ecx ], edx mov [ecx+ 4], esp mov [ecx+ 8], ebp mov [ecx+12], ebx mov [ecx+16], edi mov [ecx+20], esi xor eax, eax mov [ecx+24], eax mov [ecx+28], eax jmp edx } } _declspec(naked) void _fastcall mylongjmp(myjmp_buf *jbuf, int value) { _asm { mov eax, edx mov edx, ecx mov esp, [edx+ 4] mov edi, esp mov esi, [edx+24] mov ecx, [edx+28] cld rep movsb mov ebp, [edx+ 8] mov ebx, [edx+12] mov edi, [edx+16] mov esi, [edx+20] jmp dword ptr [edx] } } void save_stack(std::vector<char> *dest, unsigned long last, myjmp_buf *callee) { callee->length = last - callee->esp; dest->resize(callee->length); callee->stack = &(*dest)[0]; memcpy(callee->stack, (void *)callee->esp, callee->length); } std::stack<CoroutineBase *> coroutines; CoroutineBase::~CoroutineBase() {}
·¿¤¬¼Â¹Ô»þȽÄê¤Î¤¿¤á¡¢·¿»ØÄê¤ò´Ö°ã¤¨¤ë¤ÈÆ°¤«¤Ê¤¤¤Î¤ÇÃí°Õ¡£
#include <iostream> #include <string> #include "Coroutine.h" using namespace std; void test1() { yield<string>("abc"); yield<string>("1234"); yield<string>("finish!"); } void test2() { Coroutine<string> cr = test1; while (cr()) { auto s = cr.value; cout << s << ": "; yield<int>(s.size()); } } int main() { Coroutine<int> cr = test2; while (cr()) cout << cr.value << endl; }
¥³¥ë¡¼¥Á¥ó¤Î·Ñ³»þ¤Ë°ú¿ô¡ÊÁêÅö¡Ë¤òÅϤ¹ÊýË¡¡£
value¤ò½ñ¤´¹¤¨¤ë¤Èyield¤Ç¤½¤ÎÃͤ¬Ìᤵ¤ì¤ë¡£
¢¨¤¢¤é¤«¤¸¤á¤³¤ì¤¬¤Ç¤¤ë¤è¤¦¤Ë¹Íθ¤·¤¿»ÅÍÍ¡£
#include <iostream> #include "Coroutine.h" using namespace std; void test() { int n = 0; for (;;) n = yield(++n); } int main() { Coroutine<int> cr = test; if (cr()) cout << cr.value << endl; if (cr()) cout << cr.value << endl; cr.value = 5; if (cr()) cout << cr.value << endl; }
¤³¤ì°Ê³°¤ÎÊýË¡¤ò¤¤¤¯¤Ä¤«¾Ò²ð¤¹¤ë¡£
¥¯¥í¡¼¥¸¥ã¤Ç¥í¡¼¥«¥ëÊÑ¿ô¤ò¥¥ã¥×¥Á¥ã¡£
#include <iostream> #include "Coroutine.h" using namespace std; int main() { int n = 0; Coroutine<int> cr = [&] { for (;;) yield(++n); }; if (cr()) cout << cr.value << endl; if (cr()) cout << cr.value << endl; n = 5; if (cr()) cout << cr.value << endl; }
´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥È¤òÅϤ¹¤È¥¤¥ó¥¹¥¿¥ó¥¹¤¬ºî¤é¤ì¤Æ¡¢
°ú¿ô¤È¤·¤Æ¥á¥ó¥Ð¤ò¤¤¤¸¤ëÌÜŪ¤ÏãÀ®¤Ç¤¤Ê¤¤¡£
¤¢¤Þ¤ê»È¤¤Æ»¤Ï¤Ê¤¤¤¬¡¢¥Ï¥Þ¤ë²ÄǽÀ¤¬¤¢¤ë¤¿¤á¾Ò²ð¡£
¤¢¤ë°ÕÌ£¥¸¥§¥Í¥ì¡¼¥¿¤Ã¤Ý¤¤¡£
¤·¤«¤·³°Éô¤«¤éÃͤòÁàºî¤Ç¤¤Ê¤¤¤Ê¤é¡¢
ñ½ã¤Ë¥í¡¼¥«¥ëÊÑ¿ô¤Ç¥«¥¦¥ó¥È¤·¤¿Êý¤¬Îɤ¤¡£
#include <iostream> #include "Coroutine.h" using namespace std; int main() { struct Test { int n; Test() : n(0) {} void operator()() { for (;;) yield(++n); } } test; Coroutine<int> cr1 = test; if (cr1()) cout << "cr1: " << cr1.value << endl; if (cr1()) cout << "cr1: " << cr1.value << endl; Coroutine<int> cr2 = test; if (cr2()) cout << "cr2: " << cr2.value << endl; if (cr2()) cout << "cr2: " << cr2.value << endl; cout << "test.n: " << test.n << endl; }
- ¤¢¤é¤«¤¸¤á¥í¡¼¥«¥ëÍѤ˥¹¥¿¥Ã¥¯¤ò¼è¤Ã¤Æ¤ª¤¤¤Æ¤â¡¢
¥³¥ë¡¼¥Á¥ó¤«¤é¤Î´Ø¿ô¸Æ¤Ó½Ð¤·¤Ç¥¹¥¿¥Ã¥¯¤¬Ç˲õ¤µ¤ì¤ë¶²¤ì¤¬¤¢¤ë¡£
- ¤½¤â¤½¤â¥¹¥¿¥Ã¥¯¤ò´¬¤Ìᤷ¤¿»þÅÀ¤ÇÃͤÎÊݸ¤ò´üÂÔ¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¡£
- ¥Ò¡¼¥×¤Ê¤É¤Ë¥í¡¼¥«¥ë¥¹¥¿¥Ã¥¯¤ò¼è¤Ã¤Æ¤âƱÍͤÎÌäÂê
- OSµ¡Ç½¤È¤·¤Æ¤Î¥Õ¥¡¥¤¥Ð¡¼¤ò»È¤¨¤ÐÊ̤˥¹¥¿¥Ã¥¯¤¬³ÎÊݤǤ¤Æ¼«Æ°¿Ä¥¤µ¤ì¤ë
- ²¼²ó¤ê¤¬Windows¤Ë°Í¸¤¹¤ë¤¿¤áº£²ó¤ÏOS¥Õ¥¡¥¤¥Ð¡¼¤ò»È¤ï¤Ê¤¤
- ¥¹¥ì¥Ã¥É¤Ç¤âÊ̤νê¤Ë¥¹¥¿¥Ã¥¯¤¬³ÎÊݤµ¤ì¤Æ¼«Æ°¿Ä¥¤µ¤ì¤ë¡£
- ¥¹¥ì¥Ã¥É¤òƱ´üŪ¤Ë¸Æ¤Ó½Ð¤»¤Ð¥Õ¥¡¥¤¥Ð¡¼¤È¤Û¤ÜÅù²Á
- GUI¤Ê¤É¥¹¥ì¥Ã¥É°Í¸¤Î½èÍý¤Ç¥¹¥ì¥Ã¥É´Ö¸Æ¤Ó½Ð¤·¤¬É¬ÍפˤʤêÌÌÅÝ
- ´¬¤Ìᤷ¤ò»È¤ï¤Ê¤¤¥³¥ë¡¼¥Á¥ó¤¬ÍýÁÛŪ
- ¸À¸ìµ¡Ç½¤È¤·¤Æ¼ÂÁõ¤Ç¤¤ë¤Ê¤é¡¢¥í¡¼¥«¥ëÊÑ¿ô¤Ï¥á¥â¥ê¾å¤ÎǤ°Õ¤Ë¼è¤Ã¤Æ¡¢
¤½¤ì¤è¤ê²¼¤Ø¤Î¸Æ¤Ó½Ð¤·¤Ï¸½¹Ô¤Î¥¹¥¿¥Ã¥¯¤ò¾ÃÈñ¤µ¤»¤ë¤Î¤¬¥¹¥Þ¡¼¥È¡£
¥µ¥ó¥¯¤È°Ñ¾ù¤òƳÆþ¤·¤¿Win32¤Ë·Ñ³¤òÁȤ߹ç¤ï¤»¤ë¡£
¥¤¥Ù¥ó¥È¥É¥ê¥Ö¥ó¤Ç¾õÂÖ¤òÊÝ»ý¤·¤Æ¤¤¤ëÉôʬ¤Î¿Þ¼¨¡£
°ìÏ¢¤Îή¤ì¤¬Ê¬ÃǤµ¤ì¤Æ¤¤¤ë¡£
¡ù¢ª{}
¡ù¢ª{}
¡ù¢ª{}
¥¤¥Ù¥ó¥È´Ö¤Ç¾õÂÖ¤ò¶¦Í¤¹¤ë¤¿¤á¥Õ¥é¥°¤ÎÎबɬÍפȤʤ롣
¥Ñ¥Ã¥·¥Ö¡Ê¥×¥Ã¥·¥å·¿¡Ë¤Ê¥³¡¼¥É¡£
¤³¤ì¤ò¥¢¥¯¥Æ¥£¥Ö¡Ê¥×¥ë·¿¡Ë¤Ê·Á¤ËÊÑ´¹¤¹¤ë¤È¡¢
¾õÂÖ¤Ïʬ´ô¤ä¥í¡¼¥«¥ëÊÑ¿ô¤Ë²¡¤·¹þ¤à¤³¤È¤¬¤Ç¤¤ë¡£
·Ñ³¤Ï¤Ê¤ë¤Ù¤¯¥é¥¤¥Ö¥é¥ê¦¤Ë±£¤¹¤È»È¤¤¤ä¤¹¤¯¤Ê¤ë¡£
Á°²ó¤ÎÌäÂê¤Ç»ÈÍѤ·¤¿Win32¥×¥í¥°¥é¥à¤ò³ÈÄ¥¤¹¤ë¡£
Coroutine.h¤ÈCoroutine.cpp¤ò¥×¥í¥¸¥§¥¯¥È¤ËÄɲá£
stdafx.h¤ËÄɲá£
// TODO: ¥×¥í¥°¥é¥à¤ËɬÍפÊÄɲåإåÀ¡¼¤ò¤³¤³¤Ç»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£ #include <list> #include <functional> #include <string> #include "xbyak/xbyak.h" #include "Window.h" +#include "Coroutine.h"
Coroutine.cpp¤Ç¤Ïstdafx.h¤òinclude¤¹¤ë¡£
- #include "Coroutine.h" + #include "stdafx.h"
¤³¤ì¤ÇCoroutine¥¯¥é¥¹¤ÎÄɲäϴ°Î»¡£
¥É¥é¥Ã¥°¤ò¥³¥ë¡¼¥Á¥ó¤Ç´Æ»ë¡£
https://gist.github.com/1275118
int mx, my; Coroutine<bool> cr = [&] { for (;;) { yield(false); int x = mx, y = my, px = pb.x, py = pb.y; while (yield(true)) { pb.x = px + (mx - x); pb.y = py + (my - y); InvalidateRect(win.hWnd, nullptr, true); } } }; cr(); win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { if (pb.x <= x && x <= pb.x + 40 && pb.y <= y && y <= pb.y + 40) { mx = x; my = y; if (!cr.value) cr(); } }); win.MouseMove.push_back([&](int x, int y, WPARAM) { if (cr.value) { mx = x; my = y; cr(); } }); win.MouseUp.push_back([&](int btn, int x, int y, WPARAM) { if (cr.value) { cr.value = false; cr(); } });
¤â¤¦¾¯¤·¥³¡¼¥É¤òÀ°Íý¤¹¤ë¡£
https://gist.github.com/1275258
Coroutine¥¯¥é¥¹¤ò³ÈÄ¥¤·¤Æ´¬¤Ì᤻¤ë¤è¤¦¤Ë¤¹¤ë¡£
Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } + void reset() { if (status == 3) status = 0; } bool operator()() { if (status == 0) _alloca(32 * 1024);
¥Ï¥ó¥É¥é¤È¤Î¶¨Ä´Æ°ºî¤òÃê½Ð¤·¤Æ¥¯¥é¥¹²½¤¹¤ë¡£
´¬¤Ìᤷ¤òÍøÍѤ·¤Æ̵¸Â¥ë¡¼¥×¤òÇÓ½ü¤·¤Æ¤¤¤ë¡£
class DragHandler { Coroutine<bool> cr; std::function<void()> handler; public: int x, y; DragHandler(Window *win) { win->MouseMove.push_back([&](int x, int y, WPARAM) { if (cr.value) { this->x = x; this->y = y; cr(); } }); win->MouseUp.push_back([&](int button, int x, int y, WPARAM) { if (cr.value) { cr.value = false; cr(); } }); } void operator=(const decltype(handler) &h) { cr = handler = h; cr.value = false; } void start(int x, int y) { this->x = x; this->y = y; if (!cr.value) { cr.reset(); cr(); } } };
¤³¤ì¤ò»È¤Ã¤Æ¥Ï¥ó¥É¥é¤ò½ñ¤Ä¾¤¹¡£
DragHandler dh(&win); win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { if (pb.x <= x && x <= pb.x + 40 && pb.y <= y && y <= pb.y + 40) dh.start(x, y); }); dh = [&] { int x = dh.x, y = dh.y, px = pb.x, py = pb.y; while (yield(true)) { pb.x = px + (dh.x - x); pb.y = py + (dh.y - y); InvalidateRect(win.hWnd, nullptr, true); } };
¥µ¥ó¥¯¡¦°Ñ¾ù¡¦·Ñ³¤ò»È¤Ã¤¿¥¤¥Ù¥ó¥È¥Ï¥ó¥É¥ê¥ó¥°¤¬´°À®¡£
¤³¤ì¤¬º£²óÄ󼨤·¤¿¤«¤Ã¤¿¥â¥Ç¥ë¡£
²ó¤ê¤«¤éºî¤Ã¤Æ¤¤¤¿¤Î¤Ç·ë¹½Ä¹¤¤Æ»¤Î¤ê¤À¤Ã¤¿¤±¤É¡¢
¤Ç¤¤¿¤â¤Î¤òÍøÍѤ¹¤ë¤À¤±¤Ê¤é¥·¥ó¥×¥ë¤À¤È»×¤¦¡£
Ê£¿ô¤Î¹àÌܤò°·¤¨¤ë¤è¤¦¤Ë¤·¤Æ¤ß¤ë¡£
https://gist.github.com/1275467
struct Rect { int x, y, w, h; inline int r() { return x + w; } inline int b() { return y + h; } Rect(int x, int y, int w, int h): x(x), y(y), w(w), h(h) {} bool contains(int px, int py) { return x <= px && px < r() && y <= py && py < b(); } }; std::vector<Rect> rects; rects.push_back(Rect(10, 10, 40, 40)); rects.push_back(Rect(60, 60, 40, 40)); win.Paint.push_back([&](HDC hdc) { auto oldPen = (HPEN)SelectObject(hdc, GetStockObject(BLACK_PEN)); auto oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(GRAY_BRUSH)); for (auto it = rects.begin(); it != rects.end(); it++) Rectangle(hdc, it->x, it->y, it->r(), it->b()); SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); }); DragHandler dh(&win); decltype(rects.rbegin()) sel; win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { for (auto it = rects.rbegin(); it != rects.rend(); it++) { if (it->contains(x, y)) { sel = it; dh.start(x, y); break; } } }); dh = [&] { int x = dh.x, y = dh.y, rx = sel->x, ry = sel->y; while (yield(true)) { sel->x = rx + (dh.x - x); sel->y = ry + (dh.y - y); InvalidateRect(win.hWnd, nullptr, true); } };
¤Á¤é¤Ä¤¤¬·ã¤·¤¤¤¬¡¢Âкö¤Ë¤Ï¥À¥Ö¥ë¥Ð¥Ã¥Õ¥¡¤¬É¬Íס£
º£²ó¤Ï¥µ¥ó¥¯¤È·Ñ³¤¬¥á¥¤¥ó¤Ê¤Î¤ÇÀâÌÀ¤Ï¸«Á÷¤ë¡£
DragHandler dh(&win), dh2(&win); decltype(rects.rbegin()) sel; win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { for (auto it = rects.rbegin(); it != rects.rend(); it++) { if (it->contains(x, y)) { sel = it; if (it->r() - x <= 5 && it->b() - y <= 5) dh2.start(x, y); else dh.start(x, y); break; } } }); dh = [&] { int x = dh.x, y = dh.y, rx = sel->x, ry = sel->y; while (yield(true)) { sel->x = rx + (dh.x - x); sel->y = ry + (dh.y - y); InvalidateRect(win.hWnd, nullptr, true); } }; dh2 = [&] { int x = dh2.x, y = dh2.y, rw = sel->w, rh = sel->h; while (yield(true)) { sel->w = rw + (dh2.x - x); sel->h = rh + (dh2.y - y); InvalidateRect(win.hWnd, nullptr, true); } };
º£²ó·ÇºÜ¤·¤¿¥µ¥ó¥×¥ë¥³¡¼¥É¤Ï¤¹¤Ù¤ÆCC0¤ÇÄ󶡤·¤Þ¤¹¡£
º£²ó¤ä¤Ã¤¿¤è¤¦¤ÊÆâÍƤòÊÙ¶¯¤¹¤ë¤Ë¤Ï¡¢
´û¸¤Î¥³¥ó¥Ñ¥¤¥é¤Î½ÐÎϤòÅð¤ß¸«¤·¤Ê¤¬¤é¡¢
¼«Ê¬¤Ç¥³¥ó¥Ñ¥¤¥é¤òºî¤Ã¤Æ¤ß¤ë¤Î¤¬Îɤ¤¤È»×¤¤¤Þ¤¹¡£
¥µ¥ó¥¯
- WTL/ATL¤Î¥á¥Ã¥»¡¼¥¸¥Þ¥Ã¥×¼Â¸½¤Î¤·¤¯¤ß
http://hp.vector.co.jp/authors/VA022575/c/msgmap.h...
¥³¥ë¡¼¥Á¥ó
- libconcurrent
http://code.google.com/p/libconcurrent/wiki/Projec...
- @sharow¤µ¤ó¤Ë¤è¤ë¥³¥ë¡¼¥Á¥ó¥é¥¤¥Ö¥é¥ê¡£³Æ¼ï¼ÂÁõ¤Î¥ê¥ó¥¯½¸¤¬¤¢¤ë¡£
- [C#][programming]C# ¤Î yield return ¤Î»È¤¤Æ»
http://d.hatena.ne.jp/u_1roh/20080302/1204471238
- ¥¤¥Ù¥ó¥È¥Ï¥ó¥É¥é¤È¥³¥ë¡¼¥Á¥ó¤Ë´Ø¤¹¤ëµÄÏÀ
- ¥«¥Æ¥´¥ê¡§
- ¥Ñ¥½¥³¥ó
- ¥×¥í¥°¥é¥ß¥ó¥°
ºÇ¿·¥³¥á¥ó¥È