汇编如何进行参数传递:按值,引用,不同类型/数组的指针?

带围巾

为了查看这一点,我编写了这个简单的代码,在其中我创建了不同类型的变量,并将它们按值,按引用和按指针传递给函数:

int i = 1;
char c = 'a';
int* p = &i;
float f = 1.1;
TestClass tc; // has 2 private data members: int i = 1 and int j = 2

函数主体留为空白,因为我只是在看如何传递参数。

passByValue(i, c, p, f, tc); 
passByReference(i, c, p, f, tc); 
passByPointer(&i, &c, &p, &f, &tc);

想要了解这对于数组有何不同,以及如何访问参数。

int numbers[] = {1, 2, 3};
passArray(numbers); 

部件:

passByValue(i, c, p, f, tc)

mov EAX, DWORD PTR [EBP - 16]
    mov DL, BYTE PTR [EBP - 17]
    mov ECX, DWORD PTR [EBP - 24]
    movss   XMM0, DWORD PTR [EBP - 28]
    mov ESI, DWORD PTR [EBP - 40]
    mov DWORD PTR [EBP - 48], ESI
    mov ESI, DWORD PTR [EBP - 36]
    mov DWORD PTR [EBP - 44], ESI
    lea ESI, DWORD PTR [EBP - 48]
    mov DWORD PTR [ESP], EAX
    movsx   EAX, DL
    mov DWORD PTR [ESP + 4], EAX
    mov DWORD PTR [ESP + 8], ECX
    movss   DWORD PTR [ESP + 12], XMM0
    mov EAX, DWORD PTR [ESI]
    mov DWORD PTR [ESP + 16], EAX
    mov EAX, DWORD PTR [ESI + 4]
    mov DWORD PTR [ESP + 20], EAX
    call    _Z11passByValueicPif9TestClass


passByReference(i, c, p, f, tc)

    lea EAX, DWORD PTR [EBP - 16]
    lea ECX, DWORD PTR [EBP - 17]
    lea ESI, DWORD PTR [EBP - 24]
    lea EDI, DWORD PTR [EBP - 28]
    lea EBX, DWORD PTR [EBP - 40]
    mov DWORD PTR [ESP], EAX
    mov DWORD PTR [ESP + 4], ECX
    mov DWORD PTR [ESP + 8], ESI
    mov DWORD PTR [ESP + 12], EDI
    mov DWORD PTR [ESP + 16], EBX
    call    _Z15passByReferenceRiRcRPiRfR9TestClass

passByPointer(&i, &c, &p, &f, &tc)

    lea EAX, DWORD PTR [EBP - 16]
    lea ECX, DWORD PTR [EBP - 17]
    lea ESI, DWORD PTR [EBP - 24]
    lea EDI, DWORD PTR [EBP - 28]
    lea EBX, DWORD PTR [EBP - 40]
    mov DWORD PTR [ESP], EAX
    mov DWORD PTR [ESP + 4], ECX
    mov DWORD PTR [ESP + 8], ESI
    mov DWORD PTR [ESP + 12], EDI
    mov DWORD PTR [ESP + 16], EBX
    call    _Z13passByPointerPiPcPS_PfP9TestClass

passArray(numbers)

    mov EAX, .L_ZZ4mainE7numbers
    mov DWORD PTR [EBP - 60], EAX
    mov EAX, .L_ZZ4mainE7numbers+4
    mov DWORD PTR [EBP - 56], EAX
    mov EAX, .L_ZZ4mainE7numbers+8
    mov DWORD PTR [EBP - 52], EAX
    lea EAX, DWORD PTR [EBP - 60]
    mov DWORD PTR [ESP], EAX
    call    _Z9passArrayPi

    // parameter access
    push    EAX
    mov EAX, DWORD PTR [ESP + 8]
    mov DWORD PTR [ESP], EAX
    pop EAX

我假设我正在寻找与参数传递有关的正确程序集,因为每个函数的末尾都有调用!

但是由于我对汇编的了解非常有限,所以我不知道这是怎么回事。我了解了ccall约定,所以我假设正在进行的事情与保留调用方保存的寄存器,然后将参数压入堆栈有关。因此,我期望看到的东西都被加载到寄存器中并“推”到任何地方,但是不知道movs和leas发生了什么。另外,我也不知道是什么DWORD PTR

我只了解了registerseax, ebx, ecx, edx, esi, edi, espebp,所以看到类似XMM0DL仅仅是让我感到困惑的东西我想知道lea何时通过引用/指针传递是有意义的,因为它们使用内存地址,但是我实际上无法确定发生了什么。当涉及到按值传递时,似乎有很多指令,因此这可能与将值复制到寄存器有关。不知道何时将数组作为参数传递和访问。

如果有人可以向我解释有关每个组装块发生了什么的一般想法,我将不胜感激。

伊戈尔·波波夫(Igor Popov)

使用CPU寄存器传递参数比使用内存(即堆栈)要快。但是,CPU中的寄存器数量有限(尤其是在x86兼容的CPU中),因此,当函数具有许多参数时,将使用堆栈代替CPU寄存器。在您的情况下,有5个函数参数,因此编译器将堆栈用作参数而不是寄存器。

原则上,编译器可以使用push指令将参数推入堆栈,然后再执行实际call操作,但是许多编译器(包括gnu c ++)都使用指令将参数mov推入堆栈。这种方法很方便,因为它不会在调用函数的代码部分中更改ESP寄存器(堆栈的顶部)。

如果passByValue(i, c, p, f, tc)参数值放在堆栈中。您可以看到mov从存储器位置到寄存器以及从寄存器到堆栈的适当位置的许多指令。原因是x86程序集禁止直接从一个内存位置移动到另一个内存位置(例外是movs将值从一个数组(或所需的字符串)移动到另一个)。

如果passByReference(i, c, p, f, tc)您看到许多5条lea指令,它们会将自变量的地址复制到CPU寄存器,并且这些寄存器的值将移入堆栈。

的情况passByPointer(&i, &c, &p, &f, &tc)类似于passByValue(i, c, p, f, tc)在内部,在汇编级别,按引用传递使用指针,而在较高的C ++级别,程序员不需要在引用上显式使用&and*运算符。

将参数移至堆栈后call,将发出指令,这会将指令指针压EIP入堆栈,然后再将程序执行转移到子例程。指令之后,moves堆栈中的所有参数都将用于EIP堆栈call

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

通过不同类型的引用传递参数时如何打字

我可以使用lambda指针数组来保存具有不同类型的参数/返回值的函数吗?

如何进行if或汇编?

如何将不同类型的list <T>传递到按相似字段进行分组的方法中

在Spark / Scala中将不同类型的值作为参数传递给单个函数

如何正确解组不同类型的数组?

如何返回不同类型的数组?

C ++将“结构”类型的参数作为引用(&)传递或按值传递

如何在SQL Server中按不同类型的分数对ID进行分组

C按值传递数组vs按引用传递数组

不同类型的数组

如何在C#中将2种不同类型传递给函数参数?

如何在C中传递N个不同类型的参数

C ++不同类型的指针

如何将多个不同类型的数组列表传递给单个 recyclerview 适配器

将不同类型的参数传递给函数

将不同类型的参数传递给jdbctemplate查询

将不同类型的参数传递给功能模板

传递两个不同类型的参数

按升序打印多个不同类型的数组

如何不使用参数在不同类的方法之间传递值

SystemVerilog数组是按值或引用传递的吗?

如何在scala中为不同类型的参数组合相同的函数

将不同类型的 Action<T> 数组传递给方法

如何从JSON对象数组中检索不同类型的数据并进行处理?

如何在C中对每列都是不同类型的二维数组进行排序?

当对象可以具有不同类型时如何按键对对象数组进行分组

如何创建参数化函数来检查不同类型的值

如何在汇编函数中将元素数组作为参数传递时转发ARM寄存器的地址指针