4byte씩 끊어서 바이트 오더를 바꿀려면 어떻게 해야할까요? 예를들어 unsigned char * a ;
위의 a 변수에 {1,2,3,4,5,6,7,8} 이 있다면
{4,3,2,1,8,7,6,5 }로 바꾸고 싶습니다..
장점: 짧은코드 / 빠른코드 단점: 이식성 리눅스/윈도우 만 됨.
테스트도 안하고 짠거지만 될겁니다.
#include <stdio.h> #include <string.h> #if defined(WIN32) void pascal MZ_Cvt4Swap(void *s_Data, int s_Count) { asm { PUSH EBX; MOV ECX, DWORD PTR s_Count; MOV EBX, DWORD PTR s_Data; L_Loop:; MOV EAX, DWORD PTR [EBX]; XCHG AL, AH; ROL EAX, 16; XCHG AL, AH; MOV DWORD PTR [EBX], EAX ADD EBX, 4; LOOP short L_Loop; POP EBX; } } #else void MZ_Cvt4Swap(void *s_Data, int s_Count) { __asm__ __volatile__( "\n\t" "0:\n\t" "movl (%%ebx), %%eax\n\t" "xchgb %%al, %%ah\n\t" "roll $16, %%eax\n\t" "xchgb %%al, %%ah\n\t" "movl %%eax, (%%ebx)\n\t" "addl $4, %%ebx\n\t" "loop 0b\n\t" "\n\t" : : "b"(s_Data), "c"(s_Count) ); } #endif int main(int s_Argc, char *s_Argv[]) { char s_Data[] = "12345678"; (void)MZ_Cvt4Swap(s_Data, strlen(s_Data) >> 2); MT_Dump(s_Data, 8); fprintf(stdout, "[%s]\n", s_Data); return(0); }
정말 어떻게 할 지에 대해 어떠한 아이디어도 없으신 건지, 아니면 가장 효율적인 방법을 원하시는 건지 모르겠네요. 전자라면, 알고리즘 공부를 좀 더 하셨으면 합니다.
Orion Project : http://orionids.org
char *a; char buf[4]; int i, j; for ( i = 0; i < strlen(a) / 4; i++ ) { strncpy(buf, (a + i), 4); for ( j = 0; j < 4; j++ ) { *(a + ( i * 4 ) + j) = buf[3 - j]; } } // 4의 배수로 끊어지지 않아서, 남은 애들 처리해 주기 for ( j = 0; j < strlen(a) % 4; j++) { strncpy(buf, (a + i), strlen(a) % 4); *(a + ( i * 4 ) + j) = buf[(strlen(a) % 4) - j]; }
허걱.. 소스 대충 짜다보니.. 어느새 답변이 올라왔네여..
그.. 그런데..;; 장난 아니시네요 ^^;
어셈이라니..;;
기죽어서 이런거 올리기두 심란하네요.. ㅡㅜ
허걱.. 소스 대충 짜다보니.. 어느새 답변이 올라왔네여.. 그.. 그런데..;; 장난 아니시네요 ^^; 어셈이라니..;; 기죽어서 이런거 올리기두 심란하네요.. ㅡㅜ
기죽지 마세요... 그래도 꾸준히 답글주시는 것이 명랑비비를 만드는 일 아니겠습니까...
처음 질문하신분과 직접적인 답은 아니지만, 다음과 같은 코드도 있습니다.
unsigned long conv( unsigned long x ) { unsigned long t = x; x = ( (x >> 8) | ( x & 0x000000ff ) << 24 ) & 0xff00ff00; t = ( (t << 8) | ( t & 0xff000000 ) >> 24 ) & 0x00ff00ff; return (x | t); }
개념은 어셈블리어에서 온것이지만, C로 표현하자니.. 위와같이 되는 군요.
---http://coolengineer.com
#define STR_TO_INT32(s) \ ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]) #define INT32_TO_STR(i, s) \ do { \ s[0] = ((i >> 24) & 0xFF); \ s[1] = ((i >> 16) & 0xFF); \ s[2] = ((i >> 8) & 0xFF); \ s[3] = (i & 0xFF); \ } while(0) #define SWAP32(x) \ x = ((((x) & 0xff000000) >> 24) | \ (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | \ (((x) & 0x000000ff) << 24)) typedef u_int32_t INT;
질문자님께서 완전한 프로그램으로 작성하시구요, 이 코드상의 미흡한 부분은 공부하시면서 보충해보세요. 그럼 건투를 빌겠습니다.
내 블로그: http://unipro.tistory.com
저도 자주 쓰는 함수인데 특히 실시간 소켓데이타 처리시 바이트 오더링에 필요하겠지요. 쉬프트 연산하려면 오래 걸리니까 (?) 그냥 바이트단위로 복사하는게 더 빠를것 같네요.
/* * 바이트 순서 바꿈 SUN <---> Intel Convert */ int convert(char *out, char *in, int n) { for (n-- ; n >= 0; n-- ) *out++ = *(in+n); return(n); }
(사용법) int old , new ;
old = 0x01020304 ; convert((char*)&new, 4, (char *) &old);
new == 0x04030201 로 됩니다.
내 자식들도 나처럼 !!
쉬프트 연산하려면 오래 걸리니까 (?)
위의 좋은 의견들도 있지만, 저는 htons(), htonl(), ntohs(), ntohl()을 그냥 사용합니다. 이유는 그냥 씁니다.
------------------ P.S. -------------- 지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
union temp { char bytes[4]; long data; }; long exchange(long a) { union b; char t; b.data=a t=b.bytes[3]; b.bytes[3]=b.bytes[0]; b.bytes[0]=t; t=b.bytes[2]; b.bytes[2]=b.bytes[1]; b.bytes[1]=t; return b.data; }
굳이 어셈블리로 짠다면 아래 라인을 인라인어셈으로 집어넣으면 됩니다. (data는 바이트오더를 바꿀 값이 있는 변수라고 가정한다면..) 특히 레지스터에 데이터가 있는 경우는 bswap 명령 한개만 달랑 쓰면 됩니다. 단, cpu가 486이상이어야만 함
mov eax,[data] bswap eax mov [data],eax
Written By the Black Knight of Destruction
텍스트 포맷에 대한 자세한 정보
<code>
<blockcode>
<apache>
<applescript>
<autoconf>
<awk>
<bash>
<c>
<cpp>
<css>
<diff>
<drupal5>
<drupal6>
<gdb>
<html>
<html5>
<java>
<javascript>
<ldif>
<lua>
<make>
<mysql>
<perl>
<perl6>
<php>
<pgsql>
<proftpd>
<python>
<reg>
<spec>
<ruby>
<foo>
[foo]
장점: 짧은코드 / 빠른코드단점: 이식성 리눅스/윈도우 만 됨.
장점: 짧은코드 / 빠른코드
단점: 이식성 리눅스/윈도우 만 됨.
테스트도 안하고 짠거지만 될겁니다.
#include <stdio.h> #include <string.h> #if defined(WIN32) void pascal MZ_Cvt4Swap(void *s_Data, int s_Count) { asm { PUSH EBX; MOV ECX, DWORD PTR s_Count; MOV EBX, DWORD PTR s_Data; L_Loop:; MOV EAX, DWORD PTR [EBX]; XCHG AL, AH; ROL EAX, 16; XCHG AL, AH; MOV DWORD PTR [EBX], EAX ADD EBX, 4; LOOP short L_Loop; POP EBX; } } #else void MZ_Cvt4Swap(void *s_Data, int s_Count) { __asm__ __volatile__( "\n\t" "0:\n\t" "movl (%%ebx), %%eax\n\t" "xchgb %%al, %%ah\n\t" "roll $16, %%eax\n\t" "xchgb %%al, %%ah\n\t" "movl %%eax, (%%ebx)\n\t" "addl $4, %%ebx\n\t" "loop 0b\n\t" "\n\t" : : "b"(s_Data), "c"(s_Count) ); } #endif int main(int s_Argc, char *s_Argv[]) { char s_Data[] = "12345678"; (void)MZ_Cvt4Swap(s_Data, strlen(s_Data) >> 2); MT_Dump(s_Data, 8); fprintf(stdout, "[%s]\n", s_Data); return(0); }Re: 4byte씩 끊어서 바이트 오더를 바꿀려면 어떻게 해야할까요?
정말 어떻게 할 지에 대해 어떠한 아이디어도 없으신 건지,
아니면 가장 효율적인 방법을 원하시는 건지 모르겠네요.
전자라면, 알고리즘 공부를 좀 더 하셨으면 합니다.
Orion Project : http://orionids.org
[code:1]char *a;char buf[4];
char *a; char buf[4]; int i, j; for ( i = 0; i < strlen(a) / 4; i++ ) { strncpy(buf, (a + i), 4); for ( j = 0; j < 4; j++ ) { *(a + ( i * 4 ) + j) = buf[3 - j]; } } // 4의 배수로 끊어지지 않아서, 남은 애들 처리해 주기 for ( j = 0; j < strlen(a) % 4; j++) { strncpy(buf, (a + i), strlen(a) % 4); *(a + ( i * 4 ) + j) = buf[(strlen(a) % 4) - j]; }허걱.. 소스 대충 짜다보니.. 어느새 답변이 올라왔네여..
그.. 그런데..;; 장난 아니시네요 ^^;
어셈이라니..;;
기죽어서 이런거 올리기두 심란하네요.. ㅡㅜ
[quote="lunarainbow"]허걱.. 소스 대충 짜다보니.. 어
기죽지 마세요... 그래도 꾸준히 답글주시는 것이 명랑비비를 만드는 일 아니겠습니까...
처음 질문하신분과 직접적인 답은 아니지만, 다음과 같은 코드도 있습니다.
unsigned long conv( unsigned long x ) { unsigned long t = x; x = ( (x >> 8) | ( x & 0x000000ff ) << 24 ) & 0xff00ff00; t = ( (t << 8) | ( t & 0xff000000 ) >> 24 ) & 0x00ff00ff; return (x | t); }개념은 어셈블리어에서 온것이지만, C로 표현하자니.. 위와같이 되는 군요.
---
http://coolengineer.com
[code:1]#define STR_TO_INT32(s)
#define STR_TO_INT32(s) \ ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]) #define INT32_TO_STR(i, s) \ do { \ s[0] = ((i >> 24) & 0xFF); \ s[1] = ((i >> 16) & 0xFF); \ s[2] = ((i >> 8) & 0xFF); \ s[3] = (i & 0xFF); \ } while(0) #define SWAP32(x) \ x = ((((x) & 0xff000000) >> 24) | \ (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | \ (((x) & 0x000000ff) << 24)) typedef u_int32_t INT;질문자님께서 완전한 프로그램으로 작성하시구요,
이 코드상의 미흡한 부분은 공부하시면서 보충해보세요.
그럼 건투를 빌겠습니다.
내 블로그: http://unipro.tistory.com
저도 자주 쓰는 함수인데 특히 실시간 소켓데이타 처리시 바이트 오더링에
저도 자주 쓰는 함수인데 특히 실시간 소켓데이타 처리시 바이트 오더링에 필요하겠지요.
쉬프트 연산하려면 오래 걸리니까 (?)
그냥 바이트단위로 복사하는게 더 빠를것 같네요.
/*
* 바이트 순서 바꿈 SUN <---> Intel Convert
*/
int convert(char *out, char *in, int n)
{
for (n-- ; n >= 0; n-- ) *out++ = *(in+n);
return(n);
}
(사용법)
int old , new ;
old = 0x01020304 ;
convert((char*)&new, 4, (char *) &old);
new == 0x04030201 로 됩니다.
내 자식들도 나처럼 !!
[quote]쉬프트 연산하려면 오래 걸리니까 (?) [/quote]메
메모리 복사보다는, shift연산이 더 빠르다고 알고 있습니다만.
위의 좋은 의견들도 있지만, 저는 htons(), htonl(), ntohs(), ntohl()을 그냥 사용합니다. 이유는 그냥 씁니다.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
공용체 쓰면 쉽습니다.
union temp { char bytes[4]; long data; }; long exchange(long a) { union b; char t; b.data=a t=b.bytes[3]; b.bytes[3]=b.bytes[0]; b.bytes[0]=t; t=b.bytes[2]; b.bytes[2]=b.bytes[1]; b.bytes[1]=t; return b.data; }굳이 어셈블리로 짠다면 아래 라인을 인라인어셈으로 집어넣으면 됩니다.
(data는 바이트오더를 바꿀 값이 있는 변수라고 가정한다면..)
특히 레지스터에 데이터가 있는 경우는 bswap 명령 한개만 달랑 쓰면 됩니다. 단, cpu가 486이상이어야만 함
Written By the Black Knight of Destruction
댓글 달기