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]
장점: 짧은코드 / 빠른코드단점: 이식성 리눅스/윈도우 만 됨.
장점: 짧은코드 / 빠른코드
단점: 이식성 리눅스/윈도우 만 됨.
테스트도 안하고 짠거지만 될겁니다.
Re: 4byte씩 끊어서 바이트 오더를 바꿀려면 어떻게 해야할까요?
정말 어떻게 할 지에 대해 어떠한 아이디어도 없으신 건지,
아니면 가장 효율적인 방법을 원하시는 건지 모르겠네요.
전자라면, 알고리즘 공부를 좀 더 하셨으면 합니다.
Orion Project : http://orionids.org
[code:1]char *a;char buf[4];
허걱.. 소스 대충 짜다보니.. 어느새 답변이 올라왔네여..
그.. 그런데..;; 장난 아니시네요 ^^;
어셈이라니..;;
기죽어서 이런거 올리기두 심란하네요.. ㅡㅜ
[quote="lunarainbow"]허걱.. 소스 대충 짜다보니.. 어
기죽지 마세요... 그래도 꾸준히 답글주시는 것이 명랑비비를 만드는 일 아니겠습니까...
처음 질문하신분과 직접적인 답은 아니지만, 다음과 같은 코드도 있습니다.
개념은 어셈블리어에서 온것이지만, C로 표현하자니.. 위와같이 되는 군요.
---
http://coolengineer.com
[code:1]#define STR_TO_INT32(s)
질문자님께서 완전한 프로그램으로 작성하시구요,
이 코드상의 미흡한 부분은 공부하시면서 보충해보세요.
그럼 건투를 빌겠습니다.
내 블로그: 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. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
공용체 쓰면 쉽습니다.
굳이 어셈블리로 짠다면 아래 라인을 인라인어셈으로 집어넣으면 됩니다.
(data는 바이트오더를 바꿀 값이 있는 변수라고 가정한다면..)
특히 레지스터에 데이터가 있는 경우는 bswap 명령 한개만 달랑 쓰면 됩니다. 단, cpu가 486이상이어야만 함
Written By the Black Knight of Destruction
댓글 달기