ARM64函数调用流程分析

news2025/1/22 16:01:20

ARM64函数调用流程分析

  • 1 ARM64 函数调用实例
  • 2 对应代码的分析
    • 2.1 main函数及其对应的汇编程序
      • 2.1.1 main的C代码实现
      • 2.1.2 main函数对应汇编及其分析
      • 2.1.3 执行完成之后栈的存放情况
    • 2.2 test_fun_a函数及其对应的汇编程序
      • 2.2.1 test_fun_a函数的C实现
      • 2.2.2 test_fun_a函数对应汇编及其分析
      • 2.2.3 执行完成之后栈帧的使用情况
    • 2.3 test_fun_b函数及其对应的汇编程序
      • 2.3.1 test_func_b函数的C实现
      • 2.3.2 test_fun_b函数对应汇编及其分析
      • 2.3.3 执行完成之后栈帧的使用情况

ARM64 程序调用标准

1 ARM64 函数调用实例

下图是介绍一个简单函数调用的示例,在该示例中简单介绍了栈的使用。
在这里插入图片描述

2 对应代码的分析

2.1 main函数及其对应的汇编程序

2.1.1 main的C代码实现

int main(void)
{
        long a = 1;                                                                             
        long b = 2;

        printf("The current function is %s a:%ld b:%ld\r\n", __func__, a, b); 

        test_fun_a(a, b, 0, 1); 

        a = a + b;
        b = a + b;

        return 0;
}

2.1.2 main函数对应汇编及其分析

  • 0000000000000114 <main>:main函数的入口
  • 114: a9be7bfd stp x29, x30, [sp, #-32]! 将sp = sp - 32,为main函数开一个32Byte的栈空间,然后将x29(FP),X30(LR)寄存器的值存放在SP和SP + 8的位置处。
  • 118: 910003fd mov x29, sp 将SP寄存器的值存放到X29(FP)寄存器中,即FP寄存器指向当前main函数的栈顶。
  • 11c: d2800020 mov x0, #0x1 // #1 将局部变量a的值保存到x0寄存器中
  • 120: f9000be0 str x0, [sp, #16] 将局部变量a的值保存到sp + 16的位置处。
  • 124: d2800040 mov x0, #0x2 // #2 将局部变量b的值保存到x0寄存器中
  • 128: f9000fe0 str x0, [sp, #24] 将局部变量b的值保存到sp + 24栈内存处
  • 12c: f9400fe3 ldr x3, [sp, #24] 从栈中加载局部变量b的值到x3寄存器中
  • 130: f9400be2 ldr x2, [sp, #16]从栈中加载局部变量a的值到x2寄存器中
  • 134: 90000000 adrp x0, 0 <test_fun_b>加载test_func_b函数的地址到x0寄存器中
  • 138: 91000001 add x1, x0, #0x0将x0 + 0的值保存到x1寄存器中
  • 13c: 90000000 adrp x0, 0 <test_fun_b>加载test_func_b函数的地址到x0寄存器中
  • 140: 91000000 add x0, x0, #0x0将x0 + 0的值保存到x0寄存器中
  • 144: 94000000 bl 0 <printf>调用函数printf
  • 148: d2800023 mov x3, #0x1 // #1将1保存到x3寄存器中,作为调用test_fun_a函数的第4个参数
  • 14c: d2800002 mov x2, #0x0 // #0将0保存到寄存器x2中,作为调用test_fun_a函数的第3个参数
  • 150: f9400fe1 ldr x1, [sp, #24]从栈中取出局部变量b的值,放到x1寄存器中,作为调用test_fun_a的第2个参数
  • 154: f9400be0 ldr x0, [sp, #16]从栈中取出局部变量a的值,放到x0寄存器中,作为调用test_fun_a的第1个参数
  • 158: 94000000 bl 80 <test_fun_a>调用test_func_a函数,其参数分别为前面的x0 ~ x3寄存器的值
  • 15c: f9400be1 ldr x1, [sp, #16] 加载局部变量a的值到x1寄存器
  • 160: f9400fe0 ldr x0, [sp, #24]加载局部变量b的值到x0寄存器
  • 164: 8b000020 add x0, x1, x0 a = a + b
  • 168: f9000be0 str x0, [sp, #16] 将计算到的局部变量a的值重新存到栈中
  • 16c: f9400fe1 ldr x1, [sp, #24]从栈中取出局部变量b的值
  • 170: f9400be0 ldr x0, [sp, #16]从栈中取出局部变量a的值
  • 174: 8b000020 add x0, x1, x0 b = a + b
  • 178: f9000fe0 str x0, [sp, #24]将新计算得到的局部变量b的值重新保存到栈中
  • 17c: 52800000 mov w0, #0x0 // #0给w0寄存器赋值为0,该操作是用在ret指令执行时,返回0值。
  • 180: a8c27bfd ldp x29, x30, [sp], #32恢复x29(FP)和X30(LR)的值,同时SP = SP + 32
  • 184: d65f03c0 ret 返回调用的指令,该指令执行的时候会返回lr寄存器指向的函数中。
                                                                                             
0000000000000114 <main>:
 114:   a9be7bfd        stp     x29, x30, [sp, #-32]!
 118:   910003fd        mov     x29, sp
 11c:   d2800020        mov     x0, #0x1                        // #1
 120:   f9000be0        str     x0, [sp, #16]
 124:   d2800040        mov     x0, #0x2                        // #2
 128:   f9000fe0        str     x0, [sp, #24]
 12c:   f9400fe3        ldr     x3, [sp, #24]
 130:   f9400be2        ldr     x2, [sp, #16]
 134:   90000000        adrp    x0, 0 <test_fun_b>
 138:   91000001        add     x1, x0, #0x0
 13c:   90000000        adrp    x0, 0 <test_fun_b>
 140:   91000000        add     x0, x0, #0x0
 144:   94000000        bl      0 <printf>
 148:   d2800023        mov     x3, #0x1                        // #1
 14c:   d2800002        mov     x2, #0x0                        // #0
 150:   f9400fe1        ldr     x1, [sp, #24]
 154:   f9400be0        ldr     x0, [sp, #16]
 158:   94000000        bl      80 <test_fun_a>
 15c:   f9400be1        ldr     x1, [sp, #16]
 160:   f9400fe0        ldr     x0, [sp, #24]
 164:   8b000020        add     x0, x1, x0
 168:   f9000be0        str     x0, [sp, #16]
 16c:   f9400fe1        ldr     x1, [sp, #24]
 170:   f9400be0        ldr     x0, [sp, #16]
 174:   8b000020        add     x0, x1, x0
 178:   f9000fe0        str     x0, [sp, #24]
 17c:   52800000        mov     w0, #0x0                        // #0
 180:   a8c27bfd        ldp     x29, x30, [sp], #32
 184:   d65f03c0        ret

2.1.3 执行完成之后栈的存放情况

在这里插入图片描述

2.2 test_fun_a函数及其对应的汇编程序

2.2.1 test_fun_a函数的C实现

void test_fun_a(long m, long n, long x, long y)
{
        long b = 2;
        long c = 3;

        printf("The current function is %s b:%ld c:%ld\r\n", __func__, b, c); 

        test_fun_b(b, c, 0, 2); 

        b = b + c + m;
        c = b + c + n;
}

2.2.2 test_fun_a函数对应汇编及其分析

  • 0000000000000080 <test_fun_a>:test_fun_a函数的入口
  • 80: a9bc7bfd stp x29, x30, [sp, #-64]!为test_fun_a函数开栈64B,同时把X29(FP),X30(LR)保存到栈顶sp和sp + 8的栈内存位置处
  • 84: 910003fd mov x29, sp将sp保存到x29(FP)寄存器中,相当于FP指向栈的栈顶
  • 88: f90017e0 str x0, [sp, #40]将参数1保存到栈的sp + 40栈内存位置处
  • 8c: f90013e1 str x1, [sp, #32]将参数2保存到栈sp + 32的栈内存位置处
  • 90: f9000fe2 str x2, [sp, #24]将参数3保存到栈sp + 24栈内存位置处
  • 94: f9000be3 str x3, [sp, #16]将参数4保存到栈sp + 16栈内存位置处
  • 98: d2800040 mov x0, #0x2 // #2将test_fun_a函数的局部变量b保存到x0寄存器中
  • 9c: f9001be0 str x0, [sp, #48]将test_fun_a函数的局部变量b保存到sp + 48栈内存位置处
  • a0: d2800060 mov x0, #0x3 // #3将test_fun_a函数的局部变量c保存到x1寄存器中
  • a4: f9001fe0 str x0, [sp, #56]将test_fun_a函数的局部变量c保存到栈sp + 56栈内存位置处
  • a8: f9401fe3 ldr x3, [sp, #56]从栈中取出局部变量c的值放到x3寄存器中
  • ac: f9401be2 ldr x2, [sp, #48]从栈中取出局部变量b的值放到x2寄存器中
  • b0: 90000000 adrp x0, 0 <test_fun_b>将test_fun_b函数的地址加载到x0寄存器中
  • b4: 91000001 add x1, x0, #0x0 x1 = x0 + 0,其中x0保存的是test_fun_b的起始地址
  • b8: 90000000 adrp x0, 0 <test_fun_b>将test_fun_b函数的地址加载到x0寄存器中
  • bc: 91000000 add x0, x0, #0x0 x0 = x0 + 0,其中x0保存的是test_fun_b的起始地址
  • c0: 94000000 bl 0 <printf>调用函数printf
  • c4: d2800043 mov x3, #0x2 // #2给x3寄存器赋值为2,作为test_fun_b的第4个参数
  • c8: d2800002 mov x2, #0x0 // #0给x2寄存器赋值为0,作为test_func_b的第三个参数
  • cc: f9401fe1 ldr x1, [sp, #56]从栈中取出局部变量c,存放到x1寄存器,作为test_fun_b的第二个参数
  • d0: f9401be0 ldr x0, [sp, #48]从栈中取出局部变量b,存放到x0寄存器,作为test_fun_b的第一个参数
  • d4: 94000000 bl 0 <test_fun_b>调用test_fun_b函数,x0 ~ x3作为test_fun_a的四个参数
  • d8: f9401be1 ldr x1, [sp, #48]从栈中取出test_fun_a的局部变量b,放到x1寄存器中
  • dc: f9401fe0 ldr x0, [sp, #56]从栈中取出test_fun_a的局部变量c,放到x0寄存器中
  • e0: 8b000020 add x0, x1, x0 c = b + c,将c的结果保存到x0寄存器中。
  • e4: f94017e1 ldr x1, [sp, #40]从栈中取出调用test_fun_a时传入的第1个参数取出,放到x1寄存器中
  • e8: 8b000020 add x0, x1, x0 c = c + m,将计算的结果放到x0寄存器中
  • ec: f9001be0 str x0, [sp, #48]将计算的结果x0的值重新保存到局部变量b的栈内存位置处
  • f0: f9401be1 ldr x1, [sp, #48]从栈中取出局部变量b的值放到x1寄存器中。
  • f4: f9401fe0 ldr x0, [sp, #56]从栈中取出局部变量x的值放到x0寄存器中
  • f8: 8b000020 add x0, x1, x0c = b + c
  • fc: f94013e1 ldr x1, [sp, #32]从栈中取出调用test_fun_a函数时传入的第2个参数放到x1寄存器中
  • 100: 8b000020 add x0, x1, x0 c = c + n,计算的结果放到x0寄存器中
  • 104: f9001fe0 str x0, [sp, #56]将计算的新值存放到原局部变量c的栈内存位置处
  • 108: d503201f nop空操作
  • 10c: a8c47bfd ldp x29, x30, [sp], #64恢复X29(FP),X30(LR)寄存器的值,同时sp = sp + 64栈指针寄存器
  • 110: d65f03c0 ret返回X30(LR)寄存器保存的返回函数处
0000000000000080 <test_fun_a>:
  80:   a9bc7bfd        stp     x29, x30, [sp, #-64]!
  84:   910003fd        mov     x29, sp 
  88:   f90017e0        str     x0, [sp, #40]
  8c:   f90013e1        str     x1, [sp, #32]
  90:   f9000fe2        str     x2, [sp, #24]
  94:   f9000be3        str     x3, [sp, #16]
  98:   d2800040        mov     x0, #0x2                        // #2   
  9c:   f9001be0        str     x0, [sp, #48]
  a0:   d2800060        mov     x0, #0x3                        // #3   
  a4:   f9001fe0        str     x0, [sp, #56]
  a8:   f9401fe3        ldr     x3, [sp, #56]
  ac:   f9401be2        ldr     x2, [sp, #48]
  b0:   90000000        adrp    x0, 0 <test_fun_b>
  b4:   91000001        add     x1, x0, #0x0
  b8:   90000000        adrp    x0, 0 <test_fun_b>
  bc:   91000000        add     x0, x0, #0x0
  c0:   94000000        bl      0 <printf>
  c4:   d2800043        mov     x3, #0x2                        // #2
  c8:   d2800002        mov     x2, #0x0                        // #0
  cc:   f9401fe1        ldr     x1, [sp, #56]
  d0:   f9401be0        ldr     x0, [sp, #48]                                                 
  d4:   94000000        bl      0 <test_fun_b>
  d8:   f9401be1        ldr     x1, [sp, #48]
  dc:   f9401fe0        ldr     x0, [sp, #56]
  e0:   8b000020        add     x0, x1, x0
  e4:   f94017e1        ldr     x1, [sp, #40]
  e8:   8b000020        add     x0, x1, x0
  ec:   f9001be0        str     x0, [sp, #48]
  f0:   f9401be1        ldr     x1, [sp, #48]
  f4:   f9401fe0        ldr     x0, [sp, #56]
  f8:   8b000020        add     x0, x1, x0
  fc:   f94013e1        ldr     x1, [sp, #32]
 100:   8b000020        add     x0, x1, x0
 104:   f9001fe0        str     x0, [sp, #56]
 108:   d503201f        nop
 10c:   a8c47bfd        ldp     x29, x30, [sp], #64
 110:   d65f03c0        ret

2.2.3 执行完成之后栈帧的使用情况

在这里插入图片描述

2.3 test_fun_b函数及其对应的汇编程序

2.3.1 test_func_b函数的C实现

void test_fun_b(long m, long n, long x, long y)
{
        long c = 3;
        long d = 4;

        printf("The current function is %s c:%ld d:%ld\r\n", __func__, c, d); 

        c = c + d + m;
        d = c + d + n;
}

2.3.2 test_fun_b函数对应汇编及其分析

  • 0000000000000000 <test_fun_b>:test_fun_b函数的入口
  • 0: a9bc7bfd stp x29, x30, [sp, #-64]!为test_fun_b函数开栈64B,同时把X29(FP),X30(LR)保存到栈顶sp和sp + 8的栈内存位置处
  • 4: 910003fd mov x29, sp将sp保存到x29(FP)寄存器中,相当于FP指向栈的栈顶
  • 8: f90017e0 str x0, [sp, #40]将参数1保存到栈的sp + 40栈内存位置处
  • c: f90013e1 str x1, [sp, #32]将参数2保存到栈sp + 32的栈内存位置处
  • 10: f9000fe2 str x2, [sp, #24]将参数3保存到栈sp + 24栈内存位置处
  • 14: f9000be3 str x3, [sp, #16]将参数4保存到栈sp + 16栈内存位置处
  • 18: d2800060 mov x0, #0x3 // #3将test_fun_b函数的局部变量c保存到x0寄存器中
  • 1c: f9001be0 str x0, [sp, #48]将test_fun_b函数的局部变量c保存到sp + 48栈内存位置处
  • 20: d2800080 mov x0, #0x4 // #4将test_fun_b函数的局部变量d保存到x1寄存器中
  • 24: f9001fe0 str x0, [sp, #56]将test_fun_b函数的局部变量d保存到栈sp + 56栈内存位置处
  • 28: f9401fe3 ldr x3, [sp, #56]从栈中取出局部变量d的值放到x3寄存器中
  • 2c: f9401be2 ldr x2, [sp, #48]从栈中取出局部变量c的值放到x2寄存器中
  • 30: 90000000 adrp x0, 0 <test_fun_b>将test_fun_b函数的地址加载到x0寄存器中
  • 34: 91000001 add x1, x0, #0x0x1 = x0 + 0,其中x0保存的是test_fun_b的起始地址
  • 38: 90000000 adrp x0, 0 <test_fun_b>将test_fun_b函数的地址加载到x0寄存器中
  • 3c: 91000000 add x0, x0, #0x0x0 = x0 + 0,其中x0保存的是test_fun_b的起始地址
  • 40: 94000000 bl 0 <printf>调用函数printf
  • 44: f9401be1 ldr x1, [sp, #48]从栈中取出局部变量c,存放到x1寄存器
  • 48: f9401fe0 ldr x0, [sp, #56]从栈中取出局部变量d,存放到x0寄存器
  • 4c: 8b000020 add x0, x1, x0 d = c + d,将d的结果保存到x0寄存器中。
  • 50: f94017e1 ldr x1, [sp, #40]从栈中取出调用test_fun_b时传入的第1个参数取出,放到x1寄存器中
  • 54: 8b000020 add x0, x1, x0 d = d + m
  • 58: f9001be0 str x0, [sp, #48]将计算的结果x0的值重新保存到局部变量c的栈内存位置处
  • 5c: f9401be1 ldr x1, [sp, #48]从栈中取出局部变量c的值放到x1寄存器中。
  • 60: f9401fe0 ldr x0, [sp, #56]从栈中取出局部变量d的值放到x0寄存器中
  • 64: 8b000020 add x0, x1, x0 c = c + d
  • 68: f94013e1 ldr x1, [sp, #32]从栈中取出调用test_fun_b函数时传入的第2个参数放到x1寄存器中
  • 6c: 8b000020 add x0, x1, x0 c = c + n
  • 70: f9001fe0 str x0, [sp, #56]将计算的新值存放到原局部变量d的栈内存位置处
  • 74: d503201f nop空操作
  • 78: a8c47bfd ldp x29, x30, [sp], #64恢复X29(FP),X30(LR)寄存器的值,同时sp = sp + 64栈指针寄存器
  • 7c: d65f03c0 ret返回X30(LR)寄存器保存的返回函数处
0000000000000000 <test_fun_b>:
   0:   a9bc7bfd        stp     x29, x30, [sp, #-64]!
   4:   910003fd        mov     x29, sp
   8:   f90017e0        str     x0, [sp, #40]
   c:   f90013e1        str     x1, [sp, #32]
  10:   f9000fe2        str     x2, [sp, #24]
  14:   f9000be3        str     x3, [sp, #16]
  18:   d2800060        mov     x0, #0x3                        // #3
  1c:   f9001be0        str     x0, [sp, #48]
  20:   d2800080        mov     x0, #0x4                        // #4
  24:   f9001fe0        str     x0, [sp, #56]
  28:   f9401fe3        ldr     x3, [sp, #56]
  2c:   f9401be2        ldr     x2, [sp, #48]
  30:   90000000        adrp    x0, 0 <test_fun_b>                                            
  34:   91000001        add     x1, x0, #0x0
  38:   90000000        adrp    x0, 0 <test_fun_b>
  3c:   91000000        add     x0, x0, #0x0
  40:   94000000        bl      0 <printf>
  44:   f9401be1        ldr     x1, [sp, #48]
  48:   f9401fe0        ldr     x0, [sp, #56]
  4c:   8b000020        add     x0, x1, x0
  50:   f94017e1        ldr     x1, [sp, #40]
  54:   8b000020        add     x0, x1, x0
  58:   f9001be0        str     x0, [sp, #48]
  5c:   f9401be1        ldr     x1, [sp, #48]
  60:   f9401fe0        ldr     x0, [sp, #56]
  64:   8b000020        add     x0, x1, x0
  68:   f94013e1        ldr     x1, [sp, #32]
  6c:   8b000020        add     x0, x1, x0
  70:   f9001fe0        str     x0, [sp, #56]
  74:   d503201f        nop     
  78:   a8c47bfd        ldp     x29, x30, [sp], #64
  7c:   d65f03c0        ret

2.3.3 执行完成之后栈帧的使用情况

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/925037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习ts(八)模块与命名空间

模块 ts与es5一样&#xff0c;任何包含顶级import和export的文件都被当成一个模块。相反的&#xff0c;如果一个文件不带有顶级的import和export声明&#xff0c;那么他的内容被视为全局可见的。 在两个文件中声明相同属性名的变量&#xff0c;会出现错误信息 可以使用export…

中文分词和tfidf特征应用

文章目录 引言1. NLP 的基础任务 --分词2. 中文分词2.1 中文分词-难点2.2 中文分词-正向最大匹配2.2.1 实现方式一2.2.2 实现方式二 利用前缀字典 2.3 中文分词-反向最大匹配2.4 中文分词-双向最大匹配2.5 中文分词-jieba分词2.5.1 基本用法2.5.2 分词模式2.5.3 其他功能 2.6 三…

帆软FineReport下拉框联动实现

在用帆软做报表展示时&#xff0c;有需求是要进行联动效果&#xff0c;记录下来&#xff0c;方便查看。 帆软版本&#xff1a;10.0 背景 编辑栏两个控件&#xff0c;产品ID是输入框&#xff0c;用户可输入产品ID&#xff0c;产品名称为下拉框&#xff0c;可选择产品名称。当用…

C语言实例_双向链表增删改查

一、双向链表介绍 双向链表&#xff08;Doubly Linked List&#xff09;是一种常见的数据结构&#xff0c;在单链表的基础上增加了向前遍历的功能。与单向链表不同&#xff0c;双向链表的每个节点除了包含指向下一个节点的指针外&#xff0c;还包含指向前一个节点的指针。 作用…

NPM中管理团队

目录 1、关于开发团队 2、创建团队 3、将组织成员添加到团队 3.1 从CLI管理团队 4、从团队中删除组织成员 5、管理团队对组织包的访问 5.1 向团队添加包访问权限 Web网页上的团队添加包访问权限 使用CLI向团队添加包访问权限 5.2 从组中删除包访问权限 从Web网页上的…

【Vue】vue2预览显示quill富文本内容,vue-quill-editor回显页面,v-html回显富文本内容

文章目录 前言一、下载二、使用步骤1.引入样式2.html代码 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; vue后台框架&#xff0c;若依系统里有一个富文本编辑器&#xff0c;效果如下 在package.json里面查看&#xff0c;发现插件名叫quill 插件的…

Systick滴答定时器

今天&#xff0c;对Systick滴答定时器进行资料的整理&#xff0c;这个定时器在程序中的作用就是提供延时函数。参考&#xff08;【STM32】Systick滴答定时器_一只大喵咪1201的博客-CSDN博客&#xff09; Systick滴答定时器的介绍 相关寄存器 寄存器CTRL 补充HCLK 寄存器LOAD…

Linux 网络编程 和 字节序的概念

网络编程概述 不同于之前学习的所有通讯方法&#xff0c;多基于Linux内核实现&#xff0c;只能在同一个系统中不同进程或线程间通讯&#xff0c;Linux的网络编程可以实现真正的多机通讯&#xff01; 两个不相关的终端要实现通讯&#xff0c;必须依赖网络&#xff0c;通过地址…

【C++】—— c++11新特性之 lambda

前言&#xff1a; 上期&#xff0c;我们学习了有关 C11 一些属于了解的新特性介绍。本期&#xff0c;我们要讲到的内容则属于 需要掌握 的知识点之一。 目录 &#xff08;一&#xff09;lambda 的引入 &#xff08;二&#xff09; lambda表达式 1、lambda表达式语法 2、捕获…

压力监测设备——监测压力的仪器仪表

压力监测设备的原理和差压变送器相同&#xff0c;所不同的是压力监测设备低压室压力是大气压或真空。压力监测设备是一种接受压力变量&#xff0c;经传感转换后&#xff0c;按一定比例将压力变化转换成标准信号的仪表。 压力监测设备的输出信号传送到中央控制室进行压力指示和…

【大模型】基于 LlaMA2 的高 star 的 GitHub 开源项目汇总

【大模型】基于 LlaMA2 的高 star 的 GitHub 开源项目汇总 Llama2 简介开源项目汇总NO1. FlagAlpha/Llama2-ChineseNO2. hiyouga/LLaMA-Efficient-TuningNO3. yangjianxin1/FireflyNO4. LinkSoul-AI/Chinese-Llama-2-7bNO5. wenge-research/YaYiNO6. michael-wzhu/Chinese-LlaM…

万字精讲——数据结构栈与队列必会OJ练习

W...Y的主页 &#x1f495; 代码库分享 &#x1f60a; 在之前的博客中&#xff0c;我们学习了栈与队列的基本内容&#xff0c;并且实现了栈与队列。今天我们进行刷题训练&#xff0c;走进栈与队列的世界中去感受一番&#xff01;&#xff01;&#xff01; 目录 括号匹配问题…

springboot集成redisson

springboot集成redisson有两种方式&#xff0c;分别是集成redisson-spring-boot-starter或redisson-spring-data。由于作者的项目和redisson-spring-boot-starter有冲突&#xff0c;所以选择集成redisson-spring-data&#xff0c;下面介绍集成集成步骤&#xff0c;已单机版redi…

对CSV格式的数据文件进行插值处理

使用Python程序&#xff0c;实现对一个较短的csv文件&#xff0c;进行差值处理&#xff0c;并绘制GUI界面&#xff1b; 这个程序是一个使用Python的Tkinter库构建的GUI应用程序&#xff0c;用于对CSV格式的数据文件进行插值处理。下面我会逐步解释程序的各个部分和功能&#x…

使用 docker 搭建 granfana+prometheus 监控平台监控测试服务器资源

互联网发展的今天&#xff0c;人们对互联网产品的用户体验要求也越来越高&#xff0c;企业为了能提供更优质的用户体验&#xff0c;就会绞尽脑汁想尽各种办法。而对于服务器的资源监控&#xff0c;搭建一个资源监控平台&#xff0c;就是一个很好的维护优质服务的保障平台。利用…

函数的参数传递和返回值-PHP8知识详解

本文学习的是《php8知识详解》中的《函数的参数传递和返回值》。主要包括&#xff1a;向函数传递参数值、向函数传递参数引用、函数的返回值。 1、向函数传递参数值 函数是一段封闭的程序&#xff0c;有时候&#xff0c;程序员需要向函数传递一些数据进行操作。可以接受传入参…

Python如何输出文本到屏幕

如何输出文本到屏幕 在Python中&#xff0c;要将文本输出到屏幕&#xff0c;可以使用print()函数。这个函数是Python中的内置函数&#xff0c;非常常用&#xff0c;让我们一起来学习如何使用它。 使用print()函数 print()函数用于将内容输出到终端&#xff08;屏幕&#xff…

从0开始配置eslint

没有在.eslintrc文件中配置parserOptions指定语言版本和模块类型 {"parserOptions": {"ecmaVersion": 7, //指定es版本为es2016"sourceType": "module", //使用import导入模块} }eslint还不能识别jsx语法 {"parserOptions"…

Android11.0 Launcher3单层app列表页排序功能实现

1.概述 在11.0的定制化开发中,对于Launcher3的功能定制也是好多的,而对于单层app列表页来说排序功能的开发,也是常有的功能这就需要了解加载app数据的流程,然后根据需要进行排序就可以了, 如图: 2. Launcher3 单层app列表页排序功能实现 packages\apps\Launcher3\src\…

禅道后台命令执行漏洞

漏洞简介 禅道是第一款国产的开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、 组织管理和事务管理于一体&#xff0c;是一款专业的研发项目管理软件&#xff0c;完整地覆盖了项目管理的核心流程。 禅道管理思想注重实效&#xff0c;功能完备丰富&#xff0c;…