汇编语言赋予程序员更强的操作硬件的能力,同时对程序员理解计算机硬件结构的能力要求也就相对来说比较高,重点是对CPU如何操作寄存器,CPU如何进行寻址,计算机中寄存中的结构(本文不包括浮点计算)。
IA32架构的CPU中一共有八个寄存器,%eax,%ebx,%ecx,%edx,%esi,%edi,%esp,%ebp,除了%esp与%ebp有特殊的用途外,其他的都可以随意使用,PS:%eax一般用做函数返回值的存储了。
IA32架构下这些寄存器都是32byte的,所以有些寄存器存在高低字节之分,比如%al,%ah,如果去掉e,那就是16byte的寄存器,不过很少这么用了。
为了很好理解汇编指令,首先要了解一下计算机的寻址方式:
1.立即数,用$0x108,意思是指这个数据,CPU可以直接使用,不通过任务寄存器与存储器
2.寄存器,用Ea来表示任意寄存器a,用引用来表示它的值,然后他所存储的数据是R[Ea]
3.存储器,一般格式是Imm(Eb,Ei,s),Imm是一个立即数偏移,一个基址寄存器,一个索引寄存器,一个索引变量因素组成的寻址方式,所以用字母的形式是M[R[Eb]+R[Ei]*s+Imm]
这三种就是计算机的基本寻址方式了,当然存储器可以细分,但在这里没有这个必要,大概了解下概念即可。它们分别对应的汇编表达式是如下:
1.就这样了,$0x108
2.也就这样了,%eax,(这里面用%eax代表任意寄存器了)
3.9(%eax,%edx,5),也就是指到%eax+%edx*5+9的内存地址上找数据了
通过上面的数讲解,开始接触汇编指令
1.数据传输指令
| 指令 | 效果 | 描述 |
| movl S , D | D <- S | 传送双字 |
| movw S , D | D <- S | 传送字 |
| movb S , D | D <- S | 传送字节 |
| movsbl S , D | D <- 符号扩展(S) | 传送字符扩展字节 |
| movzbl S , D | D <-零扩展(S) | 传送零扩展字节 |
| pushl S |
R[%esp]<-R[%esp]-4 M[R[%esp]] <-S |
压栈 |
| popl |
S <-M[R[%esp]] R[%esp] <-R[%esp]+4 |
出栈 |
其中movsbl与movzbl只是操作低位字节,然后把高位24填充数据,movzbl是以0填充24位,movsbl是以低位字节高位数据进行填充(0或1)
|
示例 movb %dh %al; movsbl %dh, %eabx #FFFFFFFFF8D movzbl %dh,%edx #000000008D |
从表格中我们可以很清楚的看到push1与pop1只对寄存器%esp进行操作,这是为什么呢?因为这是栈的特殊用途寄存器,push1与pop1就是对栈进行操作的,通过栈的先进先出特性但程序栈中栈顶又是往内存的低位增长所以造成了push1是R[%esp]-4.
对C语言来个示例分析吧(假设x=8(%esp),*y=12(%sp):
int test(int x,int *y) {
int t=x + *y ; #1. movl 8(%esp),%eax; 2. mov 12(%esp),%edx; addl (%edx),%eax;
return t;
}
下一篇文章介绍(算术和逻辑操作,控制操作,过程指令,C语言中嵌入汇编)

