X86 汇编存在两种不同的语法:inter语法和AT&T语法,在windows平台上通常使用的是inter语法,二在UNIX/linux平台的汇编器使用的则一直是AT&T语法。
与inter语法相比,AT&T语法的特点有:
(1) 、寄存器前面用前缀% 来标识;
(2) 、指令中源操作数在前目的操作数在后;(与inter语法刚好相反)
(3) 、操作数的长度通过在指令字符后添加后缀来却定,b 表示 8位,w 表示16位,l 表示32位。例如:movl %esp %ebp, 表示将寄存器esp 中的值复制到 寄存 器ebp中。
(4) 、立即数用“$”来标识,例如:addl $5 %eax 表示将寄存器eax 中的值加5;
(5) 、变量前面加'$"表示不同的意义,例如:movl $g %eax 表示把 g 的地址存到eax中, 而 movl g %eax 表示把变量g 的值存到eax中 (类似于函数参数传递 中的引用传递与值传递的区别)
1、从main函数开始执行,假设进入main函数之前,堆栈的栈底指针ebp指向2000,栈顶指针esp指向2000
2、假设函数f 的入口地址为:0x1234,指令指针ip指向0x3456
3、ip指针指向了飞函数的入口地址后开始运行函数
4、接下来将跳转到函数g,假设函数g 的入口地址为:0x2234,此时指令指针指向:0x1248
此时指令指针指向了0x1248,也就是回到调用函数g之前的那条指令的下一条指令(f函数中)
5、计算机又回到了函数 f 中:
此时指令指针指向了0x3456,也就是回到调用函数 f 之前的那条指令的下一条指令(main函数中)
6、计算机又回到了main函数中:
因为eax 之前的值为13,所,现在eax=13+9=22
此时经过ret 指令后,计算机退出了main 函数,进程结束。
通过以上的操作,完成了简单的从C语言到汇编语言,在模拟计算机执行汇编指令的全过程,编写的程序虽然很简单但很有代表性,包含了函数调用与参数传递,以及在程序运行中的堆栈变化,以及参数值在各个寄存器之间的传递与运算。
汇编语言不可否认要比C语言复杂、难写、难读,但是经过这样一个过程后,对汇编程序没有之前那么抵触。汇编与C语言在本质上也都一样,只是表达的形式不同。C语言中运用的是不同的变量来”存储“和传递参数,而汇编语言则是使用堆栈、寄存器来“保存”和传递参数,最终都是由运算器计算,C语言中的变量可以随意定义,但是汇编中堆栈空间和寄存器数量都有限,就像汉诺塔游戏中,给你无限多根柱子问题很容易就能解决,但是只给三根柱子问题就变得很繁琐。程序的最终目的不是解决问题,而应该是高效率的解决问题。所以一个写一个好的C语言程序只是第一步,还要有好的编译器等工具,为C程序最终要变成2进制代码交给计算机执行。