codecamp

Assembly Big和Little Endian表示法

在前面的章节本教程介绍了多字节数据的big和little endian表示法的概念。这一节将详细介绍这一主题。读者可能会回忆起endian表示法指的是一个多字节数据的单个字节元素储存在内存中的顺序。Big endian是最直接的方法。它首先储存的是最高有效字节,然后是第二个有效字节,以些类推。换句话说就是,大的位被首先储存。Little endian以一个相反的顺序来储存字节(最小的有效字节最先被储存)。x86家族的处理器使用的就是little endian表示法。


看一个例子:考虑双字的表示。如果是big endian表示法,这些字节将像这样储存:12 34 56 78。如果是little endian表示法,这些字节就像这样储存:78 56 34 12。


现在读者可能会这样问自己:一个理智的芯片设计者怎么会使用little endian表示法?在Intel公司里的工程师是不是虐待狂?因为他们使广大的程序员承受了这种混乱的表示法。像这样,CPU看起来会因为在内存中向后储存字节而做额外的工作(而且从内存中读出时又要颠倒它们)。答案是CPU使用little endian格式读写内存是不需要做额外的工作的。你必须认识到CPU是由许多电子电路组成,简单地工作在位值上。位(和字节)在CPU中不需要有任何的顺序的。


考虑2个字节的寄存器AX。这可以分解成单个字节的寄存器:AH和AL。在CPU中的电路保留了AH 和AL的值。在一个CPU中,电路是没有任何顺序的。也就是说,储存AH的电路可以在储存AL的电路前面或后面。mov指令复
制AX的值到内存中,首先复制AL的值,接着是AH。CPU做这件事一点也没有比先储存AH难。


同样的讨论还可以用到一个字节的单个比特位上。它们在CPU电路(或就此而言,内存)里并不真的有一定顺序。但是,因为在CPU或内存中单个的比特位并没有编址,所以没有办法知道(或关心)CPU在内部对它们是如

何排序的。


在图3.4中的C代码展示了如何确定CPU的Endian格式。p指针把word变量当作两个元素的字符数组来看待。因此,word在内存里的第一个字节赋值给了p[0],而这取决于CPU的Endian格式。


确定Ending


什么时候需要在乎Little和Big Endian

对于典型的编程,CPU的Endian格式并不是很重要。它很重要的大多数时刻是在不同的计算机系统间传输二进制数据时。此时使用的要么是某种类型的物理数据媒介(例如一块硬盘)要么是网络。因为ASCII数据是单个字节的,Endian格式对它来说是没有问题的。

所有的内部的TCP/IP消息头都以big endian的格式来储存整形。(称为网络字节续). TCP/IP 库提供了可移植处理Endian格式问题的方法的C函数。例如:htonl () 函数把一个双字(或长整形)从主机格式转换成了网络格式。ntohl ()函数执行一个相反的交换。对于一个big endian系统,这两个函数仅仅是无修改地返回它们的输入。这就允许你写出的网络程序可以在任何的Endian格式系统上成功编译和运行。

invert endian Function

图3.5展示了一个转换双字Endian格式的C函数。486处理器提供了一个名为BSWAP的新的指令来交换任意32位寄存器中的字节。例如:

bswap      edx              ; 交换edx中的字节

这条指令不可以使用在16位的寄存器上。但是XCHG 指令可以用来交换可以分解成8位寄存器的16寄存器中的字节。例如:

xchg        ah,al             ; 交换ax中的字节

Assembly C中的按位运算
Assembly 计算位数的3种方法
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }