汇编指令带有后缀:
对于访问一个字节数据类型,后缀是b。
对于访问两个字节数据类型,后缀是w。
对于访问四个字节数据类型,后缀是l。
例如,对于mov指令,有movb, movw, movl。
movl $0x4050, %eax //把0x4050这个值装入到%eax寄存器中。
movw %bp, %sp //把%bp寄存器中保存的值装入到%sp寄存器中。
movb (%edi, %ecx), %ah //把ecx与edi中的值相加,这个值作为地址,找到这个地址指向的内存数据,取第一个字节存入ah寄存器中。
movb $-17 (%esp) //把-17这个数字保存到esp寄存器保存的地址对应的内存中。
movl %eax, -12(%ebp) //把eax寄存器保存的值装入ebp-12的地址指向的内存。
另外还有两类令movs和movz,这类指令用于把较小数据移入到较大数据。
movs是指高位用符号位填充,movz是指高位用0来填充。
push指令用于把数据压入到栈,pop指令用于把数据从栈中弹出。
pushl %ebp等价于以下两条指令:
subl $4, %esp
movl %ebp, (%esp)
popl %eax等价于以下两条指令:
movl (%esp), %eax
addl $4, $esp
示例:
int exchange(int *xp, int y)
{
int x = *xp;
*xp = y;
return x;
}
gcc -O1 -S -m32 exchange.c
exchange:
pushl %ebp //把旧的ebp值压入堆栈。
movl %esp, %ebp //把当前esp值保存在ebp中,作为新的ebp。
movl 8(%ebp), %edx//ebp+8指向的地址中的值装入edx,ebp+8是第一个入参:xp。
movl (%edx), %eax //把xp指向的值装入eax。
movl 12(%ebp), %ecx //把ebp+12指向的地址中的值装入ecx。是第二个入参:y。
movl %ecx, (%edx) //把y的值装入xp指针指向的地址对应的内存。
popl %ebp //弹出栈中的值到寄存器ebp,其实就是把刚才保存的旧的ebp值刷新回来。
ret //返回。