Appendix B. String.h inline assembly

static inline char * strcpy(char * dest,const char *src)
{
	int d0, d1;
	__asm__ __volatile__("cld\n"
		"1:\tlodsb\n\t"
		"stosb\n\t"
		"testb %%al,%%al\n\t"
		"jne 1b"
		:"=&S"(d0),"=&D"(d1)
		: "0" (src),"1" (dest)
		:"ax");
	return dest;
}
  • Line 3: cld(clear direction flag) EFLAGS의 DF 플래그를 클리어한다. DF 플래그가 0이라면, string 오퍼레이션에서 인덱스 레지스터(ESI and/or EDI)가 증가한다.

  • Line 4: lods(load string) ds:esi에서 1/2/4바이트를 AL, AX 또는 EAX 레지스터에 로드한다. 읽은 만큼 esi 레지스터 값이 DF플래그에 따라 증가 또는 감소한다.

  • Line 5: stos(store string) AL, AX 또는 EAX 레지스터에서 1/2/4 바이트를 es:edi/di에 store한다. 저장한 만큼 edi 레지스터 값이 DF플래그에 따라 증가 또는 감소한다.

  • Line 6~7: 읽은 값(ax)가 NULL이 아니면 1번 라벨로 돌아간다.

  • Line 8: 이하 생략

    • input: esi(dummy0), edi(dummy1)

    • output: esi(src), edi(dest)

    • clobber: ax

circle-exclamation
  • Line 4~5: count의 값을 1 감소 시킨다. 음수라면, 2번 라벨로 점프한다.

  • Line 6~9: strcpy의 내용과 동일

  • Line 10~12: 남은 count만큼 stosb 반복한다. 즉 count만큼 NULL을 edi에 복사한다.

  • Line 3: DF 플래그 클리어.

  • Line 4~6:

    • repne: zero flag가 0일때 동안,

    • scas(scan string) ax/al/eax를 edi 레지스터의 값과 비교(cmp)하여 플래그를 설정한다.

    • 즉, src의 NULL 위치 바로 전까지 이동한다는 말이다.

  • Line 7~10: strcpy와 동일

  • Line 4: DF 플래그 클리어.

  • Line 5~7:

    • repne: zero flag가 0일때 동안,

    • scas(scan string) ax/al/eax를 edi 레지스터의 값과 비교(cmp)하여 플래그를 설정한다.

    • 즉, src의 NULL 위치 바로 전까지 이동한다는 말이다.

  • Line 8: ecx를 인자로 받은 count로 세팅한다.

  • Line 9~14: ecx를 감소시키며 1바이트를 복사한다(esi -> edi)

  • Line 5: DF 플래그 클리어.

  • Line 6~7: ds:esi에서 1바이트를 ax에 로드하고 es:edi의 값과 cmp한다.

  • Line 8: 같지 않다면 2번 라벨로 점프한다.

  • Line 9~12: ax가 NULL인지 확인한다. 아니라면 1번 라벨로 점프한다. 맞다면, eax를 0으로 세팅하고 리턴한다.

  • Line 13~15: 1을 리턴할지, 1을 리턴할지 결정한다.

  • Line 5: DF 플래그 클리어.

  • Line 6~7: count를 감소하고 음수라면 2번 라벨로 점프한다.

  • Line 8~9: ds:esi에서 1바이트를 ax에 로드하고 es:edi의 값과 cmp한다.

  • Line 10: 같지 않다면 3번 라벨로 점프한다.

  • Line 11~14: ax가 NULL인지 확인한다. 아니라면 1번 라벨로 점프한다. 맞다면, eax를 0으로 세팅하고 리턴한다.

  • Line 15~17: 1을 리턴할지, 1을 리턴할지 결정한다.

  • Line 5: DF 플래그 클리어.

  • Line 6: c를 ah으로 이동

  • Line 7~8: ds:esi로부터 1바이트를 읽고, al에 저장하고 ah와 비교한다.

  • Line 9: 동일하면 2번 라벨로 점프한다.

  • Line 10~11: NULL에 도달할 때까지 1번 라벨로 점프한다.

  • Line 12~14: 못찾으면 0을 리턴하고, 찾았다면 찾은 주소(esi)를 리턴한다.

  • Line 5: DF 플래그 클리어.

  • Line 6: c를 ah으로 이동

  • Line 7~8: ds:esi로부터 1바이트를 읽고, al에 저장하고 ah와 비교한다.

  • Line 9: 동일하지 않으면 2번 라벨로 점프한다.

  • Line 10~11: 발견한 주소를 __res에 저장한다.

  • Line 12~14: NULL에 도달하지 않았다면 1번 라벨로 돌아간다.

  • Line 5: DF 플래그 클리어.

  • Line 6~11: ct의 길이를 구하여 edx에 저장.

  • Line 12~14: esi에서 1바이트를 읽고 al에 저장, NULL인지 확인

  • Line 15~19: ct 중 al과 일치하는 바이트가 있는지 확인, 없다면 리턴한다.

  • Line 20: 일치하는 문자가 있다면(je) 1번 라벨로 돌아가 다음 문자를 비교한다.

  • Line 5: DF 플래그 클리어.

  • Line 6~11: ct의 길이를 구하여 edx에 저장.

  • Line 12~14: esi에서 1바이트를 읽고 al에 저장, NULL인지 확인

  • Line 15~19: ct 중 al과 일치하는 바이트가 있는지 확인, 있다면 리턴한다.

  • Line 20: 일치하는 문자가 없다면(jne) 1번 라벨로 돌아가 다음 문자를 비교한다.

  • Line 5: DF 플래그 클리어.

  • Line 6~11: ct의 길이를 구하여 edx에 저장.

  • Line 12~14: esi에서 1바이트를 읽고 al에 저장, NULL인지 확인

  • Line 15~19: ct 중 al과 일치하는 바이트가 있는지 확인, 있다면 찾은 주소를 리턴한다.

  • Line 20: 일치하는 문자가 없다면(jne) 1번 라벨로 돌아가 다음 문자를 비교한다.

  • Line 5: DF 플래그 클리어.

  • Line 6~11: ct의 길이를 구하여 edx에 저장.

  • Line 12~14: ct를 edi에 세팅, esi를 eax에 세팅, ecx에 구한 길이를 저장.

  • Line 15~17: cs에서 ct와 일치하는 문자열이 있는지 확인, 있다면 찾은 주소를 리턴한다.

  • Line 18~22: 문자열 끝에 도달하면, 0을 리턴 아니라면 index를 증가시켜 1번 라벨로 돌아간다.

  • Line 5: DF 플래그 클리어.

  • Line 6~10: s의 길이를 구하여 __res에 저장.

Last updated