1.汇编语言应该掌握的一门语言,调试程序、理解计算机递增一些运行原理重要
2.仅介绍汇编指令,二进制机器指令是CPU才能理解的语言,因为是二进制格式,非常便于CPU解析和执行,但不利于人嘞阅读和交流,所以才有机器指令对应的汇编指令。二者区别如下
0x40054d : add %rdx,%rax // 汇编指令 (gdb) x/3xb 0x40054d 0x40054d : 0x48 0x01 0xd0 // 机器指令 同样是把rdx和rax寄存器中的值相加,汇编指令为:add %rdx,%rax,而机器指令却是三个数字:0x48 0x01 0xd0,显然,汇编指令对人类来说更加友好,它更加易记易读和易写。
汇编指令格式
操作码[操作数]
操作码:操作码指示CPU执行什么操作,比如是执行加法,减法还是读写内存。每条指令都必须要有操作码。
操作数:操作数是操作的对象,比如加法操作需要两个加数,这两个加数就是这条指令的操作数。操作数的个数一般是0个,1个或2个。源操作数、目的操作数
add %rdx,%rax
callq 0x400526 callq,表示调用函数 操作数是0x400526,它是被调用函数的地址。
retq 只有操作码retq,表示从被调用函数返回到调用函数继续执行。
格式说明:
1.AT&T格式的汇编指令中,寄存器名需要加%作为前缀,前面我们已经见过;
2.有2个操作数的指令中,第一个操作数是源操作数,第二个是目的操作数,刚才也讨论过,不过那条指令中的源和目的不是那么清晰,来看一个直白的,mov %eax,%esi,这条指令表示把eax寄存器中的值拷贝给esi,这条指令中源和目的就很清楚了;
3.立即操作数需要加上$符号做前缀,如 "mov $0x1 %rdi" 这条指令中第一个操作数不是寄存器,也不是内存地址,而是直接写在指令中的一个常数,这种操作数叫做立即操作数。这条指令表示把数值0x1放入rdi寄存器中。
4.寄存器间接寻址的格式为 offset(%register),如果offset为0,则可以略去偏移不写直接写成(%register)。何为间接寻址呢?其实就是指指令中的寄存器并不是真正的源操作数或目的操作数,寄存器的值是一个内存地址,这个地址对应的内存才是真正的源或目的操作数,比如 mov %rax, (%rsp)这条指令,第二个操作数(%rsp)中的寄存器的名字用括号括起来了,表示间接寻址,rsp的值是一个内存地址,这条指令的真实意图是把rax寄存器中的值赋值给rsp寄存器的值(内存地址)对应的内存,rsp寄存器本身的值不会被修改,作为比较,我们看一下 mov %rax, %rsp 这条指令 ,这里第二个操作数仅仅少了个括号,变成了直接寻址,意思完全不一样了,这条指令的意思是把rax的值赋给rsp,这样rsp寄存器的值被修改为跟rax寄存器一样的值了。下面的2张图展示了这两种寻址方式的不同: