程序的及机器级表示-访问信息
3.4
一个IA32中中央处理器包含一组8个存储32位值的寄存器。
31--------------15------8,7------0%eax %ax %ah %al
%ecx %cx %ch %cl
%edx %dx %dh %dl
%ebx %bx %bh %bl
%esi %si
%edi %di
%esp %sp
%ebp %bp
3.4.1 操作数指示符
大多数指令有一个或多个操作数,不同的操作数分为三种类型:
-
立即数(immediate): 在AT&T格式汇编代码中,立即数书写是$后面跟一个整数,如:$-577或者$0x1F;
-
寄存器(register):它表示某个寄存器的内容,对于双字来说,可以是8个32位寄存器中的一个(如:%eax),对于字操作来说可以是8个16位寄存器中的一个(如:%ax) 对于字节操作来说,可以是8个单字节寄存器元素中的一个(如:%al);
-
存储器(memory)引用: 它会 根据计算出来的地址(通常成为有效地址),访问某个存储器位置。
3.4.2 数据传送指令
指令 | 效果 | 描述 |
---|---|---|
MOV S,D | D <-S | 传送 |
movb | 传送字节 | |
movw | 传送字 | |
movl | 传送双字 | |
MOVS S,D | D<-符号拓展(S) | 传送符号拓展到字节 |
movsbw | 将做了符号拓展到额字节传送到字 | |
movsbl | 将做了符号拓展到额字节传送到双字 | |
movswl | 将做了符号拓展到额字传送到双字 | |
MOVZ S,D | D<-零拓展(S) | 传送零拓展的字节 |
movzbw | 将做了零拓展的字节传送到字 | |
movzbl | 将做了零拓展的字节传送到双字 | |
movzbl | 将做了零拓展的字传送到双字 | |
pushl S | R[%esp]<-R[%esp]-4; M[R[%esp]] <-S (栈开口向下,从高地址向地址拓展) | 将双字压栈 |
popl D | D<-M[R[%esp]]; R[%esp]<-R[%esp]+4 | 将双字出栈栈 |
栈: 栈可以实现位一个数组,总是从数组的一端插入和删除元素,这一端成为栈顶。在IA32中,程序栈存放在存储器中某个区域, 栈向下增长,这样一来,栈顶元素的地址是所有栈中元素地址最低的。
3.4.3 数据传送示例
// C代码
int exchange(int *xp, int y){
int x = *xp;
*xp = y;
return x;
}
// 汇编代码
exchange:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
call __x86.get_pc_thunk.ax
addl $_GLOBAL_OFFSET_TABLE_, %eax
movl 8(%ebp), %eax
movl (%eax), %eax
movl %eax, -4(%ebp)
movl 8(%ebp), %eax
movl 12(%ebp), %edx
movl %edx, (%eax)
movl -4(%ebp), %eax
leave
ret