简体   繁体   English

64位GCC混合32位和64位指针

[英]64-bit GCC mixing 32-bit and 64-bit pointers

Although the code works, I'm baffled by the compiler's decision to seemingly mix 32 and 64 bit parameters of the same type. 尽管代码有效,但我对编译器决定混合使用相同类型的32位和64位参数感到困惑。 Specifically, I have a function which receives three char pointers. 具体来说,我有一个接收三个char指针的函数。 Looking at the assembly code, two of the three are passed as 64-bit pointers (as expected), while the third, a local constant, but character string nonetheless, is being passed as a 32-bit pointer. 查看汇编代码,三个中的两个作为64位指针(如预期的那样)传递,而第三个,一个局部常量,但仍然是字符串,作为32位指针传递。 I don't see how my function could ever know when the 3rd parameter isn't a fully loaded 64-bit pointer. 我没有看到我的函数如何知道第3个参数何时不是满载的64位指针。 Obviously it doesn't matter as long as the higher side is 0, but I don't see it making an effort to ensure that. 显然,只要较高的一方为0,这并不重要,但我不认为它会努力确保这一点。 Anything could be in the high side of RDX in this example. 在这个例子中,任何东西都可能在RDX的高端。 What am I missing? 我错过了什么? BTW, the receiving function assumes it's a full 64-bit pointer and includes this code on entry: 顺便说一句,接收函数假定它是一个完整的64位指针,并在输入时包含此代码:

     movq    %rdx, -24(%rbp)

This is the code in question: 这是有问题的代码:

.LC4
    .string "My Silly String"

    .text
    .globl funky_funk
    .type  funky_funk, @function
    funky_funk:
        pushq     %rbp
            movq      %rsp, %rbp
            pushq     %rbx
            subq      $16, %rsp
            movq      %rdi, -16(%rbp)          ;char *dst 64-bit
            movl      %esi, -20(%rbp)          ;int len, 32 bits OK

            movl      $.LC4, %edx              ;<<<<---- why is it not RDX?

            movl      -20(%rbp), %ecx          ;int len 32-bits OK
            movq      -16(%rbp), %rbx          ;char *dst 64-bit
            movq      -16(%rbp), %rax          ;char *dst 64-bit
            movq      %rbx, %rsi               ;char *dst 64-bit
            movq      %rax, %rdi               ;char *dst 64-bit
            call      edc_function


    void funky_funk(char *dst, int len)
    {                                             //how will function know when 
         edc_function(dst, dst, STRING_LC4, len); //a str passed in 3rd parm
    }                                             //is 32-bit ptr vs 64-bit ptr?

    void edc_function(char *dst, char *src, char *key, int len)
    {
         //so, is key a 32-bit ptr? or is key a 64-bit ptr?
    }

When loading a 32 bits value in a register, the value is zero extended. 在寄存器中加载32位值时,该值为零扩展。 You are probably working in a mode where the compiler knows the code is in the lower 32 bit addressable memory. 您可能正在使用编译器知道代码位于低32位可寻址内存中的模式。

GCC has several memory models for x64, two of which have that property. GCC有几种用于x64的内存模型,其中两种具有该属性。 From GCC documentation: 来自GCC文件:

`-mcmodel=small'
     Generate code for the small code model: the program and its
     symbols must be linked in the lower 2 GB of the address space.
     Pointers are 64 bits.  Programs can be statically or dynamically
     linked.  This is the default code model.
`-mcmodel=medium'
     Generate code for the medium model: The program is linked in the
     lower 2 GB of the address space.  Small symbols are also placed
     there.  Symbols with sizes larger than `-mlarge-data-threshold'
     are put into large data or bss sections and can be located above
     2GB.  Programs can be statically or dynamically linked.

(the other ones are kernel, which is similar to small but in the upper/negative 2GB of address space and large with no restriction). (其他的是内核,类似于小但在2GB的上/负2GB地址空间,大而没有限制)。

Adding this as an answer, as it contains "part of the puzzle" for the original question: 添加此作为答案,因为它包含原始问题的“部分难题”:

As long as the compiler can determine [by for example specifying a memorymodel that satisfies this] that .LC4 is within the first 4GB, it can do this. 只要编译器可以确定[通过例如指定满足此的内存模型] .LC4在前4GB内,它就可以做到这一点。 %edx will be loaded with 32 bits of the address of LC4, and upper bits set to zero, so when the edc_function() is called, it can use the full 64-bits of %rdx, and as long as the address is within the lower 4GB, it will work out fine. %edx将加载32位的LC4地址,高位设置为零,因此当调用edc_function()时,它可以使用%rdx的完整64位,并且只要地址在较低的4GB,它会很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM