我最初得到的是功能原型:
void decode1(int *xp, int *yp, int *zp)现在,我被告知将以下程序集转换为C代码:
movl 8(%ebp), %edi //line 1 ;; gets xp
movl 12(%ebp), %edx //line 2 ;; gets yp
movl 16(%ebp),%ecx //line 3 ;; gets zp
movl (%edx), %ebx //line 4 ;; gets y
movl (%ecx), %esi //line 5 ;; gets z
movl (%edi), %eax //line 6 ;; gets x
movl %eax, (%edx) //line 7 ;; stores x into yp
movl %ebx, (%ecx) //line 8 ;; stores y into zp
movl %esi, (%edi) //line 9 ;; stores z into xp这些评论并没有在问题上给我,这是我相信他们正在做的,但我不能百分之百肯定。
我的问题是,对于第4-6行,我是否可以假设
movl (%edx), %ebx
movl (%ecx), %esi
movl (%edi), %eax只为y,z,x创建一个局部变量?
另外,每个变量存储在(edi、edx、ecx)中的寄存器是重要的还是我可以以任何顺序使用任何寄存器来从堆栈中删除指针?
C代码:
int tx = *xp;
int ty = *yp;
int tz = *zp;
*yp = tx;
*zp = ty;
*xp = tz;如果没有给我函数原型,我如何知道使用了哪种类型的返回类型?
发布于 2015-11-12 18:48:00
让我们集中讨论一组更简单的指令。
第一:
movl 8(%ebp), %edi将位于内存上的4个字节的内容加载到EDI寄存器中,比EBP寄存器中设置的地址高出8个字节。这种特殊的EBP用法是编译器代码生成器遵循的约定,即每个函数将堆栈指针ESP保存到EBP寄存器中,然后为函数局部变量创建堆栈帧。
现在,在EDI寄存器中,我们有传递给函数的第一个参数,即指向整数的指针,因此EDI现在包含该整数的地址,而不是整数本身。
movl (%edi), %eax将获得EDI寄存器所指向的4个字节,并将它们加载到EAX寄存器中。
现在,在EAX中,我们有第一个参数中由xp指向的整数的值。
然后:
movl %eax, (%edx)将此整数值保存到EDX寄存器内容所指向的内存中,该寄存器是从传递给函数的第二个参数EBP+12加载的。
那么,您的第一个问题是,这个程序集代码是否与此等效?
int tx = *xp;
int ty = *yp;
int tz = *zp;
*yp = tx;
*zp = ty;
*xp = tz;is,yes,但请注意,没有创建tx,ty,tz局部变量,而是只创建处理器寄存器。
第二个问题是no,您不能知道返回的类型,同样,您不能通过查看生成的程序集代码来推断寄存器使用的约定。
发布于 2015-11-12 18:32:54
恭喜你,你做得对:)
您可以使用任何寄存器,但有些需要保存,即它们应该在使用之前保存,然后再恢复。在典型的调用约定中,您可以使用eax、ecx和edx,其余的都需要保留。您展示的程序集不包括用于执行此操作的代码,但它可能就在其中。
至于返回类型,很难推断。简单类型将在eax寄存器中返回,并且始终存在一些内容。我们无法判断这是作为一个返回值,还是只剩下一个局部变量。也就是说,如果您的函数有return tx;,那么它可能是相同的程序集代码。另外,我们也不知道eax的类型,它可能是任何合适的东西,并且根据调用约定预期会返回到那里。
https://stackoverflow.com/questions/33678188
复制相似问题