Linux ã«ã¼ãã«ã®ã³ã³ããã¹ãã¹ã¤ããå¦çãèªã¿è§£ã
Linux ã«ã¼ãã«ã®ããã»ã¹ã¹ã±ã¸ã¥ã¼ã©ã®æ ¸ã§ãã kernel/sched.c ã® schedule() ãèªã¿é²ãã¦ããã¨ãã¿ã¹ã¯åãæ¿ã(å®è¡ã³ã³ããã¹ãåãæ¿ã)ã¯ãã®åã context_switch() ã¨ããé¢æ°ã«éç´ããã¦ãããã¨ãåããã¾ãã2.6.20 ã® kernel/sched.c ã ã¨ä»¥ä¸ã®ã³ã¼ãã§ãã
1839 static inline struct task_struct * 1840 context_switch(struct rq *rq, struct task_struct *prev, 1841 struct task_struct *next) 1842 { 1843 struct mm_struct *mm = next->mm; 1844 struct mm_struct *oldmm = prev->active_mm; 1845 1846 if (!mm) { 1847 next->active_mm = oldmm; 1848 atomic_inc(&oldmm->mm_count); 1849 enter_lazy_tlb(oldmm, next); 1850 } else 1851 switch_mm(oldmm, mm, next); 1852 1853 if (!prev->mm) { 1854 prev->active_mm = NULL; 1855 WARN_ON(rq->prev_mm); 1856 rq->prev_mm = oldmm; 1857 } 1858 /* 1859 * Since the runqueue lock will be released by the next 1860 * task (which is an invalid locking op but in the case 1861 * of the scheduler it's an obvious special-case), so we 1862 * do an early lockdep release here: 1863 */ 1864 #ifndef __ARCH_WANT_UNLOCKED_CTXSW 1865 spin_release(&rq->lock.dep_map, 1, _THIS_IP_); 1866 #endif 1867 1868 /* Here we just switch the register state and the stack. */ 1869 switch_to(prev, next, prev); 1870 1871 return prev; 1872 }
context_switch() 㯠Linuxã«ã¼ãã«2.6解èªå®¤ ã«ããã¨
- ããã»ã¹ç©ºéã®åãæ¿ãã®å¦ç switch_mm() : 1851è¡ç®
- å種ã¬ã¸ã¹ã¿ã®åãæ¿ã switch_to() : 1869 è¡ç®
ã®äºã¤ããæã£ã¦ãããã¨ã®ãã¨ã(1) ä»®æ³ã¡ã¢ãªã®å¤æãã¼ãã«çã次ã®ããã»ã¹ç©ºéã®ãã®ã«åãæ¿ã㦠(2) CPU ã¬ã¸ã¹ã¿ã«è¨å®ããããã¼ãã¦ã§ã¢ã³ã³ããã¹ãæ å ±çãéé¿ãåãæ¿ãã... ã¨ããäºã¤ã®å¦çãè¡ãã®ãã³ã³ããã¹ãã¹ã¤ããã
ãã®å¾è ã®ã¬ã¸ã¹ã¿åãæ¿ãã®å¦çãã©ããªã£ã¦ããã®ããªãã¨èå³æ¬ä½ã§ switch_to() ãè¦ãã¿ãã¨ãã©ãçããã®ã¯ include/asm-i386/system.h ã®ãã¯ãã§ããã
14 /* 15 * Saving eflags is important. It switches not only IOPL between tasks, 16 * it also protects other tasks from NT leaking through sysenter etc. 17 */ 18 #define switch_to(prev,next,last) do { \ 19 unsigned long esi,edi; \ 20 asm volatile("pushfl\n\t" /* Save flags */ \ 21 "pushl %%ebp\n\t" \ 22 "movl %%esp,%0\n\t" /* save ESP */ \ 23 "movl %5,%%esp\n\t" /* restore ESP */ \ 24 "movl $1f,%1\n\t" /* save EIP */ \ 25 "pushl %6\n\t" /* restore EIP */ \ 26 "jmp __switch_to\n" \ 27 "1:\t" \ 28 "popl %%ebp\n\t" \ 29 "popfl" \ 30 :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ 31 "=a" (last),"=S" (esi),"=D" (edi) \ 32 :"m" (next->thread.esp),"m" (next->thread.eip), \ 33 "2" (prev), "d" (next)); \ 34 } while (0)
ã¢ã»ã³ããªè¨èªã¨ C ã®ã³ã¼ããå ¥ãä¹±ãããã¯ããä¸è¦ä½ããªã«ããã§ããããã㯠gcc ã®æ¡å¼µæ©è½ã§ãC ã®ã³ã¼ãå ã«ã¤ã³ã©ã¤ã³ã§ã¢ã»ã³ããªå¦çãæ¸ãã asm() ã¨ãããã¼ã¯ã¼ãã使ã£ãã³ã¼ãã§ããã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã¨å¼ã°ãã¾ãã
ãã®ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªãªã³ã¼ããèªã¿è§£ãããã«è²ã ã¨èª¿ã¹ãã¨ãããã®ã§ãè¨æ¶ãå¼·ããããã«ãããã§è§£èª¬ããã¦ã¿ããã¨æãã¾ãããªãã以ä¸ã«è¨ãå 容ã¯ãã·ã³èªã®åºç¤çãªè©±ã主ã§ãããåã¯ãã·ã³èªã®ç¥èã¯ã»ã¼çç¡ãªã®ã§ç¸å½é©å½ãªè§£èª¬ã«ãªã£ã¦ãå¯è½æ§ãããã¾ããééããªã©ããã¾ãããææããã ããã¨å¬ããã§ãã(ãã¨ãæ £ãã¦ãªããã®ã§ã¢ã»ã³ãã«ãã¢ã»ã³ããªãã¢ã»ã³ãã©...ã®è¨èã®ä½¿ãæ¹ãããããããããã¾ãããããã³ãå¸æã§ãã)
x86 ä¸ã¤ i386 (not x86_64) ãåæã«è©±ãé²ãã¦ããã¾ãã
GNU as ã§ã¢ã»ã³ãã«
ã¾ãã¯ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã使ããã«ãç´ ã§ã¢ã»ã³ããªè¨èªãæ¸ãã¨ãããããLinux ã«ã¼ãã«ã¯ gcc ã§ã³ã³ãã¤ã«ããã¦ãããgcc ã¯ã¢ã»ã³ãã©ã« GNU as ãå©ç¨ãã¾ããæ ã«ã¢ã»ã³ãã©ã«ã¯ gas ã使ããã¨ã«ãªãã¾ãã
æå§ãã«ãä½ãããªãããã¤ããªã gas ã§ä½ã£ã¦ã¿ã¾ãã.s ãã¡ã¤ã«ã« GNU as (gas) ã®æ§æã§ã¢ã»ã³ããªå½ä»¤ãè¨è¿°ãã¦ããã¾ãã
.file "do_nothing.s" .global main main: ret
Cè¨èªã§ main() ãæåã«å¼ã°ããã®ã¯ libc ã main ã¨ããã·ã³ãã«ããã¤ããªã®ä¸ããè¦ã¤ãã¦ããããã¨ã³ããªãã¤ã³ãã¨ãã¦å¦çãéå§ããä»çµã¿ã«ãªã£ã¦ããããã§ããå¾ã£ã¦ãä½ãããªã (ret ããã ãã®) main ã¨ããã·ã³ãã«ãç¨æãã¦ãããã gcc 㧠libc ã¨ãªã³ã¯ãã¦ããã¨ãã¤ããªãå®è¡ããã¨ãã«ãã® main ã®ç®æããå¦çãå§ã¾ããã¨ã«ãªãã¾ãããã ãããªã³ã«ããã·ã³ãã«ãåç §ã§ããããã«ããããã«ã¯ã.global ãã£ã¬ã¯ãã£ãã§æ示çã«å ¬éãããã·ã³ãã«ãæå®ããå¿ è¦ãããã¾ãã
ããã gcc ã§ã³ã³ãã¤ã«ãgcc ã¯æ¡å¼µå .s ã®ãã¡ã¤ã«ã¯ã¢ã»ã³ããªãã¡ã¤ã«ã§ããã¨èªåå¤å®ãã¦ã³ã³ãã¤ã«ããªã³ã¯ãè¡ã£ã¦ããã¾ãã
% gcc do_nothing.s -o do_nothing
å®è¡ãã¦ã¿ã¾ãã
% ./do_nothing %
å½ç¶ä½ãèµ·ãã¾ãããæå³ããã¨ããã«åãã¦ãã¾ããldd ã§å ±æã©ã¤ãã©ãªã®ä¾åé¢ä¿ã確èªãã¦ã¿ã¾ãã
% ldd do_nothing linux-gate.so.1 => (0xffffe000) libc.so.6 => /lib/tls/libc.so.6 (0xb7eb0000) /lib/ld-linux.so.2 (0xb7feb000)
libc ã¨ãªã³ã¯ãã¦ããã®ããããã¾ãã
ã¢ã»ã³ããªè¨èªã§ã·ã¹ãã ã³ã¼ã«å¼ã³åºã
ä½ãããªããã¤ããªã§ã¯é¢ç½ããªãã®ã§ã決ã¾ãã® Hello World! ããã¨ããããã¨ããã§ããããä¸çç¸ã«ã¯ããã¾ãããããã§ããHello World! ãç»é¢ã«åºåããã«ã¯ã¢ã»ã³ããªè¨èªã§ x86 Linux ã«ã¼ãã«ã®ã·ã¹ãã ã³ã¼ã« (write(2)) ãå¼ã¶å¿ è¦ãããã®ã§ãããã®è¾ºã®è§£èª¬ã¯ http://www.nk.rim.or.jp/~jun/lxasm/int80.html ã詳ããã®ã§ãåç §ãã ããã
ç°¡åã«ã¾ã¨ããã¨ãã·ã¹ãã ã³ã¼ã«çªå·ã¨å¼æ°ãæ±ç¨ã¬ã¸ã¹ã¿ã«è¨å®ãã¦ã½ããã¦ã§ã¢å²ã込㿠0x80 ãçºè¡ããããªãã¡
- ã·ã¹ãã ã³ã¼ã«ã«ã¯ä¾ãã° exit(2) 㯠1ãwrite(2) 㯠4 ãªã©ã¨æ´æ°ã§çªå·ãæ¯ããã¦ãã
- å¼ã³åºãããã·ã¹ãã ã³ã¼ã«ã«å¯¾å¿ããçªå·ã eax ã«è¨å®ãã
- ã·ã¹ãã ã³ã¼ã«ã¸ã®å¼æ°ã ebx, ecx, edx, eci, edi, ebp ã«è¨å®ãã (å¼æ°ã1ã¤ãªã1ã¤ãã ebxã2 ã¤ãªã 1ã¤ç®ã ebx 2ã¤ç®ã ecx ...)
- ã½ããã¦ã§ã¢å²ã込㿠int 0x80 ãçºè¡ãã
ã¨ããæé ã§å½ä»¤ãåºããã¨ã§ã«ã¼ãã«ã«ã·ã¹ãã ã³ã¼ã«ãçºè¡ãããã¨ãã§ãã¾ãã
ã½ããã¦ã§ã¢å²ãè¾¼ã¿ã CPU ã«çºè¡ããã㨠CPU ã¯ãããããè¨å®ãããå²ãè¾¼ã¿ãã³ãã©ãå®è¡ãã¾ããx86 Linux ã§ã¯ 0x80 ã«è¨å®ãããå²ãè¾¼ã¿ãã¯ã¿ãã·ã¹ãã ã³ã¼ã«èµ·åå¦çã«å¯¾å¿ãã¦ãã¾ããå²ãè¾¼ã¿ãå¥æ©ã« CPU ã¯ç¹æ¨©ã¢ã¼ãã«ç§»ã£ã¦ã¹ã¿ãã¯ãã«ã¼ãã«ã¹ã¿ãã¯ã«åãæ¿ãããeax ã¬ã¸ã¹ã¿ããã·ã¹ãã ã³ã¼ã«çªå·ãåå¾ãã¦å¯¾å¿ããã·ã¹ãã ã³ã¼ã«ãèµ·åãã¾ãã
ã·ã¹ãã ã³ã¼ã«çªå·ã¨ã·ã¹ãã ã³ã¼ã«ã®å¯¾å¿ã¯ i386 Linux ã®å ´å i386/kernel/syscall_table.S ã«è¨è¿°ããã¦ãã¾ãã
ENTRY(sys_call_table) .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ .long sys_exit .long sys_fork .long sys_read .long sys_write .long sys_open /* 5 */ ...
ãã® sys_call_table ãã·ã¹ãã ã³ã¼ã«çªå·ã§æ¤ç´¢ããã¨å¯¾å¿ããã·ã¹ãã ã³ã¼ã«ã®ã·ã³ãã«åãåå¾ã§ããã¨ããæµãã§ããä¸è¨ãè¦ã¦ã確ãã« exit 㯠1ã write 㯠4 ã§ãã
ãªããæè¿ã® x86 ã§ã¯ int 0x80 å½ä»¤ã§ã®ã·ã¹ãã ã³ã¼ã«å¼ã³åºãã¯ãã§ã«å¤ããsysenter å½ä»¤ã使ã£ãæ¹ãããé«éã«å¦çãå¯è½ã¨ã®ãã¨ã§ãã
ã§ã¯ãint 0x80 å½ä»¤ã使ç¨ã㦠write(2) ãçºè¡ãã¦ã¿ã¾ããwrite(2) ãã¢ã»ã³ããªè¨èªã§èµ·åããã«ã¯
- eax ã« 4 ãè¨å®
- ebx ã«ãã¡ã¤ã«ãã£ã¹ã¯ãªãã¿ã®çªå·ãæå® (æ¨æºåºå㯠0çª)
- ecx ã«åºåããæååã®å é ã¢ãã¬ã¹ãæå®
- edx ã«åºåãããã¼ã¿ã®é·ããæå®
- int 0x80
ã¨ãªãã¾ãããã®å½ä»¤ããã®ã¾ã¾è¨è¿°ããã° OKã
.file "hello_world.s" .data msg: .ascii "Hello, World!\n" .global main main: movl $0x04, %eax # 0x04 = write(2) movl $0x00, %ebx # 0x00 = stdout movl $msg, %ecx movl $14, %edx int $0x80 ret
ã¨ãªãã¾ãã
- gas ã§ã¯ (1) .data ãã£ã¬ã¯ãã£ãã§ãã¼ã¿ã»ã¯ã·ã§ã³ã®éå§ãæå®ã㦠(2) ã¯ã©ã¼ããããæååãã«ã©ãã«æå® (msg:)ãã¤ã¤ãã®å é ã¢ãã¬ã¹ãå¾ãã $msg ã§åç §ããã¨ãã£ããã¨ãã§ãã¾ãã
- å³å¤ã¯ $0x04 ãªã© $ ãä»ãã¦è¨è¿°ãã¾ãã
- ã¬ã¸ã¹ã¿ã«ã¯ % ãä»ãã¾ãã
æååã®é·ãã 14 ã¨ãã¼ãã³ã¼ããã¦ãã¾ã£ã¦ãã®ãã¡ã¨ããµãã§ããããããããã®ããã«ã¨ããããã¯ããã§ããããå ã»ã©ã¨åãããã« gcc ã§ã³ã³ãã¤ã«ã
% ./hello_world Hello, World!
ã§ãã¾ãããä¸æ³ã
(è±ç·ãã®1) ã·ã³ãã«ã®ç¨®é¡
å°ãè±ç·ãreadelf -s ã§ãã¤ããªã®ã·ã³ãã«ã«é¢ããæ å ±ãè¦ãã¦ã¿ãã¨
% readelf -s hello_world | grep main 1: 00000000 231 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2) 71: 0804954a 0 NOTYPE GLOBAL DEFAULT 22 main 72: 00000000 231 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
㨠main ã NOTYPE ã«ãªã£ã¦ãã¾ããhttp://sourceware.org/binutils/docs-2.18/as/Type.html#Type ã«ããã°ãã·ã³ãã«ã®ç¨®é¡ã¯æ示çã« .type ãã£ã¬ã¯ãã£ãã§æå®ãããã¨ãå¯è½ã ããã§ãã
.file "hello_world.s" .data msg: .ascii "Hello, World!\n" .global main .type main, @function main: movl $0x04, %eax movl $0x00, %ebx movl $msg, %ecx movl $14, %edx int $0x80 ret
ã¨ã.type ãã£ã¬ã¯ãã£ãã追å ã㦠main ã¯é¢æ°ã§ããæ¨ãæè¨ãã¾ãããããã§ã³ã³ãã¤ã«ãããã¤ããªã¯
% readelf -s hello_world | grep main 1: 00000000 231 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2) 71: 0804954a 0 FUNC GLOBAL DEFAULT 22 main 72: 00000000 231 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
ã¨ãNOTYPE ã ã£ãã¨ããã FUNC ã«ãªãã¾ãã...ã¨ããã¾ã§ã¯ããã®ã§ãããå®éåé¡ããã NOTYPE ã ã£ãã FUNC ã ã£ããããã®ãä½ã«é¢ãã£ã¦ããããããããã£ã¦ãã¾ããã誰ãæãã¦ãã ããã
(è±ç·ãã®2) libc ã«ãªã³ã¯ããªããã¤ããªã«ãã
è±ç·ãã®2ã
% ls -la hello_world -rwxr-xr-x 1 naoya naoya 6849 2007-09-24 21:56 hello_world
ã¨ããã¾ã§ã§ä½ã£ããã¤ããªã®ãµã¤ãºãè¦ã㨠6,849 ãã¤ããããã¾ããHello, World ! ãåºåããã ããªã®ã«éåã¨å¤§ãããã·ã¹ãã ã³ã¼ã«ã¯ libc ãçµç±ããã«ç´æ¥å¼ã³åºãã¦ããããã§ãããããã°ã©ã ã§ãã£ã¦ããå¦ç㧠libc ã®æ©è½ãå¿ è¦ãªã®ã¯ main() ããããã°ã©ã ãèµ·åããã¨ããè¦ç´ã®å®è£ ãããã ãã§ããããã¯ä¸ä¸ libc ã使ããªããã¤ããªã«ä»ç«ã¦ä¸ãã¦ã¿ã¾ãããã
ld ã® -e (--entry) ãªãã·ã§ã³ãæå®ããã¨ãã©ã®ã·ã³ãã«ããå¦çãéå§ããããæ示çã«æå®ãããã¨ãã§ãã¾ãã
% as -o hello_world.o hello_world.s % ld -o hello_world -e main hello_world.o
ã¨ã¢ã»ã³ãã«ã¨ãªã³ã¯ãæ示çã«è¡ãã¾ãããã®å ´å libc ã¨ãªã³ã¯ããªããªãã®ã§ããã¤ããªã®ã©ãããå¦çãå§ããã°ããã OS ãããããªããªãã¾ãããã㧠-e ãªãã·ã§ã³ã§ main ãæå®ãã¦ããã®ã¢ãã¬ã¹ãæãã¦ããã¾ãã
% ldd hello_world not a dynamic executable
ldd ããã¨ãã©ã®å ±æã©ã¤ãã©ãªãå¿ è¦ã¨ããªããã¤ããªã«ãªã£ã¦ããã®ããããã¾ããæ°ã«ãªããµã¤ãºã®æ¹ã¯ã
% ls -la hello_world -rwxr-xr-x 1 naoya naoya 612 2007-09-24 21:54 hello_world
612ãã¤ããã ãã¶å°ãããªãã¾ãããã¡ããã¨å®è¡ã§ããã試ãã¦ã¿ã¾ãã
% ./hello_world Hello, World! [1] 25473 segmentation fault (core dumped) ./hello_world
ãã£ã¨ Hello, World! ãåºãã¾ã§ã¯ããã£ãã§ããããã§ã»ã°ãã©ãã³ã¼ããè¦ã¦ã¿ã¾ãã
main: movl $0x04, %eax movl $0x00, %ebx movl $msg, %ecx movl $14, %edx int $0x80 ret
write(2) ãå®è¡ããå¾ã«ãã£ã¦ããã®ã¯åã« ret ã§å¼ã³åºãå ã¸è¿ãã®ã¿...ããããåé¡ãlibc ä¸ã§ã¯ libc ã main ã®è¿å¤ãåãåã£ã¦ exit(2) ãå¼ã³åºããªãã¦ããå¾å¦çããã¦ããã¦ããã®ã§ main ãã㯠ret ããã ãã§ããã£ãããã§ããããã®ãã¤ããªã¯ libc ã¨ãªã³ã¯ãã¦ãªãããã§ã誰ããããªé¢åãè¦ã¦ãããªãã®ã§ãã
ããã§ãexit(2) å¼ã³åºããèªåã§æ¸ãã¾ããwrite(2) ã®ã¨ãã¨æé ã¯ã»ã¨ãã©ä¸ç·ã
.file "hello_world.s" .data msg: .ascii "Hello, World!\n" .global main .type main, @function main: movl $0x04, %eax # write (2) movl $0x00, %ebx # stdout movl $msg, %ecx movl $14, %edx int $0x80 movl $0x01, %eax # exit movl $0x00, %ebx # exit(0) int $0x80
ããã§ã»ã°ãã©ããªããªãã¾ãã
ãªããHello World! 㪠ELF ãã¤ããªã極éã¾ã§å°ããããã¨ãã話é¡ã¯ãã®è¾ºãå¤æ çã§æ¥½ããã§ãã
C ã¨ã¢ã»ã³ããªã³ã¼ããæ··ãã
è±ç·ããããã®ã§æ¬è«ã¸ãgas ã§ã®ã³ã¼ãã®æ¸ãæ¹ã¯ã ãããåãã£ã¦ããã¨ããã§ã次㯠C è¨èªã¨ã¢ã»ã³ããªè¨èªã(ã¤ã³ã©ã¤ã¢ã»ã³ããªã使ããã«) æ··ããããã°ã©ã ã«ãã¦ã¿ã¾ããã¨ãã£ã¦ãä¸ã¤ã®ãã¡ã¤ã«ã«äºç¨®é¡æ¸ããããããªããããããåå¥ã®ãã¡ã¤ã« .c ãã¡ã¤ã«ã¨ .s ãã¡ã¤ã«ã¸ã
- å¼æ°ãäºã¤åãåã£ã¦ãã®äºã¤ã®æ°ã足ãã¦è¿ã add ã¨ããé¢æ°ãã¢ã»ã³ããªè¨èªã§
- add ãå¼ã³åºãã¦å®è¡ãã main() ã C ã§
ããããæ¸ãã¦ãªã³ã¯ããã¦é¢æ°å¼ã³åºãã®è£å´ãè¦ã¦ã¿ã¾ãã
ã¾ã㯠C ã®å´ããã
#include <stdio.h> int main() { printf("%d\n", add(3, 5)); return 0; }
ä½ã®å¤å²ããªããã¾ã add ãç¨æããã¦ãªãã®ã§å®è¡ãã¡ã¤ã«ã¯ä½ãã¾ããããªãã¸ã§ã¯ããã¡ã¤ã«ã«ã¯ã§ãã¾ãã
% gcc -c add_main.c -o add_main.o
ã§ããã®ãªãã¸ã§ã¯ããã¡ã¤ã«ã readelf ãã¦ã¿ã¾ãã
% readelf -s add_main.o ã·ã³ãã«ãã¼ãã« '.symtab' 㯠11 åã®ã¨ã³ããªããæ§æããã¦ãã¾ã: çªå·: å¤ ãµã¤ãº ã¿ã¤ã Bind Vis ç´¢å¼å 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS add_main.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 4 5: 00000000 0 SECTION LOCAL DEFAULT 5 6: 00000000 0 SECTION LOCAL DEFAULT 6 7: 00000000 0 SECTION LOCAL DEFAULT 7 8: 00000000 71 FUNC GLOBAL DEFAULT 1 main 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND add 10: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
add ã printf ã UND (Undefined) ã§ããprintf 㯠libc ããåãã¦ãããadd ã¯èªåã§å®è£ ãããã¨ããããã§ãããã® add ãèªåã§å®è£ ããã¨ããã®ã¯ã©ããããã¨ããlibc ã main ãæå¾ ãã¦ããã®ã§ main ã¨ããã·ã³ãã«ã®å ã«ãµãã«ã¼ãã³ãä½ã£ãã®ã¨åãããadd ãæå¾ ããã¦ããã®ã§ add ã¨ããã·ã³ãã«ã®å ã«ãµãã«ã¼ãã³ãå®ç¾©ãã.global æå®ããã° OKã
ããä¸ã¤å¥ã®è¦æ¹ããã¦ã¿ã¾ããgcc -S 㧠C ãã³ã³ãã¤ã«ãã段éã§ã¨ãã¦ã¢ã»ã³ããªè¨èªã§å¦çãè¦ã¦ã¿ã¾ãã
% gcc -S add_main.c -o add_main.s
add_main.s ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
1 .file "add_main.c" 2 .section .rodata 3 .LC0: 4 .string "%d\n" 5 .text 6 .globl main 7 .type main, @function 8 main: 9 pushl %ebp 10 movl %esp, %ebp 11 subl $8, %esp 12 andl $-16, %esp 13 movl $0, %eax 14 addl $15, %eax 15 addl $15, %eax 16 shrl $4, %eax 17 sall $4, %eax 18 subl %eax, %esp 19 movl $5, 4(%esp) 20 movl $3, (%esp) 21 call add 22 movl %eax, 4(%esp) 23 movl $.LC0, (%esp) 24 call printf 25 movl $0, %eax 26 leave 27 ret 28 .size main, .-main 29 .section .note.GNU-stack,"",@progbits 30 .ident "GCC: (GNU) 3.4.6 (Debian 3.4.6-5)"
ãããããã¡ããã¡ãã¨ããã®ã§ããã注ç®ããã®ã¯ 21 è¡ç®ã"call add" 㧠add ã¨ããã«ã¼ãã³ãå¼ã°ãã¦ãã¾ãããã® add ãã¾ã å®ç¾©ããã¦ãªããå¾ã£ã¦ãã® add ã¨ãããµãã«ã¼ãã³ãä»ã®ãã¡ã¤ã«ã§å®ç¾©ãã¦ãã£ã¦ãªã³ã¯ããã° OKãã¨ããã®ããããã¾ãã
add.s ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
1 .file "add.s" 2 .global add 3 .type add, @function 4 5 add: 6 pushl %ebp 7 movl %esp, %ebp 8 movl 12(%ebp), %eax # y => 12(%ebp) 9 addl 8(%ebp), %eax # x => 8(%ebp) 10 popl %ebp 11 ret
ãã® add 㯠Cè¨èªã®é¢æ°å¼ã³åºãã®è¦ç´ (cdecl 呼出規約 - Wikipedia) ãã¢ã»ã³ããªè¨èªã§å®è£ ãããã®ã«ãªãã¾ãããã®è¾ºã®è§£èª¬ã¯ (ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®è§£èª¬ãå«ã㦠) gccのx86インラインアセンブリに関して ãå ·ä½çã§åãããããã¨æãã¾ãã
Cã®é¢æ°å¼ã³åºãè¦ç´ã§ã¯é¢æ°ã®å¼æ°ã¯ãã®ããã°ã©ã ã®ã¹ã¿ãã¯é åã«ç©ã¾ãã¾ããå¼ã³åºãããå´ã®é¢æ°ã§ããã¨ããã® add ã§ã¯å¼æ°ãã¹ã¿ãã¯ããåãåºãã¦è¶³ãç®ãè¡ããçµæãå¼ã³åºãå ã«è¿å´ãã¾ãã
- ç¾å¨ã®ã¹ã¿ãã¯ãããã®ã¢ãã¬ã¹ã¯ esp ã«è¨å®ããã¦ãã
- x86 ã®å ´åã¹ã¿ãã¯ã¯ä¸ä½ããä¸ä½ã«ä¼¸å¼µãã
- å¾ãã®å¼æ°ããé ã«ã¹ã¿ãã¯ã«ç©ã¾ãããé¢æ°ã®æ»ãã¢ãã¬ã¹ãè©°ã¾ããã (ããã§ã¯ int y â int x â æ»ãã¢ãã¬ã¹ã®é )
- ç¶ã7è¡ç®ã§ ebp ã¬ã¸ã¹ã¿ã®å¤ãç ´å£ããã®ã§ãå ã®å¤ã¯äºåã«ã¹ã¿ãã¯ã«ç©ãã§(push ãã¦)éé¿ãã¦ãã (6è¡ç®)
- å¼æ°ãåãåºãã®ã« esp ããã®ã¾ã¾ä½¿ãã¨è²ã é¢åãªã®ã§ããã ebp ã«è¨å®ãã (7è¡ç®)
- ebp ããè¦ãã¨ãebp + 8ãã¤ããã«ç¬¬ä¸å¼æ°ãebp + 12ãã¤ãã«ç¬¬äºå¼æ°ããç©ã¾ãã¦ãã
- ebp 㯠32 ãããã¬ã¸ã¹ã¿ãªã®ã§ 4 ãã¤ã
- ãebp + 4ãã¤ããã«ã¯æ»ãã¢ãã¬ã¹
- å¼æ°ã¯ãããã int ãªã®ã§ 4 ãã¤ã âãå¼æ°ã¯ ãebp + 8 ãã¤ãããebp + 12 ãã¤ããã«ç©ã¾ãã¦ãã
- ãebp + 8ãã¤ãã㯠gas ã§ã¯ 8(%ebp) ã¨ããéæ¥åç §ã¨å¼ã°ããææ³ã§æå®ããã(C ã§è¨ãã¨ããã® a[i] ã¿ãããªãã)
- 12(%ebp) ã§ç¬¬äºå¼æ°ãåãåºã㦠eax ã«è¨å® (8è¡ç®)
- 8(%ebp) ã§ç¬¬ä¸å¼æ°ãåãåºã㦠eax ã«è¶³ããã (9è¡ç®)
- é¢æ°ã®æ»ãå¤ã¯ eax ã«çªã£è¾¼ãã§ããã¨ãã決ã¾ãããã§ã« eax ã«ã¯ x + y ã®çµæãå ¥ã£ã¦ãã
- æåã«éé¿ãã¦ããã ebp ã®å¤ãã¹ã¿ãã¯ããåãåºã (pop ãã) (10è¡ç®)
ã¨ããæµãã«ãªãã¾ããå³ãæãã¨åãããããã§ãã(å¾ã§å³ã追å ãã¾ãã)
ãã㧠mainãadd ãæã£ãã®ã§å®è¡ãã¡ã¤ã«ãä½ãã¾ãã
% gcc *.s -o add % ./add 8
add() ã« 3 㨠5 ã渡ããã 8 ã«ãªãã¾ãããã¡ããã¨åãã¦ã¾ãã
ã¤ã³ã©ã¤ã³ã¢ã»ã³ããª
ãã¦ãåæ¯ããé·ããªãã¾ããããããããæ¬çªãgcc æ¡å¼µæ©è½ã®ã¤ã³ã©ã¤ã³ã¢ã»ã³ãã©ã使ã£ã¦ãå¥ã ã«ãªã£ã¦ãã C ã«ãã main() ã¨ã¢ã»ã³ããªè¨èªã«ãã add ãä¸ã¤ã® .c ãã¡ã¤ã«ã®ä¸ã«å®ç¾©ãã¾ãã
ã¤ã³ã©ã¤ã³ã§ã¢ã»ã³ããªè¨èªã®ã³ã¼ãã C ã®ã½ã¼ã¹ã«åãè¾¼ãã«ã¯ asm() ã¨ãããã¼ã¯ã¼ãã使ãã¾ãã(ANSI C ã§ã¯ asm ã¯ä½¿ãã¾ãããgcc -std=c99 ããã¦ãå ´å㯠__asm__ ã使ãã¾ããasm ã __asm__ ãåãã§ãã) asm() ã®ä¸ã«æåå㧠gas ã®æ§æãæ¸ãã° OK ã§ãã
#include <stdio.h> int add(int x, int y) { asm( "movl 8(%ebp), %eax;" "addl 12(%ebp), %eax" ); } int main () { printf("%d\n", add(3, 5)); return 0; }
ã¨ãªãã¾ãã
å ã»ã©ã® add.s ã«æ¯ã¹ãã¨ã¢ã»ã³ããªã³ã¼ãã 4 è¡æ¸ãã¾ããããã㯠asm() ã§å¦çãè¨è¿°ããå ´æããã§ã« C ã®é¢æ°å ãªã®ã§ãé¢æ°å¼ã³åºãè¦ç´ã®å®è£ ã«ç¸å½ãã ebp ã®éé¿ã esp ã®ã³ãã¼çãå¿ è¦ãªã (ã³ã³ãã¤ã©ããã®é¨åã³ã¼ããçæãã¦ããã) ããã§ãã
é¢æ°ã®æ»ãå¤ã¯ eax ã«ç©ãã®ã§ãããä¸è¨ã§ã¯ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®å¦çãçµãã£ãæç¹ã§è¨ç®çµæ㯠eax ã«å ¥ã£ã¦ããã®ã§ãreturn ãªã©ããã«é¢æ°ãçµãã¦ãã¾ãã
% gcc -Wall inline_add.c -o inline_add inline_add.c: In function `add': inline_add.c:9: è¦å: å¶å¾¡ãé void é¢æ°ã®çµãã«å°éãã¾ãã
ã¨ãreturn ãæ¸ãã¦ããªãã®ã§ã³ã³ãã¤ã«æã«è¦åã¯åºã¾ããã¢ã»ã³ããªã¬ãã«ã§ã¯ return ããã®ã¨åãã³ã¼ããåãããã®ã§å¤§ä¸å¤«ã§ããå®è¡ãã¦ã¿ã¾ãããã
% ./inline_add 8
æ£ãã 8 ãåºåããã¾ããã
ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§æ¸ããã³ã¼ãã¯ã©ã®ããã«åºåãããã§ãããããgcc -S ã§ã³ã³ãã¤ã«ãã¦ç¢ºèªãã¦ã¿ã¾ãã
% cat inline_add.s .file "inline_add.c" .text .globl add .type add, @function add: pushl %ebp movl %esp, %ebp #APP movl 8(%ebp), %eax;addl 12(%ebp), %eax #NO_APP popl %ebp ret .size add, .-add .section .rodata .LC0: .string "%d\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp movl $5, 4(%esp) movl $3, (%esp) call add movl %eax, 4(%esp) movl $.LC0, (%esp) call printf movl $0, %eax leave ret .size main, .-main .section .note.GNU-stack,"",@progbits .ident "GCC: (GNU) 3.4.6 (Debian 3.4.6-5)"
ã¨ãªãã¾ããä¸è¦åããã«ããã®ã§ãadd() ã«ç¸å½ããã¨ããã ãã«çµãã¨
add: pushl %ebp movl %esp, %ebp #APP movl 8(%ebp), %eax;addl 12(%ebp), %eax #NO_APP popl %ebp ret
ã§ããã ä¸è¡ã§ç¹ãã£ã¦ãã¾ã£ã¦ã¾ãã #APP ã #NO_APP ã§å²ã¾ããç®æãã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§åãè¾¼ãã ã³ã¼ãã«ç¸å½ããã®ãåããã¾ããåå¾ã®ã³ã¼ããå«ããå ã«ç´ ã§æ¸ããã¢ã»ã³ããªã³ã¼ãã¨ã¾ã£ããåãå½ä»¤ã並ãã§ãã¾ãã
x86æ¡å¼µã¤ã³ã©ã¤ã³ã¢ã»ã³ããª
ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§ã¢ã»ã³ããªã³ã¼ããåãè¾¼ããããã«ãªã£ãã¨ããã§ã次㯠x86 æ¡å¼µã¢ã»ã³ããªã使ã£ã¦ Cè¨èªå´ã§ç¢ºä¿ããã¡ã¢ãªé åã¨ã®ããã¨ããã¹ãã¼ãã«ãã¦ã¿ã¾ãã
å ã®ã³ã¼ãã§ã¯ã¹ã¿ãã¯ã«ç©ã¾ããé¢æ°ã®å¼æ°ãåå¾ããã®ã« 8(%ebp) ã 12(%ebp) ãªã© ebp ã¬ã¸ã¹ã¿ãæèããè¨è¿°ããã¾ãããã¾ãæ»ãå¤ã eax ã«ç©ã¾ããã¨ããè¦ç´ãåæã«ãã¾ãããæãããã¾ãã
ããã§
- ããããå¼æ°ã§ãã x ã y ã¯é¢æ°å é¨ã§ã¯å¤æ°ã¨ãã¦åç §ã§ããããã§ããããã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®ä¸ã§ä½¿ããã° ebp ãæèããã«æ¸ãã
- ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®ä¸ã§è¨å®ãããå¤ã C ã®å¤æ°ã«æ¸ãåºããã¨ãã§ããã° C å´ã®å¤æ°ã«å¤ãã»ããã㦠return æã§ãããè¿ããã¨ãã§ãã
ã¨ãããã¨ãè¨ãã¾ãããã®ãã㪠C å´ã§ç¢ºä¿ããã¡ã¢ãªé åã¨ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®ã³ã¼ãã®é£æºãå®ç¾ããã®ã x86 æ¡å¼µã¤ã³ã©ã¤ã³ã¢ã»ã³ããªæ§æã§ãã
- asm(ã¢ã»ã³ããªãã³ãã¬ã¼ã : åºåãªãã©ã³ã : å ¥åãªãã©ã³ã : ç ´å£ãããã¬ã¸ã¹ã¿ã®ãªã¹ã)
ã¨ããæ§æã使ãã¨ãä»»æã®ã¬ã¸ã¹ã¿ã C ã®å¤æ°ã«æ¸ãåºããããC ã®ä»»æã®å¤æ°ã®å 容ãä»»æã®ã¬ã¸ã¹ã¿ã«è¨å®ããä¸ã§ã¢ã»ã³ããªã®å¦çãé²ããããããã¨ãã§ãã¾ãã
x86 æ¡å¼µã¤ã³ã©ã¤ã³ã¢ã»ã³ããªæ§æã«ã¤ãã¦ã¯
ã詳ããåèã«ãªãã¾ãã
ä¾ãã°
asm( "movl $0x01, %eax;" "addl $0x05, %eax" );
ã¨ããã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã¯ (1) å³å¤ 0x01 ã eax ã«è¨å® (2) å³å¤ 0x05 ã eax ã«è¶³ããããã¨ãããã¨ããã£ã¦ãã¦ãã®å¦çãçµãã£ãç´å¾ã« eax 㯠0x06 ã«ãªã£ã¦ãã¾ãããã® eax ã«è¨å®ããã足ãç®ã®çµæã C ã®å¤æ°ã«æ ¼ç´ãããå ´åã¯æ¡å¼µæ§æã§
int result; asm( "movl $0x01, %%eax;" "addl $0x05, %%eax" : "=a" (result) );
ã¨æ¸ããã¨ãã§ãã¾ãã
- ååã®æååé¨åãã¢ã»ã³ããªãã³ãã¬ã¼ã
- ã¢ã»ã³ããªãã³ãã¬ã¼ãå ã§ã¯ã¬ã¸ã¹ã¿ã¯ "%%eax" 㨠% ã2ã¤æå®ãã¦è¨è¿°ããå¿ è¦ãããã¾ã
- : 以éãåºåãªãã©ã³ãã®æå®
- å ¥åãªãã©ã³ããç ´å£ãããã¬ã¸ã¹ã¿ã®ãªã¹ãã¯ä½¿ããªãã®ã§çç¥
ã¨ãªã£ã¦ãã¾ãã
åºåãªãã©ã³ãã®æå®ç®æããã¤ã³ãã§ãã"=a" (result) ã¯ãã¢ã»ã³ããªã®å¦çã®æå¾ã« eax ã«è¨å®ãããå¤ã result ã¨ããå¤æ°ã«æ¸ãåºããªãããã¨ããæå®ã«ãªãã¾ãããã®æå®ã«å¾ã£ã¦ãresult ã« 0x06 ãä»£å ¥ããããã¨ã«ãªãã¾ãã
å ¥åãªãã©ã³ããæå®ãã¦ã¿ã¾ããããä¾æã®ä¸ã§å³å¤ã§ 0x01 ã 0x05 ã¨ãã¦ããç®æã C ã®å¤æ°ã«ã»ãããããå¤ã使ãããã«å¤æ´ãã¦ã¿ã¾ãã
int x = 1, y = 5; int result; asm( "movl %2, %%eax;" "addl %1, %%eax" : "=a" (result) : "m" (x), "m" (y) );
ã"m" (x), "m" (y)ããå ¥åãªãã©ã³ãã®æå®ã§ãã
- ã¡ã¢ãªä¸ã« xãy ãè¨å®ãããã®å¤ãã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®ä¸ããæå®ã§ããããã«ãã¦ãã¾ã
- ã¢ã»ã³ããªãã³ãã¬ã¼ãã®ä¸ã® %1 ã %2 ããå
¥åºåãªãã©ã³ãã«æå®ããå¤ãåç
§ããããã®æ示è©
- %0 ã result
- %1 ã x
- %2 ã y
ã§ãããã㧠x ã y ã«ä»£å ¥ããã¦ããå¤ã使ã£ã¦è¨ç®ãè¡ããã¾ãã
ããã«ããå°ãçããã¦ã¿ã¾ããä¸è¨ã®ã³ã¼ãã§ã¯
- x = x + y ã¨ãã¦çµæã x ãç ´å£ãã¦åãåãããã«ããããã®å ´å result ã¯è¦ããªãã
- æ示çã« eax ãçµç±ãã¦è¨ç®ãè¡ã£ã¦ããããå½ä»¤çã«ã¯ x + y ãã¦ãã ããªã®ã§ãã®ããã«è¨è¿°ã
ãããå å³ããã¨
int x = 1, y = 5; asm( "addl %2, %0;" : "=r" (x) : "0" (x), "m" (y) );
ã¨ãªãã¾ãã
- ãã®å ´å x ã¯å ¥åºåå ¼ç¨ã
- å ¥åãªãã©ã³ã㧠"0" ã¨ããã®ã¯ã¢ã»ã³ããªãã³ãã¬ã¼ãå 㧠%0 ã¨åçã®æå³ãæã¡ããã®ããã«æ¸ããã¨ã§ x ãå ¥åºåå ¼ç¨ã§ãããã¨ãæå®ãããã¨ãã§ãã¾ã
- åºåãªãã©ã³ãã«æå®ãã "=r" ã¯ä»»æã®ã¬ã¸ã¹ã¿ãæå³ãããã®ã§ãx ç¨ã«ä»»æã®ã¬ã¸ã¹ã¿ãå²ãå½ã¦ã¦ãã®å 容ãæå¾ã« x ã«æ¸ãåºãã¦ããã¨ããæå®ã«ãªãã¾ã
- ãã㧠%0 ã xã%2 ã yãçµæ㯠x ã«åºåãã ... ã¨ããæºåã¯æ´ãã¾ãããaddl %2, %0 㧠x = x + y ç¸å½ã®å½ä»¤ãè¨è¿°ã§ãã¾ã
ããã¾ã§ããã°å ã® add() é¢æ°ãã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®ã³ã¼ããæ¡å¼µæ§æã使ã£ã¦æ¸ãç´ããã¨ãã§ãã¾ããã以ä¸ã®ããã«ãªãã¾ããã
#include <stdio.h> int add(int x, int y) { asm( "addl %2, %0;" : "=r" (x) : "0" (x), "r" (y) ); return x; } int main () { printf("%d\n", add(3, 5)); return 0; }
å¼æ°ã® xãy ãåãåã£ã¦ x = x + y ãã¦ãã®çµæã return ãã¦ãã¾ãã
ãã¯ã + ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§ã¤ã³ã©ã¤ã³å±é
ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªãªã³ã¼ãã¯ãã¡ãããã¯ãã«ä½¿ããã¨ãã§ãã¾ããå ã® add() ãé¢æ°ã§ãªããã¯ãã¨ãã¦å®ç¾©ããã¨ä»¥ä¸ã®ããã«ãªãã¾ãã
#include <stdio.h> #define add(x, y) \ ({ \ int _x = (x), _y = (y); \ asm( \ "addl %2, %0;" \ : "=r" (_x) \ : "0" (_x), "r" (_y) \ ); \ _x; \ }) int main () { printf("%d\n", add(3, 5)); return 0; }
å½ç¶ã§ããããã¯ãã«ããå ´åå¼æ°ã® x, y ã«ã¯ã¡ã¢ãªã¯å²ãå½ã¦ããã¦ããªãã®ã§ãããç´æ¥æ¡å¼µæ§æã®å ¥åºåãªãã©ã³ãã«æå®ãããã¨ã¯ã§ãã¾ããããã㧠int _x = (x) ã¨æ°ãã«å¤æ°ãç¨æãã¦ããã«å¤ãæ ¼ç´ããã®å¤æ°ãå ¥åºåãªãã©ã³ãã¨ãã¦æå®ãã¾ãã
ãã®ãã¯ãã§å®ç¾©ãã add() ã¯ãã³ã³ãã¤ã©ãã¤ã³ã©ã¤ã³å±éãã¦ããã¾ããããã«ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®ã³ã¼ããå±éããã¾ãã試ãã«ä¸è¨ã³ã¼ãã®ã³ã³ãã¤ã«æ¸ã¿ã®ã¢ã»ã³ããªã³ã¼ããè¦ã¦ã¿ã¾ãã
% cat macro_add.s .file "macro_add.c" .section .rodata .LC0: .string "%d\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $24, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp movl $3, -4(%ebp) // int _x = 3 movl $5, -8(%ebp) // int _y = 5 movl -4(%ebp), %edx // _x ã®å¤ã edx ã«è¨å® movl -8(%ebp), %eax // _y ã®å¤ã eax ã«è¨å® #APP addl %eax, %edx; // å ç® #NO_APP movl %edx, %eax // å ç®çµæã eax ã«è¨å® movl %eax, -4(%ebp) // eax ã®å¤ã _x ã«è¨å® movl -4(%ebp), %eax movl %eax, 4(%esp) movl $.LC0, (%esp) call printf movl $0, %eax leave ret .size main, .-main .section .note.GNU-stack,"",@progbits .ident "GCC: (GNU) 3.4.6 (Debian 3.4.6-5)"
add ã®å®ç¾©ã¯ãªããmain ã®å®ç¾©å ã«å種å¦çãç´æ¥ã¤ã³ã©ã¤ã³å±éããã¦ããã®ãåããã¾ãã(ãã®ã³ã¼ãèªä½ã¯å°ã æé©åã®ä½å°ãæ®ã£ã¦ãããã§ãã) ãã®ããã«ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªããã¯ãå®ç¾©ãã¦ãããã¨ã§ add(3, 5) ã®ããã«ããããé¢æ°ã®ããã«è¦ãããã¦ãã¤ã³ã©ã¤ã³ã«ä»»æã®ã¢ã»ã³ããªå½ä»¤ãåãè¾¼ããã¨ãã§ãã¾ãã
åé ã§ã¿ãã¬ã¸ã¹ã¿éé¿å¦çãè¡ã switch_to() ã¯ãã®ææ³ã§ãã¯ãã¨ãã¦å®ç¾©ããã¦ãã¾ããã«ã¼ãã«ã®ã³ã³ããã¹ãã¹ã¤ããã¯é常ã«é »ç¹ã«å®è¡ãããå¦çãªã®ã§ããã¯ãã§ã¤ã³ã©ã¤ã³å±éããããã¨ã«ããæ§è½ã稼ãã§ãããã®ã¨æããã¾ãã
ã·ã¹ãã ã³ã¼ã«ãã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§
å°ãè±ç·æ°å³ã«ãªãã¾ãããã¢ã»ã³ããªè¨èªããã®ã·ã¹ãã ã³ã¼ã«å¼ã³åºã (write(2) / exit(2)) ãã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§æ¸ãã¦ã¿ã¾ããã¾ãã¯ããããããã®ããæ¡å¼µæ§æãªãã§ãå ã«è¦ãã¢ã»ã³ããªã§ã® write(2) ã exit(2) ã®è¨è¿°ãã¤ã¾ãæ±ç¨ã¬ã¸ã¹ã¿ã«ã·ã¹ãã ã³ã¼ã«çªå·ã¨å¼æ°ãç©ã㧠int 0x80 ãªã³ã¼ãããã®ã¾ã¾ asm() å ã«æ¸ãã ãã
int my_write(const char *str, int len) { asm( "movl $0x04, %eax;" "movl $0x00, %ebx;" "movl 8(%ebp), %ecx;" "movl 12(%ebp), %edx;" "int $0x80" ); } int my_exit(int st) { int ret = 0; asm( "movl $0x01, %eax;" "movl 8(%ebp), %ebx" ); return ret; } int main() { my_write("Hello, World!\n", 14); my_exit(0); return -1; }
ã¨ãªãã¾ãã
次ã«ãã®ã³ã¼ããæ¡å¼µæ§æã使ã£ã¦ããå°ã綺éºã«ãã¾ããä¾ãã° my_write() ã®ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§ write(2) ãå¼ãã§ãããã§ãããæ¹ã㦠wirte(2) ã®å¼ã³æ¹ãæ¯ãè¿ãã¨
- eax ã«ã·ã¹ãã ã³ã¼ã«çªå· 0x04 ãè¨å®
- ebx ã«æ¨æºåºåã®ãã¡ã¤ã«ãã£ã¹ã¯ãªãã¿ 0x00 ãè¨å®
- ecx ã«æååã®å é ã¢ãã¬ã¹ (str) ãè¨å®
- edx ã«ãã¼ã¿ã®é·ã(len) ãè¨å®
- int 0x80
ã¨ãªãã¾ãããã㧠ecx ã« str ã®å¤ãå ¥åããã«ã¯æ¡å¼µæ§æã¨ãã¦å ¥åãªãã©ã³ãã® "c" (str) ã使ãã¾ãããåæ§ã« edx ã« len 㯠"d" (len) ã¨è¨è¿°ã§ãã¾ãããã®å®¹é㧠C ã®å¤æ°ã¨é£æºãåã£ã¦ä½åãªã³ã¼ããçãã¾ãã
int my_write(const char *str, int len) { int ret = 0; asm( "movl $0x04, %%eax;" "movl $0x00, %%ebx;" "int $0x80" : "=a" (ret) : "c" (str), "d" (len) ); return ret; } int my_exit(int st) { int ret = 0; asm( "movl $0x01, %%eax;" "int $0x80" : "=a" (ret) : "b" (st) ); return ret; } int main() { my_write("Hello, World!\n", 14); my_exit(0); return -1; }
ã¨ãªãã¾ãããããã§åé¡ãªãåãã¾ãããã®ããã« C ã®å¤æ°ã«æ ¼ç´ãããå¤ãã·ã¹ãã ã³ã¼ã«ã®å¼æ°ã«ç¸å½ããå種æ±ç¨ã¬ã¸ã¹ã¿ã«ç©ãæç¶ããå ¥åãªãã©ã³ãã®æå®ã§æ¸ã¾ãã¦ããã®ããã½ã§ããã
Linux 2.6 ã® switch_to() ãèªã¿è§£ã
é§ã足ã§ãããããã¾ã§ã§ x86 ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®èª¬æã¯çµãããããããæ¬ä¸¸ãswitch_to() ã®ä¸ãæ¹ãã¦è¦ã¦ã¿ã¾ãã
14 /* 15 * Saving eflags is important. It switches not only IOPL between tasks, 16 * it also protects other tasks from NT leaking through sysenter etc. 17 */ 18 #define switch_to(prev,next,last) do { \ 19 unsigned long esi,edi; \ 20 asm volatile("pushfl\n\t" /* Save flags */ \ 21 "pushl %%ebp\n\t" \ 22 "movl %%esp,%0\n\t" /* save ESP */ \ 23 "movl %5,%%esp\n\t" /* restore ESP */ \ 24 "movl $1f,%1\n\t" /* save EIP */ \ 25 "pushl %6\n\t" /* restore EIP */ \ 26 "jmp __switch_to\n" \ 27 "1:\t" \ 28 "popl %%ebp\n\t" \ 29 "popfl" \ 30 :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ 31 "=a" (last),"=S" (esi),"=D" (edi) \ 32 :"m" (next->thread.esp),"m" (next->thread.eip), \ 33 "2" (prev), "d" (next)); \ 34 } while (0)
åªæã®ããã ã£ãã³ã¼ãã§ãããããã¾ã§ã§èª¬æããå 容ã«ç §ããåããã¨
- ãã¯ã㧠switch_to() ãå®ç¾©ããã¦ãã
- asm () ã使ã£ãã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§å種å½ä»¤ãè¨è¿°ããã¦ãã
- æ¡å¼µæ§æ㧠prev ã next ãã®ãªãã¸ã§ã¯ããä¿æããå¤ãã¬ã¸ã¹ã¿ã«è¨å®ãã¦æ¼ç®ãã¦ãã
ã¨ãããã¨ãåããã¨æãã¾ãã(asm volatile (...) ã® volatile ã¯ã³ã³ãã¤ã©ã®æé©åæå¶ãæå³ãã¾ãããã®ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã®ã³ã¼ããã³ã³ãã¤ã©ã«ããæé©åã§æå³ããªãã³ã¼ãã«ãªã£ã¦ãã¾ãã®ãé²ãããã®å¦ç½®ã§ãã)
æ¡å¼µæ§æã®ã¾ã¾ã§ãã¨å ¥å/åºåãã©ããªã£ã¦ããããå«ããå½ä»¤ã®æµãããããã«ããã®ã§ããã®ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã³ã¼ããå±éãã¦ã¿ã¾ãã
/* å ¥åãªãã©ã³ãã®å¦ç */ movl prev, %eax movl next, %edx /* æ¬ä½ */ pushfl /* Save flags */ pushl %ebp movl %esp, prev->thread.esp /* save ESP */ movl next->thread.esp, %esp /* restore ESP */ movl $1f, prev->thread.eip /* save EIP */ pushl next->thread.eip /* restore EIP */ jmp __switch_to 1: popl %ebp popfl /* åºåãªãã©ã³ãã®å¦ç */ movl %eax, last movl %esi, esi movl %edi, edi
å®éã«ã¯ã¢ã»ã³ããªè¨èªå 㧠prev->thread.esp ã¨ãã£ãåç §ã®ä»æ¹ã¯ã§ããªãã®ã§ãã®ã³ã¼ãã¯é§ç®ãªãã§ãããæ¬ä¼¼ã³ã¼ãã¨ãããã¨ã§ã²ã¨ã¤ã
ãã㧠prev ã next (ã㨠last) ã¯ããã»ã¹ãã¹ã¬ããã®ã«ã¼ãã«å é¨ã§ã®ãã¼ã¿è¡¨ç¾ã§ãã task_struct æ§é ä½ã®ã¤ã³ã¹ã¿ã³ã¹ã§ããtask_struct æ§é ä½ã®ã¤ã³ã¹ã¿ã³ã¹ã¯ããã»ã¹ãã£ã¹ã¯ãªãã¿ã¨å¼ã°ãã¾ããããã»ã¹ãã£ã¹ã¯ãªãã¿ã¯ã«ã¼ãã«å æ§é ä½ã®ä¸ã§ãé常ã«éè¦ãªãªãã¸ã§ã¯ãã§ãããã«ããã»ã¹ã®ç¶æ ãã¢ãã¬ã¹ç©ºéã®æ å ±çãããã°ã©ã ãå®è¡æã«å®ä½åãããå¾ã«å¿ è¦ãªæ å ±ãè©°ã¾ã£ã¦ãã¾ããå®è¡ã³ã³ããã¹ããåãæ¿ããã¨ããã®ã¯çµå±ã
- prev ã®ã¡ã¢ãªç©ºéã next ã®ã¡ã¢ãªç©ºéã¸åãæ¿ãã
- prev ã®ãã¼ãã¦ã§ã¢ã³ã³ããã¹ã (CPU ã®ã¬ã¸ã¹ã¿ã«è¨å®ãããå¤) ã prev å ã®é åã«éé¿
- next å ã®é åã«ãããã¼ãã¦ã§ã¢ã³ã³ããã¹ãã復帰
ã¨ããå¦çã®ãã¨ã«ãªãã¾ãããã¼ãã¦ã§ã¢ã³ã³ããã¹ãã®éé¿ã¯
- ä¸é¨ãããã»ã¹ãã£ã¹ã¯ãªãã¿å ã«
- ä¸é¨ãã«ã¼ãã«ã¢ã¼ãããã»ã¹ã¹ã¿ãã¯ã«
æ ¼ç´ãããã¨ã§è¡ããã¾ããåè ãæ ¼ç´ããå ´æãè¦ã¦ã¿ã¾ããinclude/linux/sched.h ã« task_struct ã®å®ç¾©ãããã¾ãã
struct task_struct { .... /* CPU-specific state of this task */ struct thread_struct thread; .... }
ã¨ãthread ã¡ã³ãã« CPU ç¶æ ãä¿åãã thread_struct ã¨ããå¥ã®ãªãã¸ã§ã¯ããæ ¼ç´ããã¦ãã¾ããthread_struct 㯠CPU ä¾åã®ä½ã¬ãã«ãªå®è¡ã³ã³ããã¹ãæ å ±ãæ ¼ç´ãããªãã¸ã§ã¯ãã§ãã
i386 ã® thread_struct 㯠include/asm-i386/processor.h ã«å®ç¾©ãããã¾ãã
struct thread_struct { /* cached TLS descriptors. */ struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; unsigned long esp0; unsigned long sysenter_cs; unsigned long eip; unsigned long esp; unsigned long fs; unsigned long gs; /* Hardware debugging registers */ unsigned long debugreg[8]; /* %%db0-7 debug registers */ /* fault info */ unsigned long cr2, trap_no, error_code; /* floating point info */ union i387_union i387; /* virtual 86 mode info */ struct vm86_struct __user * vm86_info; unsigned long screen_bitmap; unsigned long v86flags, v86mask, saved_esp0; unsigned int saved_fs, saved_gs; /* IO permissions */ unsigned long *io_bitmap_ptr; unsigned long iopl; /* max allowed port in the bitmap, in bytes: */ unsigned long io_bitmap_max; };
ããã°ã©ã ã«ã¦ã³ã¿ (eip) ãã¹ã¿ãã¯ãã¤ã³ã¿ (esp) ãªã© 32 ãããã¬ã¸ã¹ã¿ãåããã¡ã³ããè¦ã¤ããã¾ãããããå ã®æ¡å¼µæ§æã®å ¥åºåãªãã©ã³ãã«æå®ããã¦ãã prev->thread.esp ã prev->thread.eip ã§ããç¹°ãè¿ãã«ãªãã¾ããããããã®ã¡ã¢ãªé åã¯ããã»ã¹ãã£ã¹ã¯ãªãã¿å ã®ã¬ã¸ã¹ã¿ã®ä¿åå ´æãã¨ãããã¨ã§ããã
ã§ã¯æ¹ãã¦ãswitch_to() ã®ã¢ã»ã³ããªã³ã¼ãããå°ããã¤è¦ã¦ããã¨ãã¾ãã
/* å ¥åãªãã©ã³ãã®å¦ç */ movl prev, %eax movl next, %edx
æ¡å¼µæ§æã®å ¥åãªãã©ã³ãæå®ãå±éããç®æã§ããprevãnext ã®ã¢ãã¬ã¹ããããã eax 㨠edx ã«è¨å®ãã¦ãã¾ããä¸è¦ãªãã§ãããªãã¨ããã¨æãã®ã§ããããã¯å¾ã§ jmp ãã __switch_to() é¢æ°ã¸ã®ã¬ã¸ã¹ã¿çµç±ã§ã®å¼æ°æ¸¡ãã®ããã§ãã詳ããã¯å¾è¿°ãã¾ãã
/* æ¬ä½ */ pushfl /* Save flags */ pushl %ebp
ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§å®ç¾©ãããå¦çæ¬ä½ã«å ¥ã£ã¦ããã¾ãã
- pushfl ã§ãã©ã°ã¬ã¸ã¹ã¿ EFLAGS ãã¹ã¿ãã¯ã«éé¿
- ebp ãã¹ã¿ãã¯ã«éé¿
ãã®æç¹ã§ã®å®è¡ã³ã³ããã¹ãã¯ã¾ã 次ã«åãæ¿ããåã® prev ã§ããå¾ã£ã¦ãããã®å¤ã¯ prev ã®ã«ã¼ãã«ã¹ã¿ãã¯ã«ç©ã¾ãããã¨ã«ãªãã¾ãã(ãã®è¾ºã®ç解ãããææ§ãã«ã¼ãã«ã¢ã¼ãã¹ã¿ãã¯ã¯ããã»ã¹æ¯ã«ãã£ã¦ãã«ã¼ãã«ã®å é¨ã§ push ãªã©ãã¦ã¹ã¿ãã¯ã«ãã¼ã¿ç©ã = ç¾å¨ã®å®è¡ã³ã³ããã¹ãã«ãªã³ã¯ãã¦ããã«ã¼ãã«ã¢ã¼ãã¹ã¿ãã¯ç©ã...ã¨ãããã¨ã§è¯ã? å ·ä½çã«ã¯
union thread_union { struct thread_info thread_info; unsigned long stack[THREAD_SIZE/sizeof(long)]; };
ã® stack ãããã«ç¸å½ããããã®ç解ã§åã£ã¦ãã¨ããåæã§è©±ãé²ãã¾ããè¶ åéããã¦ããããããªããã)
movl %esp, prev->thread.esp /* save ESP */ movl next->thread.esp, %esp /* restore ESP */
- ç¾å¨ã®ã¹ã¿ãã¯ãã¤ã³ã¿ esp ã prev å ã«ä¿å
- next ã«ä¿åããã¦ããã¹ã¿ãã¯ãã¤ã³ã¿ esp ãç¾å¨ã®ã¹ã¿ãã¯ãã¤ã³ã¿ã¨ãã¦è¨å®
ããã«ãã使ç¨ããã¹ã¿ãã¯ã prev ã®ãã®ãã next ã®ãã®ã«åãæ¿ããã¾ãã(Linux 2.6 ã®æ§é ã§ã¯ esp ã®ã¢ãã¬ã¹ããè¨ç®ã㦠task_struct ã¤ã³ã¹ã¿ã³ã¹ã®ã¢ãã¬ã¹ãç¥ããã¨ãã§ãã¾ããå®éã«ã¬ã³ãããã»ã¹ãæ±ãã current ãã¯ãã¯ãã®æ¹æ³ã§ esp ããã«ã¬ã³ãããã»ã¹ã¸ã®åç §ãåå¾ãã¾ããæ ã« esp ãåãæ¿ããã¨ãããã¨ã¯ããªãã¡ã«ã¬ã³ãããã»ã¹ãåãæ¿ãããã¨ã«ç¸å½ãã¾ãã)
movl $1f, prev->thread.eip /* save EIP */ pushl next->thread.eip /* restore EIP */ jmp __switch_to
ã¹ã¿ãã¯ãã¤ã³ã¿ã«ç¶ãã¦ããã°ã©ã ã«ã¦ã³ã¿ eip ã®éé¿ã復帰ãè¡ãããã®ã§ãããããã¡ãã£ã¨ããªããã¼ã§ãã
ã¾ããprev->thread.eip ã« movl ãã¦ãã $1f ã¨ã¯ä½ããããã¯ç¶ãã¦å®ç¾©ããã¦ãã
1: popl %ebp popfl
ã® "1:" ã¨ããã©ãã«ã§æå®ããç®æã®ã¢ãã¬ã¹ã§ããprev ã¤ã¾ãåãæ¿ããããå´ã®ããã°ã©ã ã«ã¦ã³ã¿ããã (ã©ãã«1 ã®ã¢ãã¬ã¹) ã«è¨å®ããã¨ãããã¨ã¯ã次å prev ã®å¦çãåéãããã¨ãã¯ã©ãã«1 ã®ã¢ãã¬ã¹ããå¦çãåéãããã¨ããæå®ã«çããã
次ã«ãããããä¿åããã¦ãã next->thread.eip ãæ°ããåãæ¿ãã next ã®ã«ã¼ãã«ã¹ã¿ãã¯ä¸ã« pushãå ã«è¦ãããã« switch_to() ãéã£ãããã»ã¹ãã£ã¹ã¯ãªãã¿ã® thread.eip ã¡ã³ãã«ã¯ã©ãã«1ã®ã¢ãã¬ã¹ãè¨å®ãããã®ã§ããããnext->thread.eip ã(å¤ãã®å ´å) ã©ãã«1 ã®ã¢ãã¬ã¹ãæãã¦ãã¾ããã¤ã¾ããããã§æ°ãã« %eip ã«ã»ãããããå¤ãã©ãã«1 ã®ã¢ãã¬ã¹ã¨ãããã¨ã«ãªãã¾ãã*1 ãã㦠C ã® __switch_to() ã«ã¸ã£ã³ãã
ãªããã®ããã« next->thread.eip ã®ã¢ãã¬ã¹ãã¹ã¿ãã¯ã«ç©ãã§ãã __switch_to() ã«ã¸ã£ã³ãããã®ãã__switch_to() 㯠process.c ã«å®ç¾©ããã C ã®é¢æ°ã§ãæå¾ã¯ C ã® return æã§çµãã£ã¦ãã¾ããC ã® return æã¯ã¢ã»ã³ããªå½ä»¤ã§ã¯ ret ã¨ãªãã¾ããret ã¯ãã®ä»æ§ã§ãã¹ã¿ãã¯ä¸ããæ»ãã¢ãã¬ã¹ã eip ã«èªã¿è¾¼ãã¨ããä»æ§ã«ãªã£ã¦ãã¾ãã
ã¤ã¾ãã
- å ã« next->thread.eip ãã¹ã¿ãã¯ã« push ãã¦ãã jmp __switch_to ããã¨
- __switch_to() ãå¦ççµã㦠ret ã§è¿ããã¨ããã¨ãã«
- CPU ã次ã®ããã°ã©ã ã®ã¢ãã¬ã¹ã¨ãã¦ã¹ã¿ãã¯ããåãåºãå¤ã next->thread.eip ã«ãªã
- ãããããã°ã©ã ã«ã¦ã³ã¿ (eip ã¬ã¸ã¹ã¿) ã«è¨å®ããã
ããã§ããC ã®å¼åºè¦ç´ããã¾ãå©ç¨ãã¦ãé¢æ°ãå¼åºãã¦è¿ã£ã¦æ¥ããã¨ã®å¦çã®åéç®æãä»»æã®å ´æã«æå®ãããã¯ããã¯ã§ãã
__switch_to() é¢æ°ã¸ã®å¼æ°ããã (fastcall å¼åºè¦ç´)
switch_to ãã¯ãããã¸ã£ã³ããã __switch_to() é¢æ°ã¯ããã°ã©ã ã«ã¦ã³ã¿ã¨ã¹ã¿ãã¯ãã¤ã³ã¿ä»¥å¤ã®ã¬ã¸ã¹ã¿åãæ¿ããè¡ãé¢æ°ãæµ®åå°æ°ç¹æ¼ç®ã¬ã¸ã¹ã¿ããããã°é¢é£ã¬ã¸ã¹ã¿ãI/O ãã¼ãã¸ã®ã¢ã¯ã»ã¹æ¨©ã®è¨å®ã»ããè¡ãã¾ãã__switch_to() 㯠prev 㨠next ã®äºã¤ã®å¼æ°ãåãåãã¾ãã
ããã¾ã§è¦ã¦ããããã« switch_to ãã¯ããã __switch_to() ãå¼ã³åºãã«ããã£ã¦ã¯
jmp __switch_to
㨠jmp å½ä»¤ã使ã£ã¦ãã¾ããããã§æ°ã¥ãã®ãã__switch_to() ã®å¼æ°ã¨ã㦠prevãnext ã渡ãå¿ è¦ãããã®ã«ããããå¼æ°ãã¹ã¿ãã¯ã®ä¸ã«ç©ãã§ããæ§åãè¦ãããªãã¨ãããã¨ã§ããcdecl å¼åºè¦ç´ã§ã¯é¢æ°ã®å¼æ°ã¯å¼åºå ã§ã¹ã¿ãã¯ã« push ãã¦ãããããããé¢æ°ã call ãã決ã¾ãã§ãã
ãããã¨æã£ã¦ __switch_to() ã®å®£è¨ãè¦ã¦ã¿ã¾ãã
struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
fastcall ã¨ããæå®ãããã¾ããããã¯ä½ã§ãããããfastcall 㯠cdecl ã«åããé¢æ°ã®å¼åºè¦ç´ãå¼æ°ãã¹ã¿ãã¯çµç±ã§ã¯ãªãã¬ã¸ã¹ã¿çµç±ã§æ¸¡ãè¦ç´ã§ãããªãã»ã© __switch_to() ã¸ã®å¼æ°ã¯ã¹ã¿ãã¯ã§ã¯ãªãã¬ã¸ã¹ã¿ã使ã£ã¦æ¸¡ãã®ã§ããã
ãã® fastcall ãæçµçã«ã³ã³ãã¤ã©ã«ã©ã®ãããªå½¢ã§æ¸¡ãã㯠http://cheesy.dip.jp/diary/archives/141 ã«è§£èª¬ãããã¾ããfastcall 㯠gcc ã® __attribute__((regparam(3)) å±æ§ã«å±éããã¦ãçµæã¨ãã¦å¼æ°ã eax ã¬ã¸ã¹ã¿ã¨ edx ã¬ã¸ã¹ã¿çµç±ã§æ¸¡ããã¨ã«ãªãã¾ãã
__switch_to ãå±éããæ¬ä¼¼ã¢ã»ã³ããªã³ã¼ãã®ä¸ã§
/* å ¥åãªãã©ã³ãã®å¦ç */ movl prev, %eax movl next, %edx
ã¨ããç®æãå é ã«ããã¾ããããã㯠__switch_to() ã¸å¼æ°ã¨ãã¦æ¸¡ãããã®å½ä»¤ã ã£ãããã§ãã
ã©ãã« 1 以éã®å¦ç
__switch_to() ããå¦çãæ»ã£ã¦ããã¨ãã©ãã« 1 ã®ç®æããå¦çãåéããã¾ãããã§ã«ãã®æç¹ã§å®è¡ã³ã³ããã¹ãã¯åãæ¿ãã£ã¦ãã¾ãã
1: popl %ebp popfl /* åºåãªãã©ã³ãã®å¦ç */ movl %eax, last movl %esi, esi movl %edi, edi
ã¹ã¿ãã¯ã«éé¿ããã¦ãã ebp 㨠eflags ã復帰ãã¦ãã¬ã¸ã¹ã¿ãå¤æ°ã«æ¸ãåºãã¦ãã¯ãã¯çµããã¾ãã(last ã¯ããããã© esi 㨠edi ã¯ä½ã®ããã«ãããã¦ãã®ããããããªã) ã§ãcontext_switch() 㯠prev ã return ãã¦å¼åºå ã® schedule() ã«æ»ãã¾ãã
ãã®ããã«ã㦠context_switch() ããæ»ã£ãã¨ãã«ã¯å®è¡ã³ã³ããã¹ãã prev ãã next ã¸åãæ¿ã£ã¦ããã¨ããä»çµã¿ã«ãªã£ã¦ãã¾ãã
ã¾ã¨ã
ã ãã¶é·ããªã£ã¦ãã¾ãã¾ããããLinux ã®ã³ã³ããã¹ãã¹ã¤ããå¦çã®æ ¸ã¨ãªã switch_to () ãã¯ãã®ã³ã¼ããèªã¿ããã®è§£èª¬ããã¾ããã
- switch_to() ãã¯ãã§ã¯ gcc ã®ã¤ã³ã©ã¤ã³ã¢ã»ã³ããªã§ã¢ã»ã³ããªå½ä»¤ã使ããã¦ãã¾ãã
- x86 æ¡å¼µã¤ã³ã©ã¤ã³ã¢ã»ã³ããªæ§æã使ãã¨ã¢ã»ã³ããªå½ä»¤ã¨ C è¨èªã¨ã®éã§ã¹ãã¼ãã«ã¡ã¢ãªã®å 容ãããåããããã¨ãã§ãã¾ãã
- switch_to() ãã¯ããå±éãã¦ä¸ã¤ãã¤è¿½ã£ã¦ããã¨ãããã°ã©ã ã«ã¦ã³ã¿ãã¹ã¿ãã¯ãã¤ã³ã¿ãéé¿/復帰ãããæ§åãå¦çã®åéã®ããã®ãã¯ããã¯ãªã©ãè¦ããã¨ãã§ãã¾ãã
- switch_to() ãã¯ããã __switch_to() é¢æ°ãå¼ã³åºãã«ããã£ã¦ fastcall å¼åºè¦ç´ã使ããã¦ãããgcc ã® regparam å±æ§ã使ããã¨ã§ãã®å®ç¾ãå¯è½ã ã¨ãããã¨ãåããã¾ããã
ç¬ãè¨
fastcall ã®ã¨ããã¨ãè²ã 解説ãããã¨ããã¨ãå®ã¯ããåãã£ã¦ãªããã¨ããã£ã¦ããã調ã¹ããã¡ã«ç¥èãè£å¼·ãããã¨ãã§ãã¾ãããèªåãã¡ããã¨ç©äºãç解ãããã©ããã¯äººã«èª¬æãã§ãããã©ãããã¨ããã®ããããããã¾ãã
ä»å調ã¹ã¦ã¾ã ã¯ã£ããã¨ç解ã§ãã¦ãªãç®æãè¦èª¿æ»ã
- gas ã® .type ãã£ã¬ã¯ãã£ãã«ãã @function æå®ãä½ã«å½±é¿ããã
- ã«ã¼ãã«ã¹ã¿ã㯠(switch_to() å 㧠pushl %ebp ã¨ããã¦å¤ãç©ã¾ããã¹ã¿ãã¯)ã¨ã¯ãã®ã¨ãã®å®è¡ã³ã³ããã¹ãã«ç´ã¥ãã«ã¼ãã«ããã»ã¹ã¹ã¿ãã¯ã¨ããç解ã§ãããã
- switch_to() ã®çµããã§èªåå¤æ° esi, edi ã«ã¬ã¸ã¹ã¿ã®å 容ãæ¸ãåºãã¦ããã®ã¯ä½ã®ãã?
- switch_to() ã prev, next, last ã¨3ã¤å¼æ°ãåããæ¸ç±ãè¦ã㨠last ãæå®ããã¦ããçç±ã®è§£èª¬ã¯ããã®ã ãã©ã¡ããã¨ç解ã§ãã¦ãªãã
åèæç® (æä¸ã§ç´¹ä»ãã URL 以å¤)
- Linuxã«ã¼ãã«2.6解èªå®¤
- 詳解 Linuxã«ã¼ã㫠第3ç
- Linuxã«ã¼ãã«è§£æå ¥é (Iã»O BOOKS)
- ã¯ããã¦èªã8086â16ãããã»ã³ã³ãã¥ã¼ã¿ãããããèªã (ã¢ã¹ãã¼ããã¯ã¹)
- ã¯ããã¦èªã486â32ãããã³ã³ãã¥ã¼ã¿ãããããèªã
- ããã°ã©ãã³ã°ã®åãçã¿åºãæ¬âã¤ã³ãã«CPUã®GNUã¦ã¼ã¶ã¸
- Binary Hacks âããã«ã¼ç§ä¼ã®ãã¯ããã¯100é¸
*1:fork(2) ã§çã¾ããåããã»ã¹ãå¦çãéå§ããå ´åãã«ã¼ãã«ã¹ã¬ããçææã¯ä¾å¤