Byteorder
مقدمه¶
byte order یا endianness اشاره میکنه به ترتیبی که بایت های دیتا داخل کامپیوتر ذخیره و خونده میشن. وقتی که دارین به برنامه ورودی میدین یا هگزدامپ(نمایش دیتا در مبنای ۱۶) دیتایی رو میخونین نیاز دارین بدونین اون دیتا یا برنامه از چه byte order استفاده میکنه، وگرنه احتمالا اشتباه چیزی رو تفسیر میکنین و به هدفتون نمیرسین.
little endian¶
یعنی بایت کم ارزش تر داخل ادرس پایین تر و بایت پر ارزش تر داخل ادرس بالاتر ذخیره شه، این روش پر استفاده ترین داخل کامپیوتر هاست.
با چند مثال میبینیم که چطور دیتا رو به صورت little endian بخونیم یا بدیم به برنامه.
مثال ۱ - دیتا¶
0x7fffffffcc28: 0x27 0xeb 0xd5 0xf7
HIGH
--------
0x7fffffffcc2b | 0xf7 |
--------
0x7fffffffcc2a | 0xd5 |
--------
0x7fffffffcc29 | 0xeb |
--------
0x7fffffffcc28 | 0x27 |
--------
LOW
این عدد در واقع هست:
0xf7d5eb27
مثال ۲ - دیتا¶
0x7fffffffcc48: 0x1a 0x9c 0x55 0xba 0x55 0xec 0x0 0x0
0x7fffffffcc50: 0xfc 0xdc 0xff 0xaf 0xff 0x7f 0x0 0x0
اگه تک تک داده ها و ادرس هاشونو کنار هم بزاریم این شکلی میشه
HIGH
--------
0x7fffffffcc57 | 0x00 |
--------
0x7fffffffcc56 | 0x00 |
--------
0x7fffffffcc55 | 0x7f |
--------
0x7fffffffcc54 | 0xff |
--------
0x7fffffffcc53 | 0xaf |
--------
0x7fffffffcc52 | 0xff |
--------
0x7fffffffcc51 | 0xdc |
--------
0x7fffffffcc50 | 0xfc |
--------
0x7fffffffcc4f | 0x00 |
--------
0x7fffffffcc4e | 0x00 |
--------
0x7fffffffcc4d | 0xec |
--------
0x7fffffffcc4c | 0x55 |
--------
0x7fffffffcc4b | 0xba |
--------
0x7fffffffcc4a | 0x55 |
--------
0x7fffffffcc49 | 0x9c |
--------
0x7fffffffcc48 | 0x1a |
--------
LOW
که میشه این عدد
0x00007fff,afffdcfc,0000ec55,ba559c1a
,
هارو برای خوانایی بیشتر گذاشتم و میتونن در نظر گرفته نشن مثال ۳ - ورودی/خروجی برنامه¶
#include <stdio.h>
int main(){
int buff;
buff = 0;
scanf("%s", &buff);
printf("%p:%x\n", &buff, buff);
}
└─$ printf '\xba\xbe\xca\xec' | ./a.out
0x7ffce587f39c:eccabeba
چرا برعکس شد؟
چون بایت کم ارزش عدد سمت راست ترین بایتش هست، ولی وقتی داریم string رو میخونیم کم ارزش ترین بایتش سمت چپ ترینش هست، مثال زیر رو ببینین:
char str[] = "hello";
str[0]; // 'h'
int number = 0xbafc; //یک عدد رندوم
number & 0x00ff; // 0xfc
big endian¶
یعنی بایت پرارزش تر توی ادرس های پایین تر و بایت کم ارزش تر توی ادرس های بالاتر قرار بگیره. تعدادی از پردازنده ها از این روش استفاده میکنن ولی بیشترین کاربرد این روش برای پر کردن header های پیام های شبکه هستش. به صورت قراردادی تمام برنامه ها باید header های شبکه رو به صورت big endian پر کنن که ناهماهنگی به وجود نیاد.
مثال - ادرس IP¶
وقتی که برنامه میخواد به سیستم عامل بگه که ادرس ای پی مقصدش کجاست باید از big endian استفاده کنه که اون ادرس ایپی رو ذخیره کنه.
فرض کنیم که میخوایم به سیستم عامل بگیم میخوایم به ادرس 192.168.178.160
پیام بدیم. این ادرس ایپی رو اینطوری باید توی حافظه ذخیره کنیم:
0: c0 a8 b2 a0
توابع پر استفاده¶
htons¶
این تابع مخفف host to network short هست که میگه ورودی که از نوع short هست ( یک نوع داده داخل زبان c) رو از byteorder کامپیوتر (میتونه little endian یا big endian باشه) تبدیل میکنم به byte order شبکه (که یعنی big endian) این تابع و توابع شبیه اون بهمون کمک میکنن بدون توجه به byte order کامپیوتری که روش برنامه نویسی میکنیم برنامه نویسی کنیم و برنامه مون رو بتونیم روی کامپیوتر هایی که byte order متفاوت دارن کامپایل و اجرا کنیم.
از این تابع نسخه های دیگه هم وجود داره:
- ntohs: network to host short
- htonl: host to network long
- ntohl: network to host long
نویسنده