Linux Android ARM 64 bit32 bit 编程移植

    xiaoxiao2021-08-20  104

    ARMv8 arch overview

    32bit user @ 64 bit kernel

    ARMv8支持64-bit 和32-bit所规范的层次结构

    ARMv8arch overview-generalregister layout

    Armv8架构下有31个通用寄存器(R0-R30),每个寄存器有64bit的位宽。访问方式:

          当作64-bit寄存器来访问,命名为(X0-X30)       当作32-bit寄存器来访问,命名为(W0-W30)       X30用来作为连接寄存器(LR), 用来保存调用子程序的返回地址或者异常返回地址.      SP是专用堆栈指针寄存器,位宽64bit,用来保存当前处理器模式的堆栈的栈顶。       PC是程序计数器,位宽64bit,其内容是处理器要取的下一条指令的地址。Armv8软件上不能直接操作PC。 ARMv8arch overview-AddressTranslation

    l Usecompat_ioctl( ) but not onlyunlock_ioctl() in kernel driver lcompat_ioctl( ) :支持64bitdriver必须要实现的ioctl当有32bituserspace application call 64bit kernelIOCTL的时候,这个callback会被调用到 lioctl参数和结构体一致性

     1.   数据类型 nILP32数据模型是32bit系统中用的最多的数据模型,在64bit系统中,用的比较多的就有两种LP64LLP64 nLP64主要用在linux系统上,而LLP64主要用在windows系统上,移植代码时需要注意数据类型在不同平台上的长度

    Programming Type

    ILP32

    LP64(linux)

    LLP64(windows)

    char

    8-bit

    8-bit

    8-bit

    short

    16-bit

    16-bit

    16-bit

    int

    32-bit

    32-bit

    32-bit

    long

    32-bit

    64-bit

    32-bit

    long long

    64-bit

    64-bit

    64-bit

    float

    32-bit

    32-bit

    32-bit

    double

    64-bit

    64-bit

    64-bit

    size_t

    32-bit

    64-bit

    64-bit

    void * (pointer)

    32-bit

    64-bit

    64-bit

    intptr_t

    32-bit

    64-bit

    64-bit

    ptrdiff_t

    32-bit

    64-bit

    64-bit

    2.   类型转化

    3.   高位截断

    情形一:函数中如果需要精确地控制指针偏移时,有时候需要添加一个偏移量,处理时我们可能会选择先把指针转化为 int 或者 unsigned int 类型,这在 32bit 平台上是 OK 的,但在 64bit 平台上则会发生高位截断。强制类型转换会把高位数据丢 .

    情形二:在分配一个对齐指针时,可能会先把指针做类型转化,接着再与上一个对齐量,这种做法在64bit平台上也同样存在高位截断问题。 4.移位有效性     32bit 平台允许 bitNum 设置在 0~31 之间,在 64bit 平台可能允许 bitNum 设置在 0~63 之间。 下边函数 SetBitN ( ) 32bit 平台上可以正常工作, 但在 64bit 平台,当 bitNum >31 时候,便取不到正确结果。这是因为对于没有加任何后缀的常量或者立即数,编译器会认为它属于最小的那种类型。

    longlongSetBitN(longlong value, unsignedbitNum)

    {

           longlong mask

           mask = (longlong) 1 <<bitNum;

           return value |msk;

    }

    或者

    {

           longlong mask

           mask = 1LL<<bitNum;

           return value |mask;

    }

    5.位域操作 32bit平台下由于longint数据类型长度一样,可以取得正确的结果。 64bit平台下由于long int数据类型长度不一致,将会取得错误的结果。 6.函数返回 情形一:这种错误跟函数原型的定义有关系,例如在函数中引用一个子函数,而子函数没有显式定义的话,虽然链接的时候还是可以链接成功,但编译器由于不知道返回值是什么,就会使用缺省的int类型。 例如下边的例子,在 64bit 平台上就不能很好的工作了。

    8.   常数有效性

    情景一:有时候如果是习惯于32bit的思维,做一些操作时我们会去做一些假设,比如pointer size等于40x7FFF FFFF32bit有符号数最大值等等,或者在32bit环境下常用无符号常量0xFFFF FFFF用来测试是否等于-1

                    defineINVALID_POINTER_VALUE 0xFFFFFFFF

    64bit系统中,这个值不是-1, 而是4294967295; 在64bit系统中,-1正确的值应当为0xFFFF FFFFFFFFFFFF。要避免这个问题,在常量声明时,使用const并带上signed或者unsigned

                      Const signedintINVALID_POINTER_VALUE =  0xFFFF FFFF

    上边代码,在32bit或者64bit环境下都可以正常运行。另外,根据需要,适当的使用L后缀或者U后缀来声明整形常量。

    代码检查check list

    声明

    1)如果变量32bit平台是32位的,64bit平台是32位的,根据需要可以将其类型定义为int

    2)如果变量32bit平台是32位的,64bit平台是64位的,根据需要可以将其类型定义为long

    3)防止符号扩展,需要Check变量是否可以定义成unsigned.

    4)防止符号扩展,需要Check常量是否需要添加L”或者U”来约束.

    表达式

    1Check表达式是否存在显示类型转换

    2)注意隐形转化,需要Check表达式操作数是否混合使用不同数据类型.

    3)注意隐形转化,需要Check表达式操作数是否混合使用有符号数与无符号数.

    赋值

    1Check是否存在把指针变量赋值给int

    2Check是否存在把int赋值给指针变量

    3Check是否存在左值&&右值数据类型不一致

    函数参数相关

    1Check调用到的函数,是否已经声明。

    2Check实参数据类型与形参数据类型是否匹配。

    字符串格式化

    1Check地址打印,尽量使用printk("addr=%p\n", addr)格式.

    2Check整型打印,例如int型用%d或者%xlong型用%ld或者%lx.

    转载请注明原文地址: https://ju.6miu.com/read-676726.html

    最新回复(0)