将寄存器保存到汇编中的指针参数

时间:2016-05-30 02:17:18

标签: pointers assembly

所以我无法如何保存寄存器我将函数的值保存到指针中。该函数是无效的,所以我需要将值保存到参数中,但我不知道如何。

这就是我得到的

void factorial (unsigned int input, unsigned int *output)// caller
{

// C code to be converted to x86 assembly
/*
    *output = recFactorial (input);
*/

    __asm{
            // BEGIN YOUR CODE HERE
        mov ebx, input
        lea edi, output

        //----------------------
        //caller prologue
        push eax
        push ecx
        push edx

        //parameters
        push ebx//n or inpur
        //-----------------------
        cmp ebx, 12
        jle rec_factorial
        ret

    rec_factorial:
        call recFactorial

        //------------------------
        //caller epilogue
        add esp, 4 //remove parameters
        mov edi, eax
        //save onto output


        pop edx
        pop ecx
        pop eax
        //-------------------------

            // END YOUR CODE HERE
    }

}

2 个答案:

答案 0 :(得分:1)

你应该尝试更好地理解指针。 在CPU的汇编程序中,内存是一个字节单元块,就像在C byte memory[mem_size];中一样。每个单元格都有它的地址,如0,1,2 ......,所以第一个单元格值为memory[0],其地址为0

因此,如果您说“我在地址5处有值120”,则表示120 == memory[5](值120等于地址5处的内存单元格的内容)。

通过在C中声明一些变量如int result = 120;,你强制编译器在内存中保留一个int空间(四个字节)(来自未使用的内存部分)并使用值120初始化它。例如,它将选择空闲单元格在地址10和商店价值120。

由于此处编译器在地址10处对值120具有“别名”result,即(10 == &result)(结果的地址为10)和(120 == result)(值120等于结果) 。从CPU的角度来看(不知道结果别名),它看起来像120 == memory[10]

result = 30;表示编译器“将值30写入地址10的存储单元”,即memory[10] = 30;。但是在您的源代码中,您不必处理地址10并解除引用它,因为您的C别名为“result”,因此简单result = 30;就足够了,C编译器将为您处理内存。 / p>

指向结果的指针(值10,即结果值的地址)可以在C中作为int *pointer_to_result = &result;接收。使用它来处理result值本身意味着取消引用它。因此*pointer_to_result = 30;相当于result = 30;。 (或*(&result) = 30;pointer_to_result[0] = 30;

指针数学是如何以许多灵活的方式在内存中处理值的非常强大的方法,但它也允许你以多种方式将自己射入脚中,因此理解计算机内存的概念,它的地址(指针)至关重要)和价值观。

现在在你的例子中,如果你有:

void factorial (unsigned int input, unsigned int *output);

void testCaller() {
    unsigned int result;  //reserve some memory for result at address X
    factorial(5, &result);
}

阶乘函数将在input中获得值“5”,在output中获得值“X”。

这就是为什么提示说*output = ...,而不是output = ...。因此,它将计算结果存储到值“X”(覆盖它,并在范围结束后丢失它),而是存储到地址“X”指向的内存中(输出前面的星号表示应该取消引用值输出)。

在asm中那意味着:

    mov edi,output ; edi = X (memory address where "result" resides).

    lea edi,output ; edi = address of temporary memory where value X is stored
                   ; (if caller did it temporarily store it somewhere,
                   ; otherwise it doesn't even make sense, if it's passed in register)

    mov output,eax ; rewrites value X in function parameter
                   ; caller will have no means to receive it
                   ; in C parameters are free to change by function without
                   ; affecting caller (function receives "copies" of values)

    mov [output],eax ; rewrites value in memory pointed by X
                     ; that's the "unsigned int result;" value
                     ; so caller accessing "result" after will have the value

    ; so as Al Kepp writes, this is the simple way to store result
    ; into memory pointed to by pointer output:
    mov edi,output  ; edi = X
    mov [edi],eax   ; memory[X] = eax

答案 1 :(得分:0)

我只展示了存储输出所需的代码段。只需使用两个mov指令。

...    
call recFactorial
...
mov edi,output
mov [edi],eax

如果你使用lea,那就错了,因为output是一个标准的指针变量。因此,您只需将其加载到edi等寄存器中,然后使用[edi]取消引用它。只是不要忘记用push-pop保护所有已更改的寄存器(就像你已经做的那样)。