C.2. »ç·Ê ºÐ¼®

¸®´ª½º Ä¿³Î¿¡ ÀÌ¹Ì »ç¿ëµÈ ¼ö ¸¹Àº ¿¹¸¦ ÅëÇØ ¾î¶² ½ÄÀ¸·Î ÀζóÀÎ ¾î¼Àºí¸®°¡ »ç¿ëµÆ´ÂÁö ¾Ë¾Æº¸ÀÚ.

C.2.1. strcpy()

¾Æ·¡ ¼Ò½º ÄÚµå´Â include/asm-i386/string.h¿¡ ÀÖ´Â strcpy() ÇÔ¼ö¸¦ °¡Á®¿Í ÄÄÆÄÀÏ ÇØº¸±â À§ÇØ Á¶±Ý Ãß°¡ÇÑ ÄÚµå´Ù.

	/* test.c */
	static inline char * strcpy(char * dest,const char *src)
	{
	int d0, d1, d2;
	__asm__ __volatile__(
		"1:\tlodsb\n\t"
		"stosb\n\t"
		"testb %%al,%%al\n\t"
		"jne 1b"
		: "=&S" (d0), "=&D" (d1), "=&a" (d2)
		:"0" (src),"1" (dest) : "memory");
	return dest;
	}

	int main()
	{
		char a[] = "1234";
		char b[] = "4567";

		strcpy(a, b);

		return 0;
	}
	

ÄÄÆÄÀÏÀº 'gcc -S -c test.c'¶ó°í ÇÑ´Ù. ±×·¯¸é test.s°¡ »ý±æ °ÍÀÌ´Ù. test.s´Â ´ÙÀ½°ú °°´Ù.

		.file	"test.c"
		.version	"01.01"
	gcc2_compiled.:
	.section	.rodata
	.LC0:
		.string	"1234"
	.LC1:
		.string	"5678"
	.text
		.align 4
	.globl main
		.type	 main,@function
	main:
		pushl %ebp
		movl %esp,%ebp
		subl $24,%esp
		leal -8(%ebp),%eax
		movl .LC0,%edx
		movl %edx,-8(%ebp)
		movb .LC0+4,%al
		movb %al,-4(%ebp)
		leal -16(%ebp),%eax
		movl .LC1,%edx
		movl %edx,-16(%ebp)
		movb .LC1+4,%al
		movb %al,-12(%ebp)
		addl $-8,%esp
		leal -16(%ebp),%eax
		pushl %eax
		leal -8(%ebp),%eax
		pushl %eax
		call strcpy
		addl $16,%esp
		xorl %eax,%eax
		jmp .L3
		.p2align 4,,7
	.L3:
		movl %ebp,%esp
		popl %ebp
		ret
	.Lfe1:
		.size	 main,.Lfe1-main
		.align 4
		.type	 strcpy,@function
	strcpy:
		pushl %ebp
		movl %esp,%ebp
		subl $28,%esp
		pushl %edi
		pushl %esi
		pushl %ebx
		movl 12(%ebp),%esi
		movl 8(%ebp),%edi
#APP
		1:	lodsb
		stosb
		testb %al,%al
		jne 1b
#NO_APP
		movl %esi,%ecx
		movl %edi,%edx
		movl %ecx,%ebx
		movl %ebx,-4(%ebp)
		movl %edx,%edx
		movl %edx,-8(%ebp)
		movl %eax,%eax
		movl %eax,-12(%ebp)
		movl 8(%ebp),%eax
		jmp .L2
	.L2:
		leal -40(%ebp),%esp
		popl %ebx
		popl %esi
		popl %edi
		movl %ebp,%esp
		popl %ebp
		ret
	.Lfe2:
		.size	 strcpy,.Lfe2-strcpy
		.ident	"GCC: (GNU) 2.95.3 20010315 (release)"
	

ÀζóÀÎ ¾î¼Àºí¸®´Â #APP¿Í #NO_APP»çÀÌ¿¡ Á¸ÀçÇÑ´Ù.

: "=&S" (d0), "=&D" (d1), "=&a" (d2)

outputÀÇ ±¸¼ºÀ» ³ªÅ¸³½´Ù. "=&S" (d0)´Â d0¸¦ 'si' ·¹Áö½ºÅÍ¿¡ ÀúÀåÇÏ´Â °ÍÀ̰í "=&D" (d1)Àº d1À» 'di' ·¹Áö½ºÅÍ¿¡ ÀúÀåÇ϶õ °ÍÀ̰í "=&a" (d2)´Â d2¸¦ 'a' ·¹Áö½ºÅÍ¿¡ ÀúÀåÇ϶õ °ÍÀÌ´Ù.

test.s¿¡ ÀÇÇÏ¸é ¾î¼Àºí¸® Äڵ尡 ½ÇÇàµÈ ÈÄ outputÀ¸·Î d0, d1, d2°¡ Àִµ¥ #NO_APP ¹Ù·Î ¹ØÀÇ 3ÁÙÀÌ ÀÌ ¿ªÇÒÀ» ÇÑ´Ù. d2´Â %ebx¿¡ ÇÒ´çµÆÀ½À» ¾Ë ¼ö ÀÖ´Ù.

:"0" (src),"1" (dest)

inputÀÇ ±¸¼ºÀ» ³ªÅ¸³½´Ù. "0" (src)´Â src°¡ 0¹øÂ° ¿ÀÆÛ·£µå¿Í °°Àº À§Ä¡¸¦ Á¡À¯Ç϶õ ¸»·Î %0ÀÎ d0¸¦ ÀǹÌÇÑ´Ù. ¶Ç d0°¡ si¸¦ »ç¿ëÇϹǷΠ°á±¹ siÀÇ Ãʱ⠰ªÀÌ src°¡µÈ´Ù. dest´Â %1ÀÎ di¿¡ ÀԷµȴÙ.

test.s¿¡ ÀÇÇϸé #APP ¹Ù·Î ÀüÀÇ µÎÁÙÀÌ input¿¡ ÇØ´çÇϰí %esi¿Í %edi¿¡ src, dest¸¦ ÀÔ·ÂÇØ ÁØ´Ù.

: "memory"

clobber¿¡ ÁöÁ¤µÈ "memory"´Â ÄÄÆÄÀÏ·¯¿¡°Ô ¾î¼Àºí¸®Äڵ尡 ¸Þ¸ð¸®ÀÇ ¾îµò°¡¸¦ º¯°æÇÑ´Ù°í °¡¸£ÃÄ ÁÖ´Â °ÍÀÌ´Ù. ÀÌ °ÍÀ» »ç¿ëÇÏÁö ¾ÊÀ¸¸é ¾î¼Àºí¸®Äڵ忡¼­ ¸Þ¸ð¸®ÀÇ ³»¿ëÀ» º¯°æÇÏ´Â °ÍÀ» ÄÄÆÄÀÏ·¯´Â ÀüÇô ¾Ë ¼ö ¾ø´Ù. Àß ¸øÇÏ¸é ¾î¼Àºí¸®¿¡¼­ °íÄ£ °ª°ú ´Ù¸¥ °ªÀ» ÄÄÆÄÀÏ·¯ ´Â »ç¿ëÇϰí ÀÖÀ» °¡´É¼ºµµ ÀÖ´Ù. "memory"¸¦ ¸í½ÃÇØ ÁÖ¸é ÄÄÆÄÀÏ·¯´Â ¾î¼Àºí¸® Äڵ带 ½Ç ÇàÇϱâ Àü/ÈÄ¿¡ ·¹Áö½ºÅÍ¿¡ ÀúÀåµÇ¾î ÀÖ´Â ¸ðµç º¯¼öÀÇ °ªÀ» °»½ÅÇϵµ·Ï ÇÑ´Ù.

"1:\tlodsb\n\t"

1:Àº labelÀ» ÀǹÌÇÑ´Ù. loadsb ¸í·ÉÀ¸·Î al ·¹Áö½ºÅÍ¿¡ es:esiÀÇ ³»¿ëÀ» ÀÐ¾î ¿Â´Ù. ¿©±â¼­ srcÀÇ ³»¿ëÀ» ÀÐ¾î ¿Â´Ù. ¸í·É ½ÇÇàÈÄ esi´Â ÀÚµ¿À¸·Î 1ÀÌ Áõ°¡ÇÑ´Ù(¹ÙÀÌÆ® ´ÜÀ§·Î Àб⠶§¹®).

"stosb\n\t"

alÀÇ °ªÀ» es:edi¿¡ ÀúÀåÇÑ´Ù. ediµµ ¸í·É ½ÇÇà ÈÄ 1 Áõ°¡ÇÑ´Ù.

"testb %%al,%%al\n\t"

alÀÇ ³»¿ëÀÌ 0ÀÎÁö Å×½ºÆ®ÇÑ´Ù. ½ºÆ®¸µÀ» º¹»çÇÒ ¶© NULL ij¸¯ÅͰ¡ ³ª¿Ã ¶§ ±îÁö º¹»çÇϱ⠶§¹®¿¡ 0ÀÎÁö ÆÇº°ÇÑ´Ù.

"jne 1b"

0ÀÌ ¾Æ´Ñ °æ¿ì, Áï NULL ij¸¯ÅͰ¡ ¾Æ´Ñ °æ¿ì °è¼ÓÇØ¼­ º¹»çÇÑ´Ù.

C.2.2. _set_gate()

arch/i386/kernel/trap.c¿¡ ÀÖ´Â _set_gate()ÀÇ ³»¿ëÀ» °¡Á®´Ù ÄÄÆÄÀÏ Çϱâ À§ÇØ ¾à°£ º¯°æÇÑ °ÍÀÌ´Ù.

/* sg.c */

#define __KERNEL_CS 0x10

#define _set_gate(gate_addr,type,dpl,addr) \
do { \
  int __d0, __d1; \
  __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
	"movw %4,%%dx\n\t" \
	"movl %%eax,%0\n\t" \
	"movl %%edx,%1" \
	:"=m" (*((long *) (gate_addr))), \
	 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
	:"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
	 "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \
} while (0)

int main()
{
	_set_gate(0, 1, 2, 3);
	return 0;
}

'gcc -S -c sg.c'·Î ÄÄÆÄÀÏÇÑ °ÍÀº ´ÙÀ½°ú °°´Ù.

	.file	"sg.c"
	.version	"01.01"
gcc2_compiled.:
.text
	.align 4
.globl main
	.type	 main,@function
main:
	pushl %ebp
	movl %esp,%ebp
	subl $24,%esp
	nop
	.p2align 4,,7
.L3:
	movl $3,%edx
	movl $1048576,%ecx
	movl %ecx,%eax
#APP
	movw %dx,%ax
	movw $-16128,%dx
	movl %eax,0
	movl %edx,4
#NO_APP
	movl %eax,%ecx
	movl %ecx,-4(%ebp)
	movl %edx,%eax
	movl %eax,-8(%ebp)
.L5:
	jmp .L4
	.p2align 4,,7
.L6:
	jmp .L3
	.p2align 4,,7
.L4:
	xorl %eax,%eax
	jmp .L2
	.p2align 4,,7
.L2:
	movl %ebp,%esp
	popl %ebp
	ret
.Lfe1:
	.size	 main,.Lfe1-main
	.ident	"GCC: (GNU) 2.95.3 20010315 (release)"

:"i" ((short) (0x8000+(dpl<<13)+(type<<8))), "3" ((char *) (addr)),"2" (__KERNEL_CS << 16));

inputÀ¸·Î Á¤ÀÇµÈ °Í µéÀÌ´Ù. "3", "2"´Â °¢°¢ %3(__d0), %2(__d1)·Î ´ëÀÀµÇµµ·Ï ÇÑ´Ù. $APP ÀüÀÇ 3ÁÙ Áß À­ 2ÁÙÀÌ "3", "2"¿¡ ÇØ´çÇÏ´Â °ÍµéÀÌ´Ù.

:"=m" (*((long *) (gate_addr))), "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1)

outputÀ¸·Î Á¤ÀÇµÈ °Í µé. %0Àº °ªÀÌ 0À̵ǰí(main¿¡¼­ _set_gate(0, 1, 2, 3)À¸·Î Ç߱⠶§¹®¿¡) %1Àº 4°¡ µÈ´Ù.