4byte씩 끊어서 바이트 오더를 바꿀려면 어떻게 해야할까요?

toy의 이미지

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

lunarainbow의 이미지

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];
}

허걱.. 소스 대충 짜다보니.. 어느새 답변이 올라왔네여..

그.. 그런데..;; 장난 아니시네요 ^^;

어셈이라니..;;

기죽어서 이런거 올리기두 심란하네요.. ㅡㅜ

pynoos의 이미지

lunarainbow wrote:
허걱.. 소스 대충 짜다보니.. 어느새 답변이 올라왔네여..

그.. 그런데..;; 장난 아니시네요 ^^;

어셈이라니..;;

기죽어서 이런거 올리기두 심란하네요.. ㅡㅜ

기죽지 마세요... 그래도 꾸준히 답글주시는 것이 명랑비비를 만드는 일 아니겠습니까...

처음 질문하신분과 직접적인 답은 아니지만, 다음과 같은 코드도 있습니다.

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로 표현하자니.. 위와같이 되는 군요.

unipro의 이미지

#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

xfmulder의 이미지

저도 자주 쓰는 함수인데 특히 실시간 소켓데이타 처리시 바이트 오더링에 필요하겠지요.

쉬프트 연산하려면 오래 걸리니까 (?)
그냥 바이트단위로 복사하는게 더 빠를것 같네요.

/*
* 바이트 순서 바꿈 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 로 됩니다.

내 자식들도 나처럼 !!

mach의 이미지

Quote:
쉬프트 연산하려면 오래 걸리니까 (?)

메모리 복사보다는, shift연산이 더 빠르다고 알고 있습니다만.

위의 좋은 의견들도 있지만, 저는 htons(), htonl(), ntohs(), ntohl()을 그냥 사용합니다. 이유는 그냥 씁니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

Necromancer의 이미지

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

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.