Imitate/emulate a big-endian behavior in C? [duplicate]
I was wondering if it's possible to emulate a big-endian behavior, for testing purpose?
via either windows or linux , mingw or gcc. Here's a sample of code which I would like the emulation to return big endian:
#include <stdio.h>
#include <stdlib.h>
#include <string.开发者_运维问答h>
#include <limits.h>
#if CHAR_BIT != 8
#error "Unsupported char size for detecting endianness"
#endif
int main (void)
{
short int word = 0x0001;
char *byte = (char *) &word;
if (byte[0]) printf("little endian");
else printf("big endian");
return 0;
}
You can't switch endianes for testing purposes or anything like that. What you can do is, to install an emulator for a big-endian architecture and compile your program for the emulator. Here's one way, under:
http://people.debian.org/~aurel32/qemu/
are Debian disk images for all kinds of QEMU supported architectures. mips, sparc and arm are big-endian (do not download anything ending with -el). I'm using Debian Lenny for MIPS ( http://people.debian.org/~aurel32/qemu/mips/ ). Install QEMU for your platform, then follow the instructions on the MIPS-page to download a image and kernel file.
Now you can boot into a Debian 5 for MIPS right from your console. Login to you virtual machine, become super user (the password is "root") and install the C-compiler:
debian-mips:~# su -
debian-mips:~# apt-get update
debian-mips:~# apt-get install gcc
fire up an editor and enter your program:
debian-mips:~# pico foo.c
debian-mips:~# gcc foo.c
debian-mips:~# ./a.out
big endian
UPDATE (2021-07-27) Just want to add, for anyone reading this 11 years later, that using the multiarch privileged container in docker is an easier and faster way to get a testing setup. Getting a s390x (big endian) running is as easy as:
$ docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
$ docker run --rm -it s390x/ubuntu bash
Also, this works unter Docker Desktop for Windows.
See https://github.com/multiarch/qemu-user-static for more infos.
I wanted big-endian emulation on my little-endian Intel machine to test a program for byte order related issues. QEMU PowerPC emulator seemed like a good solution. I have documented the steps to set it up below.
1) Installed QEMU.
nifty:~# aptitude update && aptitude install qemu
2) Downloaded Mac-on-Linux from http://sourceforge.net/projects/mac-on-linux/files/ and copied the 'video.x' file in the download to '/usr/share/qemu'. This was necessary to prevent qemu-system-ppc from complaining about it.
nifty:~# tar -xjf mol-0.9.72.1.tar.bz2
nifty:~# cp mol-0.9.72.1/mollib/drivers/video.x /usr/share/qemu
3) Downloaded Debian for PowerPC and installed it on a QEMU hard disk image.
susam@nifty:~/qemu$ wget --no-verbose http://cdimage.debian.org/debian-cd/5.0.4/powerpc/iso-cd/debian-504-powerpc-CD-1.iso
2010-06-19 02:55:06 URL:http://caesar.acc.umu.se/debian-cd/5.0.4/powerpc/iso-cd/debian-504-powerpc-CD-1.iso[675569664/675569664] -> "debian-504-powerpc-CD-1.iso" [1]
susam@nifty:~/qemu$ qemu-img create powerpc.img 2G
Formatting 'powerpc.img', fmt=raw size=2147483648
susam@nifty:~/qemu$ qemu-system-ppc -hda powerpc.img -cdrom debian-504-powerpc-CD-1.iso -boot d -m 512
4) Booted the QEMU PowerPC emulator with the hard disk image.
susam@nifty:~/qemu$ qemu-system-ppc -hda powerpc.img -m 512
5) Verified that I was really on a big endian system by writing a simple C program.
susam@lilliput:~$ cat endian.c
#include <stdio.h>
int main()
{
int n = 0x1;
printf(*((char *) &n) ? "little-endian\n" : "big-endian\n");
return 0;
}
susam@lilliput:~$ gcc endian.c && ./a.out
big-endian
susam@lilliput:~$
In case you missed the pun, Lilliputians were originally big-endians.
You can throw a bunch of hton* (Host TO Network) and ntoh* (Network TO Host) calls in there between all of your different uses. Network endian is Big Endian.
16 bit: htons = Host TO Network Short ntohs = Network TO Host Short
32 bit: htonl = Host TO Network Long ntohl = Network to Host Long
Really both host to network and network to host are the same because the same swapping happens either way.
They are generally implemented as macros and will be no-ops on platforms that use big endian.
They live in:
#include <arpa/inet.h>
Which is generally available.
You could also make use of <endian.h>
if your libraries have it. With gcc this requires -D_BSD_SOURCE
On Unix, BSD, and Linux try: man htons man endian man byteorder
If you really want to do this then you can use an Intel Mac and build for both x86 and ppc. The ppc executable will run via Rosetta emulation and will be big endian, whereas the native x86 build will of course be little endian.
Why would you want to detect the endianness of your platform at run-time? When you go to compile, the endian mode is known. Your code will do what you expect it to... assuming that a short int is 2 bytes on the target platform. To avoid this hangup, you'd be better off looking at the last byte. (byte[sizeof(short int) - 1])
精彩评论