(1)汇编语言之寄存器,操作数寻址方式
写在前面:汇编语言格式有AT&T和Intel格式两种,GCC编译器采用AT&T格式,本系列文章中的所有汇编语言都采用此格式。
一、 什么是汇编语言
我们熟悉的C语言,Java,Python等语言都是高级语言,高级语言不能被处理器识别,程序运行时,需要将代码转成处理器能识别的机器码。机器码是一串十六进制的数字,如 55 5D 89 E5。由于人很难理解机器码表达的意思,因此需要用一些符号帮助理解指令。这种用符号代替机器指令操作码的低级语言称为汇编语言。机器码与汇编指令的关系如下图所示。 汇编语言由一条一条指令构成,指令有两部分组成,第一部分是操作码,用便于记忆的助记符表示,另一部分是操作数。一条指令可以有零个,一个或两个操作数。如“push %ebp” 只有一个操作数,这个指令的意思是将寄存器%ebp的值压入栈。如“mov %esp %ebp”有两个操作数,分别称为源操作数和目的操作数,这个指令的意思是将寄存器%esp的值传送给寄存器%ebp。
二、寄存器
程序编译后的指令代码存放在存储器中。CPU如何执行程序?简单的说,就是取指令,执行指令。CPU从存储器中取出一条指令,分析后执行相应的操作。如:x+y。GCC编译后产生三条指令,第一条指令告诉CPU从存储器中取出x的值,放在CPU的寄存器中,第二条指令告诉CPU从存储器中取出y的值,放在CPU的寄存器中,第三条指令告诉CPU将两个寄存器的值相加。
寄存器用来存储整数数据以及指针,一个IA32指令集架构的处理器包含一组8个32位的寄存器。
32 | 16 | 高8位 | 低8位 |
---|---|---|---|
%eax | %ax | %ah | %al |
%ecx | %cx | %ch | %cl |
%edx | %dx | %dh | %dl |
%ebx | %bx | %bh | %bl |
%esi | %si | ||
%edi | %di | ||
%esp | %sp | ||
%ebp | %bp |
32位处理器需要向后兼容16位处理器。表中%eax对应32位寄存器,%ax对应16位寄存器,%ax寄存器由%ah与%al组成,%ah与%al分别表示寄存器的高八位与低八位。
表中前6个寄存器是通用寄存器,可以存放数据和指针。%esp是栈指针寄存器,%ebp是帧指针寄存器。
三、操作数寻址方式
操作数分为三种:立即数(immediate),寄存器,存储器的引用。翻译一下,就是常数,寄存器中的值(用表示),存储器中的值(用表示)。而寻址的意思就是如何得到操作数表达的值。 举一个例子就可以明白上图中表达的意思。
假设存储器地址中的值如下所示:
地址 | 值 |
---|---|
0X100 | 0XFF |
0X104 | 0XAB |
0X108 | 0X13 |
0X10C | 0X11 |
寄存器中的值如下所示:
寄存器 | 值 |
---|---|
%eax | 0X100 |
%ecx | 0X1 |
%edx | 0X3 |
那操作数与值的对应关系如下表所示:
操作数 | 值 |
---|---|
%eax | 0X100 |
0X104 | 0XAB |
$0X108 | 0X108 |
(%eax) | 0XFF |
4(%eax) | 0XAB |
9(%eax,%edx) | 0X11 |
(%eax,%edx,4) | 0X11 |
0XFC(,%ecx,4) | 0XFF |
以9(%eax,%edx)为例,9(%eax,%edx)=M[9+%eax+%edx] = M[0X9+0X100+0X3]=M[0X10C],表示存储器0X10C地址的值,在第一张表上可以查到,地址0x10C上的值为0x11。