2.1. µÑ·¯º¸±â

inline assembly¿¡¼­ Á¤ÇØÁÖ¾î¾ß ÇÏ´Â °ÍµéÀº ´ÙÀ½°ú °°½À´Ï´Ù.


__asm__ __volatile__ (asms : output : input : clobber);
	

asms

½Öµû¿ÈÇ¥·Î µÑ·¯½ÎÀÎ assembly ¹®ÀÚ¿­. ¹®ÀÚ¿­¾È¿¡¼­ %n ÇüÅ·Πinput, output ÀÎÀÚµéÀ» »ç¿ëÇÒ ¼ö ÀÖÀ¸¸ç ÀÎÀÚµéÀÌ Ä¡È¯µÈ ÈÄ ±×´ë·Î ÄÄÆÄÀÏ µÈ assembly¿¡ ³ªÅ¸³³´Ï´Ù.

output

½°Ç¥·Î ±¸ºÐµÈ "constraint" (variable)µéÀÇ ¸®½ºÆ®ÀÌ¸ç °¢°¢ÀÌ ÀÌ inline assembly¿¡¼­ ¾²ÀÌ´Â output ÀÎÀÚ¸¦ ³ªÅ¸³À´Ï´Ù.

input

output°ú °°Àº ÇüÅÂÀ̸ç input ÀÎÀÚµéÀ» ³ªÅ¸³À´Ï´Ù.

clobber

½°Ç¥·Î ±¸ºÐµÇ´Â ½Öµû¿ÈÇ¥·Î µÑ·¯½ÎÀÎ ·¹Áö½ºÅÍ À̸§µéÀÇ ¸®½ºÆ®À̸ç input, output¿¡ ³ª¿ÀÁø ¾Ê¾ÒÁö¸¸ ÇØ´ç assembly¸¦ ¼öÇàÇÑ °á°ú·Î °ªÀÌ ¹Ù²î´Â ·¹Áö½ºÅ͵éÀ» ³ªÅ¸³À´Ï´Ù.

ouput, input, clobber´Â ºñ¾îÀÖ´Ù¸é µÚ¿¡¼­ ºÎÅÍ »ý·«µÉ ¼ö ÀÖ½À´Ï´Ù. ÇÏÁö¸¸ ¾Õ¿¡ ¿À´Â ÆÄ¶ó¹ÌÅͰ¡ ºñ¾îÀÖÀ» ¶§´Â :·Î Ç¥½Ã¸¦ ÇØÁÖ¾î¾ß ÇÕ´Ï´Ù. Áï,


__asm__ __volatile__(asms : output : input);  /* clobber ¾øÀ» ¶§ */
__asm__ __volatile__(asms : : input);	      /* output, clobber ¾øÀ» ¶§ */
      

ÀÇ ÇüÅ·Π»ý·« °¡´ÉÇÕ´Ï´Ù.

__asm__ Ű¿öµå´Â asmÀ¸·Îµµ ¾µ ¼ö ÀÖÁö¸¸ ansi¿É¼ÇÀ¸·Î ÄÄÆÄÀÏÇÏ°Ô µÇ¸é asmÀº Á¤ÀǵǾîÀÖÁö ¾Ê±â ¶§¹®¿¡ __asm__À¸·Î ¾²´Â °ÍÀÌ ÁÁ½À´Ï´Ù.

__volatile__Àº ÇØ´çÇÏ´Â inline assembly¸¦ optimizationÀ¸·Î ¾ø¾Ö°Å³ª À§Ä¡¸¦ ¹Ù²ÙÁö¸»¶ó´Â ¶æÀÔ´Ï´Ù. GCC manual¿¡ µû¸£¸é side effect°¡ ¾ø´Ù°í ¿©°ÜÁö´Â °æ¿ì assembly¸¦ ¾ø¾Ö°Å³ª loopÀÇ ¹ÛÀ¸·Î »©´Â optimizationÀ» ÇÒ ¼ö ÀÖ´Ù°í ÇÕ´Ï´Ù. ¿¹¸¦ µé¾î outputÀÌ ÀÖÁö¸¸ ½ÇÁ¦·Î outputÀ¸·Î ¾²ÀÎ º¯¼ö°¡ ±× ÀÌÈÄ·Î ÇÑ ¹øµµ ¾²ÀÌÁö ¾Ê¾Ò´Ù¸é ±× inline assembly´Â ÇÁ·Î±×·¥ÀÇ ¼öÇà¿¡ ¾Æ¹«·± ¿µÇâÀ» ³¢Ä¡Áö ¾Ê´Â´Ù°í »ý°¢ÇÏ°í ¾ø¾Ö¹ö¸®´Â °ÍÀÔ´Ï´Ù. ¹°·Ð Á¶°ÇÀ» Á¤È®ÇÏ°Ô Á¤ÇØÁÖ¸é ±»ÀÌ __volaitile__À» ºÙÀÌÁö ¾Ê´õ¶óµµ Á¦´ë·Î ÀÛµ¿ÇϰÚÁö¸¸ °¡²û¾¿ ¾û¶×ÇÏ°Ô µÇ¹ö¸®´Â °æ¿ìµµ Àֱ⶧¹®¿¡ Àß »ý°¢Çؼ­ inline assembly¸¦ ¾²°í __volatile__À» ºÙ¿©ÁÖ´Â °ÍÀÌ ÁÁ½À´Ï´Ù.

½ÇÁ¦·Î input, outputÀÌ ¾²ÀÎ ¿¹¸¦ º¸°Ú½À´Ï´Ù.


int test_and_set_bit(int nr, volatile unsigned * addr)
{
	int oldbit;

	__asm__ __volatile__(
		"lock; btsl %2,%1\n\tsbbl %0,%0"
		:"=r" (oldbit),"=m" (*addr)
		:"r" (nr));
		return oldbit;
}
      

asms

lock; btsl %2, %1
sbbl %0, %0
	    
output

"=r" (oldbit), "=m" (*addr)
	    
input

"r" (nr)
	    

asms¿¡¼­ \n\t ´ë½Å ;À» Àû¾îµµ µÇÁö¸¸ gcc¿¡ -S¿É¼ÇÀ» ÁÖ¾î assembly outputÀ» º¼ ¶§¿¡ ³ª¸ÓÁö ºÎºÐ°ú ÁÙÀ» ¸ÂÃß·Á¸é °¢ ÀνºÆ®·Â¼Ç »çÀ̸¦ \n\t·Î ±¸ºÐÇØÁÖ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. %0 %1 %2 °¢°¢Àº ÀÎÀÚµéÀ» ³ªÅ¸³»´Âµ¥ output, input¿¡ ÀÖ´Â ¼ø¼­´ë·Î ¹øÈ£°¡ ÁÖ¾îÁý´Ï´Ù. Áï, %0Àº oldbit, %1Àº *addr, %2´Â rÀÌ µË´Ï´Ù. À§ÀÇ assembly´Â


lock; btsl nr, *addr
sbbl oldbit
      

¿Í °°Àº ÀǹÌÀÔ´Ï´Ù. ÇÏÁö¸¸ instruction¿¡ µû¶ó¼­ ÀÎÀÚ·Î ¹«¾ùÀ» ¾µ ¼ö ÀÖ´Â Áö Á¦¾àÀÌ ÀÖ½À´Ï´Ù. ¿¹¸¦ µé¾î btslÀÇ °æ¿ì¿¡´Â ù¹øÂ° ÀÎÀÚ´Â ¹ü¿ë ·¹Áö½ºÅ͸¸À», µÎ¹øÂ° ÀÎÀڷδ ¹ü¿ë ·¹Áö½ºÅͳª memory»óÀÇ º¯¼ö°¡ µÉ ¼ö ÀÖ½À´Ï´Ù. µû¶ó¼­ gcc¿¡°Ô ¾î¶² ÀÎÀÚµéÀ» inline assembly¿¡¼­ ¾²°Ú´Ù´Â °Í »Ó¸¸¾Æ´Ï¶ó ±× ÀÎÀÚµéÀÌ ¾îµð¿¡ ÀÖ¾î¾ß ÇÏ´ÂÁöµµ Á¤ÇØÁÖ¾î¾ß ÇÕ´Ï´Ù. À̰ÍÀ» constraint¿¡¼­ Á¤ÇØÁÝ´Ï´Ù.

outputÀ» º¸¸é oldbit, *addr·Î ÀÎÀÚ¸¦ Á¤ÇØÁÖ¾ú°í oldbit¿¡ ´ëÇØ¼­´Â "=r", *addr¿¡ ´ëÇØ¼­´Â "=m"À» constraint·Î ÁÖ¾ú½À´Ï´Ù. rÀº ¹ü¿ë ·¹Áö½ºÅ͸¦ ¶æÇϰí mÀº memory operand¸¦ ¶æÇÕ´Ï´Ù. Áï, oldbit°ú *addrÀº outputÀ¸·Î ¾²À̸ç oldbitÀº ¹ü¿ë ·¹Áö½ºÅÍ¿©¾ßÇϰí *addrÀº memory operandÀ̾î¾ß ÇÑ´Ù´Â ¶æÀÔ´Ï´Ù. Output ÀÎÀÚÀÇ °æ¿ì¿£ Ç×»ó =¸¦ constraint¿¡ Æ÷ÇÔ½ÃÄѾßÇϴµ¥ À̰ÍÀº ÀÌ ÀÎÀÚÀÇ °ªÀº inline assemblyÀÇ °á°ú·Î ¹Ù²ð ¼ö ÀÖ´Ù¶ó´Â °ÍÀ» ¶æÇÕ´Ï´Ù.

Inputµµ °°½À´Ï´Ù. nrÀº inputÀ¸·Î ¾²ÀÌ¸ç ¹ü¿ë ·¹Áö½ºÅÍÀ̾î¾ß ÇÑ´Ù´Â constraint¸¦ °¡Áö°í ÀÖ½À´Ï´Ù. ÇÏÁö¸¸ inputÀÇ °æ¿ì¿¡´Â =ÀÌ ¾ø½À´Ï´Ù.

¿©·¯°³ÀÇ constraint¸¦ °°ÀÌ ¾µ ¼öµµ ÀÖ½À´Ï´Ù. Áï, "ir" (nr) ó·³ ¾µ ¼ö ÀÖ½À´Ï´Ù. ÀÌ·¸°Ô ¾²¸é ÁÖ¾îÁø ¿©·¯°³ÀÇ constraintÁß Çϳª¸¦ ¸¸Á·ÇÏ¸é µÈ´Ù´Â ¶æÀ¸·Î "ir"Àº immediate operand³ª ¹ü¿ë ·¹Áö½ºÅÍÁß Çϳª¸é µÈ´Ù´Â ¶æÀÔ´Ï´Ù.

À§ÀÇ ÇÔ¼ö´Â À̸§Ã³·³ addr·Î ÁÖ¾îÁø wordÀÇ nr¹øÂ° bitÀ» atomic test and setÇÕ´Ï´Ù. º¸Åë spin lockÀ̳ª semaphoreµîÀÇ synchornization constructµéÀ» ¸¸µé ¶§ ¾²ÀÔ´Ï´Ù. ±â´ÉÀ» »ý°¢Çغ¸¸é addrÀÇ constraint°¡ ¿Ö ¹ü¿ë ·¹Áö½ºÅͰųª memory operand°¡ ¾Æ´Ï¶ó memory operand·Î¸¸ °íÁ¤À̵Ǿî ÀÖ´Â Áö ¾Ë ¼ö ÀÖ½À´Ï´Ù. ¸¸¾à ¹ü¿ë ·¹Áö½ºÅÍ·Î ÇÒ´çµÇ¾î ¹ö¸®¸é *addr¿¡ ÀÖ´Â °ªÀ» ÇÒ´çµÈ ·¹Áö½ºÅÍ·Î loadÇÑ ÈÄ¿¡ btsl°ú sbblÀÌ ¼öÇàµÇ°í ±× °á°ú°ªÀÌ ´Ù½Ã *addr·Î storeµÇ¹Ç·Î atomicÇÏÁö ¾Ê°Ô µÇ¹ö¸³´Ï´Ù.

Gcc´Â constraint¿¡ µû¶ó¼­ °¢°¢ÀÇ ÀÎÀÚµéÀ» ÇÒ´çÇÑ ÈÄ¿¡ ÇÊ¿äÇϸé input º¯¼öµéÀ» ÇÒ´çµÈ °÷¿¡ loadÇÏ´Â code¸¦ »ý¼ºÇϰí inline assembly¿¡ %n ÇüÅÂÀÇ º¯¼öµéÀ» ÇÒ´çµÈ ½ÇÁ¦ º¯¼ö·Î Ä¡È¯ÇØ¼­ code¸¦ ³»¾î³õ½À´Ï´Ù. ÄÄÆÄÀÏ·¯´Â inline assembly°¡ ½ÇÇàµÈ ÈÄ¿¡ ±× °á°ú°ªµéÀÌ ¾îµð¿¡ ÀÖ´Â Áö ¾Ë°í ÀÖÀ¸¹Ç·Î ±× ÀÌÈÄÀÇ ÄÄÆÄÀÏÀ» °è¼Ó ÁøÇàÇÒ ¼ö ÀÖ½À´Ï´Ù.

±×·³ À§ÀÇ ÇÔ¼ö°¡ ½ÇÁ¦·Î ÄÄÆÄÀÏ µÇ¾úÀ» ¶§ ¾î¶² °á°ú°¡ ³ª¿À´Â Áö º¸°Ú½À´Ï´Ù.


.globl test_and_set_bit
	.type    test_and_set_bit,@function
test_and_set_bit:
	movl 4(%esp),%eax
	movl 8(%esp),%edx
#APP
	lock; btsl %eax,(%edx)
	sbbl %eax,%eax
#NO_APP
	ret
      

È£ÃâÇÏ´Â ºÎºÐ¿¡¼­ stack¿¡ addr, nr, return address¸¦ pushÇϰí test_and_set_bitÀ¸·Î controlÀÌ ³Ñ¾î¿À¸é, nrÀ» eax¿¡ addrÀ» edx¿¡ loadÇÑ ÈÄ #APP, #NO_APP»çÀÌÀÇ inline asembly°¡ ½ÇÇàµË´Ï´Ù.

btslÀÇ Ã¹¹øÂ° ÀÎÀÚ %2´Â nrÀÌ loadµÈ %eax·Î, µÎ¹øÂ° ÀÎÀÚ %1Àº addrÀÌ loadµÈ %edxÀÇ indirect addressingÀÎ (%edx)·Î, sbblÀÇ ÀÎÀÚÀÎ %0´Â %eax·Î ġȯµÈ °ÍÀ» ¾Ë ¼ö ÀÖ½À´Ï´Ù. Return °ªÀº Å©±â°¡ ¸Â´Â °æ¿ì %eax¸¦ ÅëÇØ¼­ °¡°í inline assembly ½ÇÇà ÈÄ returnÇÒ °ªÀÌ ÀÌ¹Ì %eax¿¡ ÀÖÀ¸¹Ç·Î ±×³É ret¸¦ ½ÇÇàÇÕ´Ï´Ù.

%0¿Í %2°¡ °°Àº ·¹Áö½ºÅÍ·Î ÇÒ´çµÇ¾ú´Âµ¥, gcc´Â ±âº»ÀûÀ¸·Î ¸ðµç inputº¯¼öµéÀº output º¯¼ö°¡ »ç¿ëµÇ±â Àü¿¡ ¸ðµÎ »ç¿ëµÈ´Ù°í »ý°¢Çؼ­ °ãÄ¡°Ô ÇÒ´çÇÒ ¼öµµ ÀÖ½À´Ï´Ù. À§ÀÇ °æ¿ì¿¡¼± %2°¡ %0°¡ »ç¿ëµÇ±â Àü¿¡ »ç¿ëµÇ¾úÀ¸¹Ç·Î ¹®Á¦°¡ ¾øÁö¸¸ ±×·¸Áö ¾ÊÀº °æ¿ì¿£ output º¯¼öÀÇ constraint¿¡ '&'¸¦ ´õÇØ early clobber¸¦ Á¤ÇØÁÖ¾î¾ß ÇÕ´Ï´Ù. Early clobber¿¡ ´ëÇØ¼± output º¯¼ö Ç׸ñ¿¡¼­ ¼³¸íÇϰڽÀ´Ï´Ù.

ÀÌÁ¦ Àüü¸¦ ÇÑ ¹ø º¸¾Ò½À´Ï´Ù. ±×´ÙÁö º¹ÀâÇÏÁö ¾ÊÁö¿ä? ÀÌÁ¦ °¢ ºÎºÐ¿¡´ëÇØ ÀÚ¼¼È÷ ¾Ë¾Æº¸µµ·Ï ÇϰڽÀ´Ï´Ù.