第二代语言也叫做汇编语言,它介于第一代语言(机器语言也是二进制语言)和第三代语言(接近于自然语言拥有关键字和结构,例如C,Java等)之间。汇编语言由用助记符(Mnemonics)和地址符号(Symbol)或标号(Label)组成。助记符用来代替机器指令的操作码,地址符号或标号表示指令或操作数的地址。汇编的语法结构由:操作码 + 操作数 (也存在只有操作码没有操作数的指令)组成,例如:
mov ebp,esp
ret
第一行中,mov表示助记符也是操作码,ebp,esp;表示操作数。整段代码的意思是将esp寄存器的值存入ebp寄存器。第二行中,只有ret一个操作码,没有操作数,表示将处理返回到函数的调用源。
汇编语言源代码主要采用两种语法:AT&T语法和Intel语法。我们大部分接触的是Intel语法。
其中AT&T汇编语言以%作为所有寄存器名称的前缀,以$作为文字常量或立即操作数的前缀。它的语法结构中,源操作数位于左边,目的操作数位于右边,举个例子:add $0x4, %eax 该指令表示EAX寄存器加4。使用AT&T语法的有GNU汇编器和许多其他GNU工具(如gcc和gdb)。
Intel语法是我们接触比较多的语法,上述指令如果用Intel语法则是:add eax, 0x4。使用Intel语法的汇编器包括微软汇编器、Borland的Turbo汇编器和Netwide汇编器。
这里介绍CPU大小端模式是因为汇编语言的操作数中往往存在各种各样的数据或地址。如果不了解数组的存储方式,将难以读懂汇编代码。
计算机存储的最小单位是字节byte,一个字节等于8 bit。汇编指令一次最小处理8位,也就是一个字节。ASCII码表,每个字符都是一个字节,没有低于8位的字符。那么就产生了一个问题,假如该数据大于一个字节,该如何存储呢?
例如在一些高级语言中除了8 bit 的 char 型之外,还有16 bit 的 short 型,32 bit 的 int 型。另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。
大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。与我们的阅读习惯相同。
小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。与我们的阅读习惯相反。
例如有一个32位的数据 0x12345678,按照不同的模式从低地址到高地址进行存储。如下表所示:
地址 | 大端模式 | 小端模式 |
---|---|---|
0x00000001 | 0x12 | 0x78 |
0x00000002 | 0x34 | 0x56 |
0x00000003 | 0x56 | 0x34 |
0x00000004 | 0x78 | 0x12 |