Bharata B. Rao ÌṩÁËÔÚ Linux ƽ̨ÉÏʹÓú͹¹Ôì x86 ÄÚÁª»ã±àµÄ¸ÅÀ¨ÐÔ½éÉÜ¡£Ëû½éÉÜÁËÄÚÁª»ã±à¼°Æä¸÷ÖÖÓ÷¨µÄ»ù´¡ÖªÊ¶£¬ÌṩÁËһЩ»ù±¾µÄÄÚÁª»ã±à±àÂëÖ¸µ¼£¬²¢½âÊÍÁËÔÚ Linux ÄÚºËÖÐÄÚÁª»ã±à´úÂëµÄһЩʵÀý¡£
Èç¹ûÄúÊÇ Linux Äں˵Ŀª·¢ÈËÔ±£¬Äú»á·¢ÏÖ×Ô¼º¾³£Òª¶ÔÓëÌåϵ½á¹¹¸ß¶ÈÏà¹ØµÄ¹¦ÄܽøÐбàÂë»òÓÅ»¯´úÂë·¾¶¡£ÄúºÜ¿ÉÄÜÊÇͨ¹ý½«»ã±àÓïÑÔÖ¸Áî²åÈëµ½ C Óï¾äµÄÖм䣨ÓÖ³ÆΪÄÚÁª»ã±àµÄÒ»ÖÖ·½·¨£©À´Ö´ÐÐÕâЩÈÎÎñµÄ¡£ÈÃÎÒÃÇ¿´Ò»Ï Linux ÖÐÄÚÁª»ã±àµÄÌض¨Ó÷¨¡££¨ÎÒÃǽ«ÌÖÂÛÏÞÖÆÔÚ IA32 »ã±à¡££©
GNU »ã±à³ÌÐò¼òÊö
ÈÃÎÒÃÇÊ×ÏÈ¿´Ò»Ï Linux ÖÐʹÓõĻù±¾»ã±à³ÌÐòÓï·¨¡£GCC£¨ÓÃÓÚ Linux µÄ GNU C ±àÒëÆ÷£©Ê¹Óà AT&T »ã±àÓï·¨¡£ÏÂÃæÁгöÁËÕâÖÖÓï·¨µÄһЩ»ù±¾¹æÔò¡££¨¸ÃÁбí¿Ï¶¨²»ÍêÕû£»Ö»°üÀ¨ÁËÓëÄÚÁª»ã±àÏà¹ØµÄÄÇЩ¹æÔò¡££©
¼Ä´æÆ÷ÃüÃû
¼Ä´æÆ÷Ãû³ÆÓÐ % ǰ׺¡£¼´£¬Èç¹û±ØÐëʹÓà eax£¬ËüÓ¦¸ÃÓÃ×÷ %eax¡£
Ô´²Ù×÷ÊýºÍÄ¿µÄ²Ù×÷ÊýµÄ˳Ðò
ÔÚËùÓÐÖ¸ÁîÖУ¬ÏÈÊÇÔ´²Ù×÷Êý£¬È»ºó²ÅÊÇÄ¿µÄ²Ù×÷Êý¡£ÕâÓ뽫Դ²Ù×÷Êý·ÅÔÚÄ¿µÄ²Ù×÷ÊýÖ®ºóµÄ Intel Óï·¨²»Í¬¡£
mov %eax, %ebx, transfers the contents of eax to ebx.
²Ù×÷Êý´óС
¸ù¾Ý²Ù×÷ÊýÊÇ×Ö½Ú (byte)¡¢×Ö (word) »¹Êdz¤ÐÍ (long)£¬Ö¸ÁîµÄºó׺¿ÉÒÔÊÇ b¡¢w »ò l¡£Õâ²¢²»ÊÇÇ¿ÖÆÐԵģ»GCC »á³¢ÊÔͨ¹ý¶ÁÈ¡²Ù×÷ÊýÀ´ÌṩÏàÓ¦µÄºó׺¡£µ«ÊÖ¹¤Ö¸¶¨ºó׺¿ÉÒÔ¸ÄÉÆ´úÂëµÄ¿É¶ÁÐÔ£¬²¢¿ÉÒÔÏû³ý±àÒëÆ÷²Â²â²»ÕýÈ·µÄ¿ÉÄÜÐÔ¡£
movb %al, %bl -- Byte move
movw %ax, %bx -- Word move
movl %eax, %ebx -- Longword move
Á¢¼´²Ù×÷Êý
ͨ¹ýʹÓà $ Ö¸¶¨Ö±½Ó²Ù×÷Êý¡£
movl $0xffff, %eax -- will move the value of 0xffff into eax register.
¼ä½ÓÄÚ´æÒýÓÃ
ÈκζÔÄÚ´æµÄ¼ä½ÓÒýÓö¼ÊÇͨ¹ýʹÓà ( ) À´Íê³ÉµÄ¡£
movb (%esi), %al -- will transfer the byte in the memory
pointed by esi into al
register
ÄÚÁª»ã±à
GCC ΪÄÚÁª»ã±àÌṩÌØÊâ½á¹¹£¬Ëü¾ßÓÐÒÔϸñʽ£º
GCG µÄ "asm" ½á¹¹
asm ( assembler template
: output operands (optional)
: input operands (optional)
: list of clobbered registers
(optional)
);
±¾ÀýÖУ¬»ã±à³ÌÐòÄ£°åÓÉ»ã±àÖ¸Áî×é³É¡£ÊäÈë²Ù×÷ÊýÊdz䵱ָÁîÊäÈë²Ù×÷ÊýʹÓÃµÄ C ±í´ïʽ¡£Êä³ö²Ù×÷ÊýÊǽ«¶ÔÆäÖ´Ðлã±àÖ¸ÁîÊä³öµÄ C ±í´ïʽ¡£
ÄÚÁª»ã±àµÄÖØÒªÐÔÌåÏÖÔÚËüÄܹ»Áé»î²Ù×÷£¬¶øÇÒ¿ÉÒÔʹÆäÊä³öͨ¹ý C ±äÁ¿ÏÔʾ³öÀ´¡£ÒòΪËü¾ßÓÐÕâÖÖÄÜÁ¦£¬ËùÒÔ "asm" ¿ÉÒÔÓÃ×÷»ã±àÖ¸ÁîºÍ°üº¬ËüµÄ C ³ÌÐòÖ®¼äµÄ½Ó¿Ú¡£
Ò»¸ö·Ç³£»ù±¾µ«ºÜÖØÒªµÄÇø±ðÔÚÓÚ ¼òµ¥ÄÚÁª»ã±àÖ»°üÀ¨Ö¸Á¶ø À©Õ¹ÄÚÁª»ã±à°üÀ¨²Ù×÷Êý¡£ÒªËµÃ÷ÕâÒ»µã£¬¿¼ÂÇÒÔÏÂʾÀý£º
ÄÚÁª»ã±àµÄ»ù±¾ÒªËØ
{
int a=10, b;
asm ("movl %1, %%eax;
movl %%eax, %0;"
:"=r"(b) /* output */
:"r"(a) /* input */
:"%eax"); /* clobbered register */
}
ÔÚÉÏÀýÖУ¬ÎÒÃÇʹÓûã±àÖ¸Áîʹ "b" µÄÖµµÈÓÚ "a"¡£Çë×¢ÒâÒÔϼ¸µã£º
* "b" ÊÇÊä³ö²Ù×÷Êý£¬ÓÉ %0 ÒýÓã¬"a" ÊÇÊäÈë²Ù×÷Êý£¬ÓÉ %1 ÒýÓá£
* "r" ÊDzÙ×÷ÊýµÄÔ¼Êø£¬ËüÖ¸¶¨½«±äÁ¿ "a" ºÍ "b" ´æ´¢ÔڼĴæÆ÷ÖС£Çë×¢Ò⣬Êä³ö²Ù×÷ÊýÔ¼ÊøÓ¦¸Ã´øÓÐÒ»¸öÔ¼ÊøÐÞÊηû "="£¬Ö¸¶¨ËüÊÇÊä³ö²Ù×÷Êý¡£
* ÒªÔÚ "asm" ÄÚʹÓüĴæÆ÷ %eax£¬%eax µÄÇ°ÃæÓ¦¸ÃÔÙ¼ÓÒ»¸ö %£¬»»¾ä»°Ëµ¾ÍÊÇ %%eax£¬ÒòΪ "asm" ʹÓà %0¡¢%1 µÈÀ´±êʶ±äÁ¿¡£ÈκδøÓÐÒ»¸ö % µÄÊý¶¼¿´×÷ÊÇÊäÈ룯Êä³ö²Ù×÷Êý£¬¶ø²»ÈÏΪÊǼĴæÆ÷¡£
* µÚÈý¸öðºÅºóµÄÐÞÊμĴæÆ÷ %eax ¸æËß½«ÔÚ "asm" ÖÐÐÞ¸Ä GCC %eax µÄÖµ£¬ÕâÑù GCC ¾Í²»Ê¹ÓøüĴæÆ÷´æ´¢ÈκÎÆäËüµÄÖµ¡£
* movl %1, %%eax ½« "a" µÄÖµÒƵ½ %eax ÖУ¬ movl %%eax, %0 ½« %eax µÄÄÚÈÝÒƵ½ "b" ÖС£
* ÒòΪ "b" ±»Ö¸¶¨³ÉÊä³ö²Ù×÷Êý£¬Òò´Ëµ± "asm" µÄÖ´ÐÐÍê³Éºó£¬Ëü½«·´Ó³³ö¸üеÄÖµ¡£»»¾ä»°Ëµ£¬¶Ô "asm" ÄÚ "b" Ëù×öµÄ¸ü¸Ä½«ÔÚ "asm" Íâ·´Ó³³öÀ´¡£
ÏÖÔÚÈÃÎÒÃǸüÏêϸµÄÁ˽âÿһÏîµÄº¬Òå¡£
»ã±à³ÌÐòÄ£°å
»ã±à³ÌÐòÄ£°åÊÇÒ»×é²åÈëµ½ C ³ÌÐòÖеĻã±àÖ¸Á¿ÉÒÔÊǵ¥¸öÖ¸ÁҲ¿ÉÒÔÊÇÒ»×éÖ¸Á¡£Ã¿ÌõÖ¸ÁӦ¸ÃÓÉË«ÒýºÅÀ¨Æ𣬻òÕßÕû×éÖ¸ÁîÓ¦¸ÃÓÉË«ÒýºÅÀ¨Æð¡£Ã¿ÌõÖ¸ÁӦ¸ÃÓÃÒ»¸ö¶¨½ç·û½áβ¡£ÓÐЧµÄ¶¨½ç·ûΪÐÂÐÐ (\n) ºÍ·ÖºÅ (;)¡£ '\n' ºó¿ÉÒÔ¸úÒ»¸ö tab(\t) ×÷Ϊ¸ñʽ»¯·ûºÅ£¬Ôö¼Ó GCC ÔÚ»ã±àÎļþÖÐÉú³ÉµÄÖ¸ÁîµÄ¿É¶ÁÐÔ¡£ Ö¸Áîͨ¹ýÊý %0¡¢%1 µÈÀ´ÒýÓà C ±í´ïʽ£¨Ö¸¶¨Îª²Ù×÷Êý£©¡£
Èç¹ûÏ£ÍûÈ·±£±àÒëÆ÷²»»áÔÚ "asm" ÄÚ²¿ÓÅ»¯Ö¸Á¿ÉÒÔÔÚ "asm" ºóʹÓùؼü×Ö "volatile"¡£Èç¹û³ÌÐò±ØÐëÓë ANSI C ¼æÈÝ£¬ÔòÓ¦¸ÃʹÓà __asm__ ºÍ __volatile__£¬¶ø²»ÊÇ asm ºÍ volatile¡£
²Ù×÷Êý
C ±í´ïʽÓÃ×÷ "asm" ÄڵĻã±àÖ¸Áî²Ù×÷Êý¡£ÔÚ»ã±àÖ¸Áîͨ¹ý¶Ô C ³ÌÐòµÄ C ±í´ïʽ½øÐвÙ×÷À´Ö´ÐÐÓÐÒâÒåµÄ×÷ÒµµÄÇé¿öÏ£¬²Ù×÷ÊýÊÇÄÚÁª»ã±àµÄÖ÷ÒªÌØÐÔ¡£
ÿ¸ö²Ù×÷Êý¶¼ÓɲÙ×÷ÊýÔ¼Êø×Ö·û´®Ö¸¶¨£¬ºóÃæ¸úÓÃÀ¨»¡À¨ÆðµÄ C ±í´ïʽ£¬ÀýÈ磺"constraint" (C expression)¡£²Ù×÷ÊýÔ¼ÊøµÄÖ÷Òª¹¦ÄÜÊÇÈ·¶¨²Ù×÷ÊýµÄÑ°Ö··½Ê½¡£
¿ÉÒÔÔÚÊäÈëºÍÊä³ö²¿·ÖÖÐͬʱʹÓöà¸ö²Ù×÷Êý¡£Ã¿¸ö²Ù×÷ÊýÓɶººÅ·Ö¸ô¿ª¡£
ÔÚ»ã±à³ÌÐòÄ£°åÄÚ²¿£¬²Ù×÷ÊýÓÉÊý×ÖÒýÓá£Èç¹û×ܹ²ÓÐ n ¸ö²Ù×÷Êý£¨°üÀ¨ÊäÈëºÍÊä³ö£©£¬ÄÇôµÚÒ»¸öÊä³ö²Ù×÷ÊýµÄ±àºÅΪ 0£¬ÖðÏîµÝÔö£¬×îºóÄǸöÊäÈë²Ù×÷ÊýµÄ±àºÅΪ n -1¡£×ܲÙ×÷ÊýµÄÊýÄ¿ÏÞÖÆÔÚ 10£¬Èç¹û»úÆ÷ÃèÊöÖÐÈκÎÖ¸ÁîģʽÖеÄ×î´ó²Ù×÷ÊýÊýÄ¿´óÓÚ 10£¬ÔòʹÓúóÕß×÷ΪÏÞÖÆ¡£
ÐÞÊμĴæÆ÷Áбí
Èç¹û "asm" ÖеÄÖ¸ÁîÖ¸µÄÊÇÓ²¼þ¼Ä´æÆ÷£¬¿ÉÒÔ¸æËß GCC ÎÒÃǽ«×Ô¼ºÊ¹ÓúÍÐÞ¸ÄËüÃÇ¡£ÕâÑù£¬GCC ¾Í²»»á¼ÙÉèËü×°Èëµ½ÕâЩ¼Ä´æÆ÷ÖеÄÖµÊÇÓÐЧֵ¡£Í¨³£²»ÐèÒª½«ÊäÈëºÍÊä³ö¼Ä´æÆ÷ÁÐΪ clobbered£¬ÒòΪ GCC ÖªµÀ "asm" ʹÓÃËüÃÇ£¨ÒòΪËüÃDZ»Ã÷È·Ö¸¶¨ÎªÔ¼Êø£©¡£²»¹ý£¬Èç¹ûÖ¸ÁîʹÓÃÈκÎÆäËüµÄ¼Ä´æÆ÷£¬ÎÞÂÛÊÇÃ÷È·µÄ»¹ÊÇÒþº¬µÄ£¨¼Ä´æÆ÷²»ÔÚÊäÈëÔ¼ÊøÁбíÖгöÏÖ£¬Ò²²»ÔÚÊä³öÔ¼ÊøÁбíÖгöÏÖ£©£¬¼Ä´æÆ÷¶¼±ØÐë±»Ö¸¶¨ÎªÐÞÊÎÁÐ±í¡£ÐÞÊμĴæÆ÷ÁÐÔÚµÚÈý¸öðºÅÖ®ºó£¬ÆäÃû³Æ±»Ö¸¶¨Îª×Ö·û´®¡£
ÖÁÓڹؼü×Ö£¬Èç¹ûÖ¸ÁîÒÔijЩ²»¿ÉÔ¤ÖªÇÒ²»Ã÷È·µÄ·½Ê½ÐÞ¸ÄÁËÄڴ棬Ôò¿ÉÄܽ« "memory" ¹Ø¼ü×ÖÌí¼Óµ½ÐÞÊμĴæÆ÷ÁбíÖС£ÕâÑù¾Í¸æËß GCC ²»ÒªÔÚ²»Í¬Ö¸ÁîÖ®¼ä½«ÄÚ´æÖµ¸ßËÙ»º´æÔڼĴæÆ÷ÖС£
²Ù×÷ÊýÔ¼Êø
Ç°ÃæÌáµ½¹ý£¬"asm" ÖеÄÿ¸ö²Ù×÷Êý¶¼Ó¦¸ÃÓɲÙ×÷ÊýÔ¼Êø×Ö·û´®ÃèÊö£¬ºóÃæ¸úÓÃÀ¨»¡À¨ÆðµÄ C ±í´ïʽ¡£²Ù×÷ÊýÔ¼ÊøÖ÷ÒªÊÇÈ·¶¨Ö¸ÁîÖвÙ×÷ÊýµÄÑ°Ö··½Ê½¡£Ô¼ÊøÒ²¿ÉÒÔÖ¸¶¨£º
* ÊÇ·ñÔÊÐí²Ù×÷ÊýλÓڼĴæÆ÷ÖУ¬ÒÔ¼°Ëü¿ÉÒÔ°üÀ¨ÔÚÄÄЩÖÖÀàµÄ¼Ä´æÆ÷ÖÐ
* ²Ù×÷ÊýÊÇ·ñ¿ÉÒÔÊÇÄÚ´æÒýÓã¬ÒÔ¼°ÔÚÕâÖÖÇé¿öÏÂʹÓÃÄÄЩÖÖÀàµÄµØÖ·
* ²Ù×÷ÊýÊÇ·ñ¿ÉÒÔÊÇÁ¢¼´Êý
Ô¼Êø»¹ÒªÇóÁ½¸ö²Ù×÷ÊýÆ¥Åä¡£
³£ÓÃÔ¼Êø
ÔÚ¿ÉÓõIJÙ×÷ÊýÔ¼ÊøÖУ¬Ö»ÓÐһС²¿·ÖÊdz£Óõģ»ÏÂÃæÁгöÁËÕâЩԼÊøÒÔ¼°¼òÒªÃèÊö¡£ÓйزÙ×÷ÊýÔ¼ÊøµÄÍêÕûÁÐ±í£¬Çë²Î¿¼ GCC ºÍ GAS Êֲᡣ
¼Ä´æÆ÷²Ù×÷ÊýÔ¼Êø (r)
ʹÓÃÕâÖÖÔ¼ÊøÖ¸¶¨²Ù×÷Êýʱ£¬ËüÃÇ´æ´¢ÔÚͨÓüĴæÆ÷ÖС£Çë¿´ÏÂÀý£º
asm ("movl %%cr3, %0\n" :"=r"(cr3val));
ÕâÀ±äÁ¿ cr3val ±£´æÔڼĴæÆ÷ÖУ¬%cr3 µÄÖµ¸´ÖƵ½¼Ä´æÆ÷ÉÏ£¬cr3val µÄÖµ´Ó¸Ã¼Ä´æÆ÷¸üе½ÄÚ´æÖС£Ö¸¶¨ "r" Ô¼Êøʱ£¬GCC ¿ÉÒÔ½«±äÁ¿ cr3val ±£´æÔÚÈκοÉÓÃµÄ GPR ÖС£ÒªÖ¸¶¨¼Ä´æÆ÷£¬±ØÐëͨ¹ýʹÓÃÌض¨µÄ¼Ä´æÆ÷Ô¼ÊøÖ±½ÓÖ¸¶¨¼Ä´æÆ÷Ãû¡£
a %eax
b %ebx
c %ecx
d %edx
S %esi
D %edi
ÄÚ´æ²Ù×÷ÊýÔ¼Êø (m)
µ±²Ù×÷ÊýλÓÚÄÚ´æÖÐʱ£¬ÈκζÔËüÃÇÖ´ÐеIJÙ×÷¶¼½«ÔÚÄÚ´æλÖÃÖÐÖ±½Ó·¢Éú£¬ÕâÓë¼Ä´æÆ÷Ô¼ÊøÕýºÃÏà·´£¬ºóÕßÏȽ«Öµ´æ´¢ÔÚÒªÐ޸ĵļĴæÆ÷ÖУ¬È»ºó½«Ëüд»ØÄÚ´æλÖÃÖС£µ«¼Ä´æÆ÷Ô¼Êøͨ³£Ö»ÔÚ¶ÔÓÚÖ¸ÁîÀ´ËµËüÃÇÊǾø¶Ô±ØÐèµÄ£¬»òÕßËüÃÇ¿ÉÒÔ´ó´óÌá¸ß½ø³ÌËÙ¶ÈʱʹÓᣵ±ÐèÒªÔÚ "asm" ÄÚ²¿¸üРC ±äÁ¿£¬¶øÄúÓÖȷʵ²»Ï£ÍûʹÓüĴæÆ÷À´±£´æÆäֵʱ£¬Ê¹ÓÃÄÚ´æÔ¼Êø×îΪÓÐЧ¡£ÀýÈ磬idtr µÄÖµ´æ´¢ÔÚÄÚ´æλÖà loc ÖУº
("sidt %0\n" : :"m"(loc));
Æ¥Å䣨Êý×Ö£©Ô¼Êø
ÔÚijЩÇé¿öÏ£¬Ò»¸ö±äÁ¿¼ÈÒª³äµ±ÊäÈë²Ù×÷Êý£¬Ò²Òª³äµ±Êä³ö²Ù×÷Êý¡£¿ÉÒÔͨ¹ýʹÓÃÆ¥ÅäÔ¼ÊøÔÚ "asm" ÖÐÖ¸¶¨ÕâÖÖÇé¿ö¡£
asm ("incl %0" :"=a"(var):"0"(var));
ÔÚÆ¥ÅäÔ¼ÊøµÄʾÀýÖУ¬¼Ä´æÆ÷ %eax ¼ÈÓÃ×÷ÊäÈë±äÁ¿£¬Ò²ÓÃ×÷Êä³ö±äÁ¿¡£½« var ÊäÈë¶ÁÈ¡µ½ %eax£¬Ôö¼Óºó½«¸üÐ嵀 %eax Ôٴδ洢ÔÚ var ÖС£ÕâÀïµÄ "0" Ö¸¶¨µÚ 0 ¸öÊä³ö±äÁ¿ÏàͬµÄÔ¼Êø¡£¼´£¬ËüÖ¸¶¨ var µÄÊä³öʵÀýÖ»Ó¦¸Ã´æ´¢ÔÚ %eax ÖС£¸ÃÔ¼Êø¿ÉÒÔÓÃÓÚÒÔÏÂÇé¿ö£º
* ÊäÈë´Ó±äÁ¿ÖжÁÈ¡£¬»òÕß±äÁ¿±»Ð޸ĺó£¬ÐÞ¸Äд»Øµ½Í¬Ò»±äÁ¿ÖÐ
* ²»ÐèÒª½«ÊäÈë²Ù×÷ÊýºÍÊä³ö²Ù×÷ÊýµÄʵÀý·Ö¿ª
ʹÓÃÆ¥ÅäÔ¼Êø×îÖØÒªµÄÒâÒåÔÚÓÚËüÃÇ¿ÉÒÔµ¼ÖÂÓÐЧµØʹÓÿÉÓüĴæÆ÷¡£
Ò»°ãÄÚÁª»ã±àÓ÷¨Ê¾Àý
ÒÔÏÂʾÀýͨ¹ý¸÷ÖÖ²»Í¬µÄ²Ù×÷ÊýÔ¼Êø˵Ã÷ÁËÓ÷¨¡£ÓÐÈç´Ë¶àµÄÔ¼ÊøÒÔÖÁÓÚÎÞ·¨½«ËüÃÇÒ»Ò»Áгö£¬ÕâÀïÖ»ÁгöÁË×î¾³£Ê¹ÓõÄÄÇЩԼÊøÀàÐÍ¡£
"asm" ºÍ¼Ä´æÆ÷Ô¼Êø "r" ÈÃÎÒÃÇÏÈ¿´Ò»ÏÂʹÓüĴæÆ÷Ô¼Êø r µÄ "asm"¡£ÎÒÃǵÄʾÀýÏÔʾÁË GCC ÈçºÎ·ÖÅä¼Ä´æÆ÷£¬ÒÔ¼°ËüÈçºÎ¸üÐÂÊä³ö±äÁ¿µÄÖµ¡£
int main(void)
{
int x = 10, y;
asm ("movl %1, %%eax;
"movl %%eax, %0;"
:"=r"(y) /* y is output operand */
:"r"(x) /* x is input operand */
:"%eax"); /* %eax is clobbered register */
}
ÔÚ¸ÃÀýÖУ¬x µÄÖµ¸´ÖÆΪ "asm" ÖÐµÄ y¡£x ºÍ y ¶¼Í¨¹ý´æ´¢ÔڼĴæÆ÷Öд«µÝ¸ø "asm"¡£Îª¸ÃÀýÉú³ÉµÄ»ã±à´úÂëÈçÏ£º
main:
pushl %ebp
movl %esp,%ebp
subl $8,%esp
movl $10,-4(%ebp)
movl -4(%ebp),%edx /* x=10 is stored in %edx */
#APP /* asm starts here */
movl %edx, %eax /* x is moved to %eax */
movl %eax, %edx /* y is allocated in edx and updated */
#NO_APP /* asm ends here */
movl %edx,-8(%ebp) /* value of y in stack is updated with
the value in %edx */
µ±Ê¹Óà "r" Ô¼Êøʱ£¬GCC ÔÚÕâÀï¿ÉÒÔ×ÔÓÉ·ÖÅäÈκμĴæÆ÷¡£ÔÚÎÒÃǵÄʾÀýÖУ¬ËüÑ¡Ôñ %edx À´´æ´¢ x¡£ÔÚ¶ÁÈ¡ÁË %edx ÖÐ x µÄÖµºó£¬ËüΪ y Ò²·ÖÅäÁËÏàͬµÄ¼Ä´æÆ÷¡£
ÒòΪ y ÊÇÔÚÊä³ö²Ù×÷Êý²¿·ÖÖÐÖ¸¶¨µÄ£¬ËùÒÔ %edx ÖиüеÄÖµ´æ´¢ÔÚ -8(%ebp)£¬¶ÑÕ»ÉÏ y µÄλÖÃÖС£Èç¹û y ÊÇÔÚÊäÈ벿·ÖÖÐÖ¸¶¨µÄ£¬ÄÇô¼´Ê¹ËüÔÚ y µÄÁÙʱ¼Ä´æÆ÷´æ´¢Öµ (%edx) Öб»¸üУ¬¶ÑÕ»ÉÏ y µÄÖµÒ²²»»á¸üС£
ÒòΪ %eax ÊÇÔÚÐÞÊÎÁбíÖÐÖ¸¶¨µÄ£¬GCC ²»ÔÚÈκÎÆäËüµØ·½Ê¹ÓÃËüÀ´´æ´¢Êý¾Ý¡£
ÊäÈë x ºÍÊä³ö y ¶¼·ÖÅäÔÚͬһ¸ö %edx ¼Ä´æÆ÷ÖУ¬¼ÙÉèÊäÈëÔÚÊä³ö²úÉú֮ǰ±»ÏûºÄ¡£Çë×¢Ò⣬Èç¹ûÄúÓÐÐí¶àÖ¸Á¾Í²»ÊÇÕâÖÖÇé¿öÁË¡£ÒªÈ·±£ÊäÈëºÍÊä³ö·ÖÅäµ½²»Í¬µÄ¼Ä´æÆ÷ÖУ¬¿ÉÒÔÖ¸¶¨ & Ô¼ÊøÐÞÊηû¡£ÏÂÃæÊÇÌí¼ÓÁËÔ¼ÊøÐÞÊηûµÄʾÀý¡£
int main(void)
{
int x = 10, y;
asm ("movl %1, %%eax;
"movl %%eax, %0;"
:"=&r"(y) /* y is output operand, note the
& constraint modifier. */
:"r"(x) /* x is input operand */
:"%eax"); /* %eax is clobbered register */
}
ÒÔÏÂÊÇΪ¸ÃʾÀýÉú³ÉµÄ»ã±à´úÂ룬´ÓÖпÉÒÔÃ÷ÏԵؿ´³ö x ºÍ y ´æ´¢ÔÚ "asm" Öв»Í¬µÄ¼Ä´æÆ÷ÖС£
main:
pushl %ebp
movl %esp,%ebp
subl $8,%esp
movl $10,-4(%ebp)
movl -4(%ebp),%ecx /* x, the input is in %ecx */
#APP
movl %ecx, %eax
movl %eax, %edx /* y, the output is in %edx */
#NO_APP
movl %edx,-8(%ebp)
Ìض¨¼Ä´æÆ÷Ô¼ÊøµÄʹÓÃ
ÏÖÔÚÈÃÎÒÃÇ¿´Ò»ÏÂÈçºÎ½«¸ö±ð¼Ä´æÆ÷×÷Ϊ²Ù×÷ÊýµÄÔ¼ÊøÖ¸¶¨¡£ÔÚÏÂÃæµÄʾÀýÖУ¬cpuid Ö¸Áî²ÉÓà %eax ¼Ä´æÆ÷ÖеÄÊäÈ룬ȻºóÔÚËĸö¼Ä´æÆ÷Öиø³öÊä³ö£º%eax¡¢%ebx¡¢%ecx¡¢%edx¡£¶Ô cpuid µÄÊäÈ루±äÁ¿ "op"£©´«µÝµ½ "asm" µÄ eax ¼Ä´æÆ÷ÖУ¬ÒòΪ cpuid Ï£ÍûËüÕâÑù×ö¡£ÔÚÊä³öÖÐʹÓà a¡¢b¡¢c ºÍ d Ô¼Êø£¬·Ö±ðÊÕ¼¯Ëĸö¼Ä´æÆ÷ÖеÄÖµ¡£
asm ("cpuid"
: "=a" (_eax),
"=b" (_ebx),
"=c" (_ecx),
"=d" (_edx)
: "a" (op));
ÔÚÏÂÃæ¿ÉÒÔ¿´µ½ÎªËüÉú³ÉµÄ»ã±à´úÂ루¼ÙÉè _eax¡¢_ebx µÈ... ±äÁ¿¶¼´æ´¢ÔÚ¶ÑÕ»ÉÏ£©£º
movl -20(%ebp),%eax /* store 'op' in %eax -- input */
#APP
cpuid
#NO_APP
movl %eax,-4(%ebp) /* store %eax in _eax -- output */
movl %ebx,-8(%ebp) /* store other registers in
movl %ecx,-12(%ebp)
respective output variables */
movl %edx,-16(%ebp)
strcpy º¯Êý¿ÉÒÔͨ¹ýÒÔÏ·½Ê½Ê¹Óà "S" ºÍ "D" Ô¼ÊøÀ´ÊµÏÖ£º
asm ("cld\n
rep\n
movsb"
: /* no input */
:"S"(src), "D"(dst), "c"(count));
ͨ¹ýʹÓà "S" Ô¼Êø½«Ô´Ö¸Õë src ·ÅÈë %esi ÖУ¬Ê¹Óà "D" Ô¼Êø½«Ä¿µÄÖ¸Õë dst ·ÅÈë %edi ÖС£ÒòΪ rep ǰ׺ÐèÒª count Öµ£¬ËùÒÔ½«Ëü·ÅÈë %ecx ÖС£
ÔÚÏÂÃæ¿ÉÒÔ¿´µ½ÁíÒ»¸öÔ¼Êø£¬ËüʹÓÃÁ½¸ö¼Ä´æÆ÷ %eax ºÍ %edx ½«Á½¸ö 32 λµÄÖµºÏ²¢ÔÚÒ»Æð£¬È»ºóÉú³ÉÒ»¸ö64 λµÄÖµ£º
#define rdtscll(val) \
__asm__ __volatile__ ("rdtsc" : "=A" (val))
The generated assembly looks like this (if val has a 64 bit memory space).
#APP
rdtsc
#NO_APP
movl %eax,-8(%ebp) /* As a result of A constraint
movl %edx,-4(%ebp)
%eax and %edx serve as outputs */
Note here that the values in %edx:%eax serve as 64 bit output.
ʹÓÃÆ¥ÅäÔ¼Êø
ÔÚÏÂÃ潫¿´µ½ÏµÍ³µ÷ÓõĴúÂ룬ËüÓÐËĸö²ÎÊý£º
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4))); \
__syscall_return(type,__res); \
}
ÔÚÉÏÀýÖУ¬Í¨¹ýʹÓà b¡¢c¡¢d ºÍ S Ô¼Êø½«ÏµÍ³µ÷ÓõÄËĸö×Ô±äÁ¿·ÅÈë %ebx¡¢%ecx¡¢%edx ºÍ %esi ÖС£Çë×¢Ò⣬ÔÚÊä³öÖÐʹÓÃÁË "=a" Ô¼Êø£¬ÕâÑù£¬Î»ÓÚ %eax ÖеÄϵͳµ÷Óõķµ»ØÖµ¾Í±»·ÅÈë±äÁ¿ __res ÖС£Í¨¹ý½«Æ¥ÅäÔ¼Êø "0" ÓÃ×÷ÊäÈ벿·ÖÖеÚÒ»¸ö²Ù×÷ÊýÔ¼Êø£¬syscall ºÅ __NR_##name ±»·ÅÈë %eax ÖУ¬²¢ÓÃ×÷¶Ôϵͳµ÷ÓõÄÊäÈë¡£ÕâÑù£¬ÕâÀïµÄ %eax ¼È¿ÉÒÔÓÃ×÷ÊäÈë¼Ä´æÆ÷£¬ÓÖ¿ÉÒÔÓÃ×÷Êä³ö¼Ä´æÆ÷¡£Ã»ÓÐÆäËü¼Ä´æÆ÷ÓÃÓÚÕâ¸öÄ¿µÄ¡£ÁíÇë×¢Ò⣬ÊäÈ루syscall ºÅ£©ÔÚ²úÉúÊä³ö£¨syscall µÄ·µ»ØÖµ£©Ö®Ç°±»ÏûºÄ£¨Ê¹Óã©¡£
ÄÚ´æ²Ù×÷ÊýÔ¼ÊøµÄʹÓÃ
Ç뿼ÂÇÏÂÃæµÄÔ×ӵݼõ²Ù×÷£º
__asm__ __volatile__(
"lock; decl %0"
:"=m" (counter)
:"m" (counter));
ΪËüÉú³ÉµÄ»ã±àÀàËÆÓÚ£º
#APP
lock
decl -24(%ebp) /* counter is modified on its memory location */
#NO_APP.
Äú¿ÉÄÜ¿¼ÂÇÔÚÕâÀïΪ counter ʹÓüĴæÆ÷Ô¼Êø¡£Èç¹ûÕâÑù×ö£¬counter µÄÖµ±ØÐëÏȸ´ÖƵ½¼Ä´æÆ÷£¬µÝ¼õ£¬È»ºó¶ÔÆäÄÚ´æ¸üС£µ«ÕâÑùÄú»áÎÞ·¨Àí½âËø¶¨ºÍÔ×ÓÐÔµÄÈ«²¿Òâͼ£¬ÕâЩÃ÷È·ÏÔʾÁËʹÓÃÄÚ´æÔ¼ÊøµÄ±ØÒªÐÔ¡£
ʹÓÃÐÞÊμĴæÆ÷
Ç뿼ÂÇÄڴ濽±´µÄ»ù±¾ÊµÏÖ¡£
asm ("movl $count, %%ecx;
up: lodsl;
stosl;
loop up;"
: /* no output */
:"S"(src), "D"(dst) /* input */
:"%ecx", "%eax" ); /* clobbered list */
µ± lodsl ÐÞ¸Ä %eax ʱ£¬lodsl ºÍ stosl Ö¸ÁîÒþº¬µØʹÓÃËü¡£%ecx ¼Ä´æÆ÷Ã÷È·×°Èë count¡£µ« GCC ÔÚÎÒÃÇ֪ͨËüÒÔÇ°ÊDz»ÖªµÀÕâЩµÄ£¬ÎÒÃÇÊÇͨ¹ý½« %eax ºÍ %ecx °üÀ¨ÔÚÐÞÊμĴæÆ÷¼¯ÖÐÀ´Í¨Öª GCC µÄ¡£ÔÚÍê³ÉÕâÒ»²½Ö®Ç°£¬GCC ¼ÙÉè %eax ºÍ %ecx ÊÇ×ÔÓɵģ¬Ëü¿ÉÄܾö¶¨½«ËüÃÇÓÃ×÷´æ´¢ÆäËüµÄÊý¾Ý¡£Çë×¢Ò⣬%esi ºÍ %edi ÓÉ "asm" ʹÓã¬ËüÃDz»ÔÚÐÞÊÎÁбíÖС£ÕâÊÇÒòΪÒѾÉùÃ÷ "asm" ½«ÔÚÊäÈë²Ù×÷ÊýÁбíÖÐʹÓÃËüÃÇ¡£ÕâÀï×îµÍÏÞ¶ÈÊÇ£¬Èç¹ûÔÚ "asm" ÄÚ²¿Ê¹ÓüĴæÆ÷£¨ÎÞÂÛÊÇÃ÷È·»¹ÊÇÒþº¬µØ£©£¬¼È²»³öÏÖÔÚÊäÈë²Ù×÷ÊýÁбíÖУ¬Ò²²»³öÏÖÔÚÊä³ö²Ù×÷ÊýÁбíÖУ¬±ØÐ뽫ËüÁÐΪÐÞÊμĴæÆ÷¡£
½áÊøÓï
×ܵÄÀ´Ëµ£¬ÄÚÁª»ã±à·Ç³£¾Þ´ó£¬ËüÌṩµÄÐí¶àÌØÐÔÎÒÃÇÉõÖÁÔÚÕâÀï¸ù±¾Ã»ÓÐÉæ¼°µ½¡£µ«Èç¹ûÕÆÎÕÁ˱¾ÎÄÃèÊöµÄ»ù±¾²ÄÁÏ£¬ÄúÓ¦¸Ã¿ÉÒÔ¿ªÊ¼¶Ô×Ô¼ºµÄÄÚÁª»ã±à½øÐбàÂëÁË¡£
²Î¿¼×ÊÁÏ
* Äú¿ÉÒÔ²ÎÔı¾ÎÄÔÚ developerWorks È«ÇòÕ¾µãÉÏµÄ Ó¢ÎÄÔÎÄ.
* Çë²Î¿¼ Using and Porting the GNU Compiler Collection (GCC)Êֲᡣ
* Çë²Î¿¼ GNU Assembler (GAS)Êֲᡣ
* ×ÐϸÔĶÁ Brennan's Guide to Inline Assembly¡£
¹ØÓÚ×÷Õß
Bharata B. Rao ÓµÓÐÓ¡¶È Mysore ´óѧµÄµç×ÓºÍͨÐŹ¤³ÌµÄѧʿѧλ¡£Ëû´Ó 1999 Äê¾Í¿ªÊ¼Îª IBM Global Services, India ¹¤×÷ÁË¡£ËûÊÇ IBM Linux ¼¼ÊõÖÐÐĵijÉÔ±Ö®Ò»£¬ËûÔÚ¸ÃÖÐÐÄÖÐÖ÷Òª´ÓÊ Linux RAS£¨¿É¿¿ÐÔ¡¢¿ÉÓÃÐÔºÍÊÊÓÃÐÔ£©µÄÑо¿¡£Ëû¸ÐÐËȤµÄÆäËüÁìÓò°üÀ¨²Ù×÷ϵͳ±¾Öʺʹ¦ÀíÆ÷Ìåϵ½á¹¹¡£¿ÉÒÔͨ¹ý rbharata@in.ibm.com ÓëËûÁªÏµ¡£