アセンブラでエンディアン変換してみます。
32bitの変数aのエンディアン変換です。EAXとEBXレジスタを使います。
まずは1Byteのコピーから。
takk@deb9:~/tmp$ cat -n t.c 1 #include <stdio.h> 2 int main() 3 { 4 unsigned long a; 5 asm("movq $0x12345678,-0x8(%rbp)"); 6 asm("mov -0x8(%rbp), %eax"); 7 asm("mov $0,%ebx"); 8 asm("mov %al,%bl"); 9 asm("mov %ebx,-0x8(%rbp)"); 10 printf("%08x\n",a); 11 } takk@deb9:~/tmp$ gcc t.c takk@deb9:~/tmp$ ./a.out 00000078 takk@deb9:~/tmp$
コピーして8bitシフトします。
takk@deb9:~/tmp$ cat -n t.c 1 #include <stdio.h> 2 int main() 3 { 4 unsigned long a; 5 asm("movq $0x12345678,-0x8(%rbp)"); 6 asm("mov -0x8(%rbp), %eax"); 7 asm("mov $0,%ebx"); 8 asm("mov %al,%bl"); 9 asm("shl $8,%ebx"); 10 asm("mov %ebx,-0x8(%rbp)"); 11 printf("%08x\n",a); 12 } takk@deb9:~/tmp$ gcc t.c takk@deb9:~/tmp$ ./a.out 00007800 takk@deb9:~/tmp$
これを繰り返します。
takk@deb9:~/tmp$ cat -n t.c 1 #include <stdio.h> 2 int main() 3 { 4 unsigned long a; 5 asm("movq $0x12345678,-0x8(%rbp)"); 6 asm("mov -0x8(%rbp), %eax"); 7 asm("mov $0,%ebx"); 8 9 asm("mov %al,%bl"); 10 asm("shl $8,%ebx"); 11 asm("shr $8,%eax"); 12 13 asm("mov %al,%bl"); 14 asm("shl $8,%ebx"); 15 asm("shr $8,%eax"); 16 17 asm("mov %ebx,-0x8(%rbp)"); 18 printf("%08x\n",a); 19 } takk@deb9:~/tmp$ gcc t.c takk@deb9:~/tmp$ ./a.out 00785600 takk@deb9:~/tmp$
8bitシフトを3回繰り返して、最後の最下位1Byteをコピーすれば、エンディアン変換完了です。
takk@deb9:~/tmp$ cat -n t.c 1 #include <stdio.h> 2 int main() 3 { 4 unsigned long a; 5 asm("movq $0x12345678,-0x8(%rbp)"); 6 asm("mov -0x8(%rbp), %eax"); 7 asm("mov $0,%ebx"); 8 9 asm("mov %al,%bl"); 10 asm("shl $8,%ebx"); 11 asm("shr $8,%eax"); 12 13 asm("mov %al,%bl"); 14 asm("shl $8,%ebx"); 15 asm("shr $8,%eax"); 16 17 asm("mov %al,%bl"); 18 asm("shl $8,%ebx"); 19 asm("shr $8,%eax"); 20 21 asm("mov %al,%bl"); 22 23 asm("mov %ebx,-0x8(%rbp)"); 24 printf("%08x\n",a); 25 } takk@deb9:~/tmp$ gcc t.c takk@deb9:~/tmp$ ./a.out 78563412 takk@deb9:~/tmp$
ポインタを使ってエンディアン変換すると、こんな感じでしょうか。
takk@deb9:~/tmp$ cat -n t.c 1 #include <stdio.h> 2 3 int main() 4 { 5 unsigned long a; 6 unsigned char *p; 7 unsigned char tmp[4]; 8 a = 0x12345678; 9 p = (unsigned char*)&a; 10 tmp[3] = *p++; 11 tmp[2] = *p++; 12 tmp[1] = *p++; 13 tmp[0] = *p++; 14 a = *(unsigned long*)tmp; 15 printf("%08x\n",a); 16 } takk@deb9:~/tmp$ gcc t.c takk@deb9:~/tmp$ ./a.out 78563412 takk@deb9:~/tmp$
アセンブラにすると、長いコードになります。ポインタによるエンディアン変換はとても非効率なようです。
00000000000006b0 <main>: 6b0: 55 push %rbp 6b1: 48 89 e5 mov %rsp,%rbp 6b4: 48 83 ec 20 sub $0x20,%rsp 6b8: 48 c7 45 f0 78 56 34 movq $0x12345678,-0x10(%rbp) 6bf: 12 6c0: 48 8d 45 f0 lea -0x10(%rbp),%rax 6c4: 48 89 45 f8 mov %rax,-0x8(%rbp) 6c8: 48 8b 45 f8 mov -0x8(%rbp),%rax 6cc: 48 8d 50 01 lea 0x1(%rax),%rdx 6d0: 48 89 55 f8 mov %rdx,-0x8(%rbp) 6d4: 0f b6 00 movzbl (%rax),%eax 6d7: 88 45 ef mov %al,-0x11(%rbp) 6da: 48 8b 45 f8 mov -0x8(%rbp),%rax 6de: 48 8d 50 01 lea 0x1(%rax),%rdx 6e2: 48 89 55 f8 mov %rdx,-0x8(%rbp) 6e6: 0f b6 00 movzbl (%rax),%eax 6e9: 88 45 ee mov %al,-0x12(%rbp) 6ec: 48 8b 45 f8 mov -0x8(%rbp),%rax 6f0: 48 8d 50 01 lea 0x1(%rax),%rdx 6f4: 48 89 55 f8 mov %rdx,-0x8(%rbp) 6f8: 0f b6 00 movzbl (%rax),%eax 6fb: 88 45 ed mov %al,-0x13(%rbp) 6fe: 48 8b 45 f8 mov -0x8(%rbp),%rax 702: 48 8d 50 01 lea 0x1(%rax),%rdx 706: 48 89 55 f8 mov %rdx,-0x8(%rbp) 70a: 0f b6 00 movzbl (%rax),%eax 70d: 88 45 ec mov %al,-0x14(%rbp) 710: 48 8d 45 ec lea -0x14(%rbp),%rax 714: 48 8b 00 mov (%rax),%rax 717: 48 89 45 f0 mov %rax,-0x10(%rbp) 71b: 48 8b 45 f0 mov -0x10(%rbp),%rax 71f: 48 89 c6 mov %rax,%rsi 722: 48 8d 3d 9b 00 00 00 lea 0x9b(%rip),%rdi # 7c4 <_IO_stdin_used+0x4> 729: b8 00 00 00 00 mov $0x0,%eax 72e: e8 2d fe ff ff callq 560 <printf@plt> 733: b8 00 00 00 00 mov $0x0,%eax 738: c9 leaveq 739: c3 retq 73a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
コメント