我正在学习“计算机系统:程序员视角”一书。我在理解问题3.5时遇到了一些麻烦:
您将获得以下信息。具有原型的函数
void decode1(int *xp, int *yp, int *zp);
被编译成汇编代码。代码正文如下:
xp at%ebp + 8,yp at%ebp + 12,zp at%ebp + 16
1 movl 8(%ebp), %edi
2 movl 12(%ebp), %edx
3 movl 16(%ebp), %ecx
4 movl (%edx), %ebx
5 movl (%ecx), %esi
6 movl (%edi), %eax
7 movl %eax, (%edx)
8 movl %ebx, (%ecx)
9 movl %esi, (%edi)
参数xp,yp和zp存储在具有偏移的存储器位置 8,12和16分别相对于寄存器%ebp中的地址。 为decode1编写C代码,其效果等同于 上面的汇编代码。
我提出了以下c函数:
void decode1(int *xp, int *yp, int *zp) {
int *a = yp;
int *b = zp;
int *c = xp;
yp = c;
zp = a;
xp = b;
}
编译到程序集(flags:-w32 -O0 -S)我得到以下汇编代码:
decode1(int*, int*, int*):
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl 12(%ebp), %eax
movl %eax, -12(%ebp) // ??
movl 16(%ebp), %eax
movl %eax, -8(%ebp) // ??
movl 8(%ebp), %eax
movl %eax, -4(%ebp) // ??
movl -4(%ebp), %eax
movl %eax, 12(%ebp)
movl -12(%ebp), %eax
movl %eax, 16(%ebp)
movl -8(%ebp), %eax
movl %eax, 8(%ebp)
nop
leave
ret
我有两个问题:
我的C代码是否正确?如果是,为什么汇编代码的差异?我不明白为什么代码似乎将变量存回内存然后加载回来?为什么它只使用%eax?我有6个变量,所以它应该能够在6个寄存器中加载它们,没有?
编辑:生成的代码使用-O2而不是-O0
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl 16(%ebp), %eax
movl 12(%ebp), %ecx
movl 8(%ebp), %edx
movl %edx, -4(%ebp)
movl %ecx, -8(%ebp)
movl %eax, -12(%ebp)
movl -8(%ebp), %eax
movl %eax, -16(%ebp)
movl -12(%ebp), %eax
movl %eax, -20(%ebp)
movl -4(%ebp), %eax
movl %eax, -24(%ebp)
movl -24(%ebp), %eax
movl %eax, -8(%ebp)
movl -16(%ebp), %eax
movl %eax, -12(%ebp)
movl -20(%ebp), %eax
movl %eax, -4(%ebp)
addl $24, %esp
popl %ebp
retl
EDIT2:正确答案实际上是:
void decode1(int *xp, int *yp, int *zp) {
int a = *yp;
int b = *zp;
int c = *xp;
*yp = c;
*zp = a;
*xp = b;
}