X86_64函数调用汇编程序分析

news2024/9/24 12:31:41

X86_64函数调用汇编程序分析

  • 1 X86_64寄存器使用标准
  • 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 执行完成之后栈帧的使用情况
  • 3 X86_64 函数调用示例及其栈帧示意图
  • 4 编译和反汇编的命令
    • 4.1 编译的命令
    • 4.2 反汇编的命令

1 X86_64寄存器使用标准

  • %rdi, %rsi, %rdx, %rcx, %r8, %r9分别用于函数调用过程中的前6个参数,对于6的参数存放在栈中传递
  • %rsp用做栈指针寄存器,指向栈顶
  • %rbp用作栈框寄存器,指向栈底
  • %rax用做函数返回值的第一个寄存器

在这里插入图片描述

2 对应代码的分析

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

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.1 main的C代码实现

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

这段汇编代码实现了一个简单的程序,其功能如下:

  1. 首先,endbr64指令用于清除处理器的前瞻指令缓存,确保后面的指令正确执行。
  2. push %rbpmov %rsp,%rbp这两个指令用于保存和设置栈帧的基址指针(Base Pointer)。
  3. sub $0x10,%rsp指令用于为局部变量和保存的寄存器值分配栈空间。
  4. movq $0x1,-0x10(%rbp)movq $0x2,-0x8(%rbp)这两个指令用于将字面量1和2存储到栈中的特定位置。
  5. mov -0x8(%rbp),%rdxmov -0x10(%rbp),%rax这两个指令用于从栈中获取之前保存的值。
  6. mov %rdx,%rcxmov %rax,%rdx这两个指令用于将寄存器的值进行传递,为后面的函数调用做准备。
  7. lea 0xdf8(%rip),%rsilea 0xda6(%rip),%rdi这两个指令用于设置printf函数的参数,分别对应格式字符串和要打印的变量。
  8. mov $0x0,%eax指令用于设置系统调用的编号(这里为0,即系统调用号)。
  9. callq 1050 <printf@plt>这个指令发起系统调用,执行printf函数,打印输出指定的字符串和数值。
  10. 接下来,mov -0x8(%rbp),%rsimov -0x10(%rbp),%raxmov $0x1,%ecxmov $0x0,%edxmov %rax,%rdi这些指令用于设置函数test_fun_a的参数。
  11. callq 11e8 <test_fun_a>这个指令调用函数test_fun_a,执行其代码。
  12. 在函数test_fun_a执行完成后,通过一系列的移动和加法操作,将返回值存储回原始的参数位置。
  13. 最后,mov $0x0,%eaxleaveqretq这些指令用于清理栈帧、结束当前函数并返回。

这段汇编代码的功能是调用函数test_fun_a,并打印输出两个数值1和2,然后调用函数test_fun_a并将返回值存储回原始的参数位置。

000000000000128a <main>:
    128a:	f3 0f 1e fa          	endbr64 
    128e:	55                   	push   %rbp
    128f:	48 89 e5             	mov    %rsp,%rbp
    1292:	48 83 ec 10          	sub    $0x10,%rsp
    1296:	48 c7 45 f0 01 00 00 	movq   $0x1,-0x10(%rbp)
    129d:	00 
    129e:	48 c7 45 f8 02 00 00 	movq   $0x2,-0x8(%rbp)
    12a5:	00 
    12a6:	48 8b 55 f8          	mov    -0x8(%rbp),%rdx
    12aa:	48 8b 45 f0          	mov    -0x10(%rbp),%rax
    12ae:	48 89 d1             	mov    %rdx,%rcx
    12b1:	48 89 c2             	mov    %rax,%rdx
    12b4:	48 8d 35 f8 0d 00 00 	lea    0xdf8(%rip),%rsi        # 20b3 <__func__.2519>
    12bb:	48 8d 3d a6 0d 00 00 	lea    0xda6(%rip),%rdi        # 2068 <_IO_stdin_used+0x68>
    12c2:	b8 00 00 00 00       	mov    $0x0,%eax
    12c7:	e8 84 fd ff ff       	callq  1050 <printf@plt>
    12cc:	48 8b 75 f8          	mov    -0x8(%rbp),%rsi
    12d0:	48 8b 45 f0          	mov    -0x10(%rbp),%rax
    12d4:	b9 01 00 00 00       	mov    $0x1,%ecx
    12d9:	ba 00 00 00 00       	mov    $0x0,%edx
    12de:	48 89 c7             	mov    %rax,%rdi
    12e1:	e8 02 ff ff ff       	callq  11e8 <test_fun_a>
    12e6:	48 8b 45 f8          	mov    -0x8(%rbp),%rax
    12ea:	48 01 45 f0          	add    %rax,-0x10(%rbp)
    12ee:	48 8b 45 f0          	mov    -0x10(%rbp),%rax
    12f2:	48 01 45 f8          	add    %rax,-0x8(%rbp)
    12f6:	b8 00 00 00 00       	mov    $0x0,%eax
    12fb:	c9                   	leaveq 
    12fc:	c3                   	retq   
    12fd:	0f 1f 00             	nopl   (%rax)

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 a = x;
        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, a, 2); 

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

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

这段汇编代码是一个函数test_fun_a的实现,其功能大致如下:

  1. push %rbpmov %rsp,%rbp 用于保存和设置栈帧的基址指针(Base Pointer)。
  2. sub $0x40,%rsp 用于为局部变量和保存的寄存器值分配栈空间。
  3. mov %rdi,-0x28(%rbp)mov %rsi,-0x30(%rbp)mov %rdx,-0x38(%rbp)mov %rcx,-0x40(%rbp) 用于将参数传递到栈帧中的指定位置。
  4. mov %rax,-0x18(%rbp) 将某个值(可能是函数内的临时变量或计算结果)保存到栈帧的另一个位置。
  5. movq $0x2,-0x10(%rbp)movq $0x3,-0x8(%rbp) 用于将字面量值2和3存储到栈中的特定位置。
  6. mov -0x8(%rbp),%rdxmov -0x10(%rbp),%rax 用于从栈中获取之前保存的值。
  7. lea 0xe77(%rip),%rsilea 0xe00(%rip),%rdi 用于设置printf函数的参数,分别对应格式字符串和要打印的变量。
  8. mov $0x0,%eax 用于设置系统调用的编号(这里为0,即系统调用号)。
  9. callq 1050 <printf@plt> 发起系统调用,执行printf函数,打印输出指定的字符串和数值。
  10. mov -0x18(%rbp),%rdxmov -0x8(%rbp),%rsimov -0x10(%rbp),%raxmov $0x2,%ecxmov %rax,%rdi 用于设置函数test_fun_b的参数。
  11. callq 1149 <test_fun_b> 调用函数test_fun_b,执行其代码。
  12. 在函数test_fun_b执行完成后,将返回值存储到栈帧的特定位置。
  13. 最后,通过一系列的移动和加法操作,将计算结果存储回原始的第一个参数的位置。
  14. 48 8b 45 d0 mov -0x30(%rbp),%rax: 将栈帧中偏移为-0x30的位置的值加载到寄存器rax中。
  15. 48 01 d0 add %rdx,%rax: 将rax和rdx寄存器的值相加,并将结果存储回rax寄存器中。
  16. 48 89 45 f8 mov %rax,-0x8(%rbp): 将rax寄存器的值存储回栈帧中偏移为-0x8的位置。
  17. 90: 无操作,用于填充指令。
  18. c9: leaveq指令用于撤销栈帧,恢复调用前的堆栈状态。
  19. c3: retq指令用于从当前函数返回,返回到调用者的代码位置。
00000000000011e8 <test_fun_a>:
    11e8:	f3 0f 1e fa          	endbr64 
    11ec:	55                   	push   %rbp
    11ed:	48 89 e5             	mov    %rsp,%rbp
    11f0:	48 83 ec 40          	sub    $0x40,%rsp
    11f4:	48 89 7d d8          	mov    %rdi,-0x28(%rbp)
    11f8:	48 89 75 d0          	mov    %rsi,-0x30(%rbp)
    11fc:	48 89 55 c8          	mov    %rdx,-0x38(%rbp)
    1200:	48 89 4d c0          	mov    %rcx,-0x40(%rbp)
    1204:	48 8b 45 c8          	mov    -0x38(%rbp),%rax
    1208:	48 89 45 e8          	mov    %rax,-0x18(%rbp)
    120c:	48 c7 45 f0 02 00 00 	movq   $0x2,-0x10(%rbp)
    1213:	00 
    1214:	48 c7 45 f8 03 00 00 	movq   $0x3,-0x8(%rbp)
    121b:	00 
    121c:	48 8b 55 f8          	mov    -0x8(%rbp),%rdx
    1220:	48 8b 45 f0          	mov    -0x10(%rbp),%rax
    1224:	48 89 d1             	mov    %rdx,%rcx
    1227:	48 89 c2             	mov    %rax,%rdx
    122a:	48 8d 35 77 0e 00 00 	lea    0xe77(%rip),%rsi        # 20a8 <__func__.2513>
    1231:	48 8d 3d 00 0e 00 00 	lea    0xe00(%rip),%rdi        # 2038 <_IO_stdin_used+0x38>
    1238:	b8 00 00 00 00       	mov    $0x0,%eax
    123d:	e8 0e fe ff ff       	callq  1050 <printf@plt>
    1242:	48 8b 55 e8          	mov    -0x18(%rbp),%rdx
    1246:	48 8b 75 f8          	mov    -0x8(%rbp),%rsi
    124a:	48 8b 45 f0          	mov    -0x10(%rbp),%rax
    124e:	b9 02 00 00 00       	mov    $0x2,%ecx
    1253:	48 89 c7             	mov    %rax,%rdi
    1256:	e8 ee fe ff ff       	callq  1149 <test_fun_b>
    125b:	48 8b 55 f0          	mov    -0x10(%rbp),%rdx
    125f:	48 8b 45 f8          	mov    -0x8(%rbp),%rax
    1263:	48 01 c2             	add    %rax,%rdx
    1266:	48 8b 45 d8          	mov    -0x28(%rbp),%rax
    126a:	48 01 d0             	add    %rdx,%rax
    126d:	48 89 45 f0          	mov    %rax,-0x10(%rbp)
    1271:	48 8b 55 f0          	mov    -0x10(%rbp),%rdx
    1275:	48 8b 45 f8          	mov    -0x8(%rbp),%rax
    1279:	48 01 c2             	add    %rax,%rdx
    127c:	48 8b 45 d0          	mov    -0x30(%rbp),%rax
    1280:	48 01 d0             	add    %rdx,%rax
    1283:	48 89 45 f8          	mov    %rax,-0x8(%rbp)
    1287:	90                   	nop
    1288:	c9                   	leaveq 
    1289:	c3                   	retq

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 a = y;
        long b = m;
        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 + a;
        d = c + d + n + b;                                                                  
}

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

这段汇编代码是一个函数test_fun_b的实现。下面是对代码的逐行解释:

1149: f3 0f 1e fa - endbr64指令用于结束64位BR(Branch Prediction)指令的预测。

114d: 55 - push %rbp将当前栈帧的基址指针(Base Pointer,简称RBp)压入栈中,为新的栈帧做准备。

114e: 48 89 e5 - mov %rsp,%rbp将当前栈帧的栈指针(Stack Pointer,简称SP)复制给基址指针(RBp),建立新的栈帧。

1151: 48 83 ec 40 - sub $0x40,%rsp从SP中减去0x40个字节,扩展栈空间。

1155: 48 89 7d d8 - mov %rdi,-0x28(%rbp)将函数参数rdi的值存储到当前栈帧的-0x28位置。

1159: 48 89 75 d0 - mov %rsi,-0x30(%rbp)将函数参数rsi的值存储到当前栈帧的-0x30位置。

115d: 48 89 55 c8 - mov %rdx,-0x38(%rbp)将函数参数rdx的值存储到当前栈帧的-0x38位置。

1161: 48 89 4d c0 - mov %rcx,-0x40(%rbp)将函数参数rcx的值存储到当前栈帧的-0x40位置。

1165: 48 8b 45 c0 - mov -0x40(%rbp),%rax将当前栈帧的-0x40位置的值加载到寄存器rax中。

1169: 48 89 45 e0 - mov %rax,-0x20(%rbp)将寄存器rax的值存储到当前栈帧的-0x20位置。

116d: 48 8b 45 d8 - mov -0x28(%rbp),%rax将当前栈帧的-0x28位置的值加载到寄存器rax中。

1171: 48 89 45 e8 - mov %rax,-0x18(%rbp)将寄存器rax的值存储到当前栈帧的-0x18位置。

1175: 48 c7 45 f0 03 00 00 00 - movq $0x3,-0x10(%rbp)将立即数0x3存储到当前栈帧的-0x10位置。
117d: 48 c7 45 f8 04 00 00 00 - movq $0x4,-0x8(%rbp)将立即数0x4存储到当前栈帧的-0x8位置。

1185: 48 8b 55 f8 - mov -0x8(%rbp),%rdx将当前栈帧的-0x8位置的值加载到寄存器rdx中。

1189: 48 8b 45 f0 - mov -0x10(%rbp),%rax将当前栈帧的-0x10位置的值加载到寄存器rax中。

118d: 48 89 d1 - mov %rdx,%rcx将寄存器rdx的值复制给rcx。

1190: 48 89 c2 - mov %rax,%rdx将寄存器rax的值复制给rdx。

1193: 48 8d 35 fe 0e 00 00 - lea 0xefe(%rip),%rsi将相对地址0xefe处的值加载到寄存器rsi。

119a: 48 8d 3d 67 0e 00 00 - lea 0xe67(%rip),%rdi将相对地址0xe67处的值加载到寄存器rdi。

11a1: b8 00 00 00 00 - mov $0x0,%eax将立即数0x0加载到寄存器eax。

11a6: e8 a5 fe ff ff - callq 1050 <printf@plt>调用函数plt的printf函数,跳转到地址1050处执行。

接下来的指令继续处理计算结果,并执行一些算术操作。

11ab: 48 8b 55 f0 - mov -0x10(%rbp),%rdx将当前栈帧的-0x10位置的值加载到寄存器rdx中。

11af: 48 8b 45 f8 - mov -0x8(%rbp),%rax将当前栈帧的-0x8位置的值加载到寄存器rax中。

11b3: 48 01 c2 - add %rax,%rdx将寄存器rax和rdx的值相加,结果存储在rdx中。

11b6: 48 8b 45 d8 - mov -0x28(%rbp),%rax将当前栈帧的-0x28位置的值加载到寄存器rax中。

11bd: 48 01 c2 - add %rax,%rdx将寄存器rax和rdx的值相加,结果存储在rdx中。

11c1: 48 8b 45 e0 - mov -0x20(%rbp),%rax将当前栈帧的-0x20位置的值加载到寄存器rax中。

11c4: 48 01 d0 - add %rdx,%rax将寄存器rdx和rax的值相加,结果存储在rax中。

11c8: 48 89 45 f0 - mov %rax,-0x10(%rbp)将寄存器rax的值存储到当前栈帧的-0x10位置。

11cc: 48 8b 45 f8 mov -0x8(%rbp),%rax将当前栈帧的-0x8位置的值加载到rax寄存器中

11d0: 48 01 c2 add %rax,%rdx将寄存器rax和rdx的值相加,结果存储在rdx中。

11d3: 48 8b 45 d0 mov -0x30(%rbp),%rax将当前栈帧的-0x30位置的值加载到rax寄存器中

11d7: 48 01 c2 add %rax,%rdx 将寄存器rax和rdx的值相加,结果存储在rdx中。

11da: 48 8b 45 e8 mov -0x18(%rbp),%rax将当前栈帧的-0x18位置的值加载到rax寄存器中

11de: 48 01 d0 add %rdx,%rax 将寄存器rdx和rax的值相加,结果存储在rax中。

11e1: 48 89 45 f8 mov %rax,-0x8(%rbp)将寄存器rax的值存储到当前栈帧的-0x8位置。

11e5: 90 nop

11e6: c9 leaveq 撤销栈帧,恢复调用前的堆栈状态。

11e7: c3 retq从当前函数返回,返回到调用者的代码位置。

0000000000001149 <test_fun_b>:
    1149:	f3 0f 1e fa          	endbr64 
    114d:	55                   	push   %rbp
    114e:	48 89 e5             	mov    %rsp,%rbp
    1151:	48 83 ec 40          	sub    $0x40,%rsp
    1155:	48 89 7d d8          	mov    %rdi,-0x28(%rbp)
    1159:	48 89 75 d0          	mov    %rsi,-0x30(%rbp)
    115d:	48 89 55 c8          	mov    %rdx,-0x38(%rbp)
    1161:	48 89 4d c0          	mov    %rcx,-0x40(%rbp)
    1165:	48 8b 45 c0          	mov    -0x40(%rbp),%rax
    1169:	48 89 45 e0          	mov    %rax,-0x20(%rbp)
    116d:	48 8b 45 d8          	mov    -0x28(%rbp),%rax
    1171:	48 89 45 e8          	mov    %rax,-0x18(%rbp)
    1175:	48 c7 45 f0 03 00 00 	movq   $0x3,-0x10(%rbp)
    117c:	00 
    117d:	48 c7 45 f8 04 00 00 	movq   $0x4,-0x8(%rbp)
    1184:	00 
    1185:	48 8b 55 f8          	mov    -0x8(%rbp),%rdx
    1189:	48 8b 45 f0          	mov    -0x10(%rbp),%rax
    118d:	48 89 d1             	mov    %rdx,%rcx
    1190:	48 89 c2             	mov    %rax,%rdx
    1193:	48 8d 35 fe 0e 00 00 	lea    0xefe(%rip),%rsi        # 2098 <__func__.2503>
    119a:	48 8d 3d 67 0e 00 00 	lea    0xe67(%rip),%rdi        # 2008 <_IO_stdin_used+0x8>
    11a1:	b8 00 00 00 00       	mov    $0x0,%eax
    11a6:	e8 a5 fe ff ff       	callq  1050 <printf@plt>
    11ab:	48 8b 55 f0          	mov    -0x10(%rbp),%rdx
    11af:	48 8b 45 f8          	mov    -0x8(%rbp),%rax
    11b3:	48 01 c2             	add    %rax,%rdx
    11b6:	48 8b 45 d8          	mov    -0x28(%rbp),%rax
    11ba:	48 01 c2             	add    %rax,%rdx
    11bd:	48 8b 45 e0          	mov    -0x20(%rbp),%rax
    11c1:	48 01 d0             	add    %rdx,%rax
    11c4:	48 89 45 f0          	mov    %rax,-0x10(%rbp)
    11c8:	48 8b 55 f0          	mov    -0x10(%rbp),%rdx
    11cc:	48 8b 45 f8          	mov    -0x8(%rbp),%rax
    11d0:	48 01 c2             	add    %rax,%rdx
    11d3:	48 8b 45 d0          	mov    -0x30(%rbp),%rax
    11d7:	48 01 c2             	add    %rax,%rdx
    11da:	48 8b 45 e8          	mov    -0x18(%rbp),%rax
    11de:	48 01 d0             	add    %rdx,%rax
    11e1:	48 89 45 f8          	mov    %rax,-0x8(%rbp)
    11e5:	90                   	nop
    11e6:	c9                   	leaveq 
    11e7:	c3                   	retq

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

在这里插入图片描述

3 X86_64 函数调用示例及其栈帧示意图

在这里插入图片描述

4 编译和反汇编的命令

4.1 编译的命令

x86_64-linux-gnu-gcc  -Wl,--no-as-needed main.c -o x86_test

4.2 反汇编的命令

若是想把生成的反汇编程序保存的文件可以使用这个反汇编的命令:x86_64-linux-gnu-objdump -S -d x86_test > x86_64_test.S

x86_64-linux-gnu-objdump -S -d x86_test

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

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

相关文章

【工作技术栈】【源码解读】一次springboot注入bean失败问题的排查过程

目录 前言现象分析原因解决方法思考感悟 前言 对这次的过程排查如果要形容的话&#xff0c;我觉得更像是悬疑剧&#xff0c;bean not found 这种错误&#xff0c;已经看腻了&#xff0c;甚至有时候都看不起这种错误&#xff0c;但是似乎这个想法被springboot听见了&#xff0c…

spring-security-源码解析+自定义拓展

1.参考文档 https://docs.spring.io/spring-security/reference/5.7/servlet/architecture.html 1.1.各种filterchain 1.1.1.SecurityFilterChain 1.1.2.springSecurityFilterChain 1.1.3.Security Filters 2.几个重要的注解 2.1.EnableXXX EnableWebMvcSecurity–deprecate…

C语言之初阶总结篇

目录 NO.1 NO.2 NO.3 NO.4 NO.5 NO.6 NO.7 NO.8 NO.9 NO.10 NO.11 NO.12.概念tips NO.13.求最小公倍数 NO.14.最大公因数 NO.15.输入读取字符串 NO.16.倒置字符串 今天是一些C语言题目&#xff0c;最近天气炎热&#xff0c;多喝水。 NO.1 下面程序执行后&am…

浅谈泛在电力物联网、能源互联网与虚拟电厂

导读&#xff1a;从能源互联网推进受阻&#xff0c;到泛在电力物联网名噪一时&#xff0c;到虚拟电厂再次走向火爆&#xff0c;能源领域亟需更进一步的数智化发展。如今&#xff0c;随着新型电力系统建设推进&#xff0c;虚拟电厂有望迎来快速发展。除了国网和南网公司下属的电…

LLMs之Baichuan 2:《Baichuan 2: Open Large-scale Language Models》翻译与解读

LLMs之Baichuan 2&#xff1a;《Baichuan 2: Open Large-scale Language Models》翻译与解读 导读&#xff1a;2023年9月6日&#xff0c;百川智能重磅发布Baichuan 2。科技论文主要介绍了Baichuan 2&#xff0c;一个开源的大规模语言模型&#xff0c;以及其在多个领域的性能表现…

与 vmx86 驱动程序的版本不匹配: 预期为 410.0,实际为 401.0

与 vmx86 驱动程序的版本不匹配: 预期为 410.0&#xff0c;实际为 401.0。 驱动程序“vmx86.sys”的版本不正确。请尝试重新安装 VMware Workstation。 我电脑历史上装过几个版本的vmware workstation: 怀疑是不兼容版本生成的vmx.86.sys 在系统中和该软件冲突&#xff0c;又没…

【完整代码】2023数学建模国赛C题代码--蔬菜类商品的自动定价与补货决策

C 题 蔬菜类商品的自动定价与补货决策 在生鲜商超中&#xff0c;一般蔬菜类商品的保鲜期都比较短&#xff0c;且品相随销售时间的增加而变差&#xff0c; 大部分品种如当日未售出&#xff0c;隔日就无法再售。因此&#xff0c;商超通常会根据各商品的历史销售和需 求情况每天进…

java+ssh+mysql智能化办公管理系统

项目介绍&#xff1a; 本系统为基于jspsshmysql的OA智能办公管理系统&#xff0c;包含管理员、领导、员工角色&#xff0c;功能如下&#xff1a; 管理员&#xff1a;公告信息&#xff1b;工作计划&#xff1b;公司资料&#xff1b;部门管理&#xff1b;员工管理&#xff1b;员…

软件测试/测试开发丨Linux进阶命令

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27139 一、Linux进阶命令学习 curljq 二、curl简介 curl 是一个发送请求数据给服务器的工具 curl支持的协议有&#xff1a;FTP、FTPS、HTTP、HTTP、SFTP…

深度学习推荐系统(七)NFM模型及其在Criteo数据集上的应用

深度学习推荐系统(七)NFM模型及其在Criteo数据集上的应用 1 NFM模型原理及其实现 1.1 NFM模型原理 无论是 FM&#xff0c;还是其改进模型FFM&#xff0c;归根结底是⼀个⼆阶特征交叉的模型。受组合爆炸问题的困扰&#xff0c;FM 几乎不可能扩展到三阶以上&#xff0c;这就不…

sonarqube的基本使用

操作截图 下载一个中文插件。 插件安装成功&#xff0c;提示需要重启sonarqube。 通过maven的命令对代码进行测试 找到maven。 修改apache-maven-3.6.1\setting.xml。 通过以下命令对当前代码进行质量检测。 检测完毕。 回到sonarqube&#xff0c;看到刚刚检测的结果…

【Unity3D赛车游戏优化篇】【十】汽车粒子特效和引擎咆哮打造极速漂移

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

Nginx 学习(十)高可用中间件的配置与实现

一 Keepalived热备 1 概述 调度器出现单点故障&#xff0c;如何解决?Keepalived实现了高可用集群Keepalived最初是为LVS设计的&#xff0c;专门监控各服务器节点的状态Keepalived后来加入了VRRP功能&#xff0c;防止单点故障 2 运行原理 Keepalived检测每个服务器节点状…

湖南省副省长秦国文一行调研考察亚信科技

9月5日&#xff0c;湖南省人民政府党组成员、副省长秦国文一行到亚信科技调研考察&#xff0c;亚信科技高级副总裁陈武主持接待。 图&#xff1a;双方合影 在亚信科技创新展示中心&#xff0c;秦国文了解了亚信科技在5G、算力网络、人工智能、大数据等前沿领域的创新探索&…

LeetCode 865. Smallest Subtree with all the Deepest Nodes【树,DFS,BFS,哈希表】1534

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

AVLTree模拟实现

一、常用的搜索逻辑 1、暴力搜索 O(N) 2、二分搜索 前提是有序&#xff0c;可以先用O(NlogN)排序一次&#xff0c;后续每次查找都是logN。 缺点&#xff1a;快排需要容器有随机访问功能&#xff0c;即为顺序表等。 如果不仅要搜索&#xff0c;还要插入删除&#xff0c;此时…

修复 ChatGPT 发生错误的问题

目录 ChatGPT 发生错误&#xff1f;请参阅如何修复连接错误&#xff01; 修复 ChatGPT 发生错误的问题 基本故障排除技巧 检查 ChatGPT 的服务器状态 检查 API 限制 检查输入格式 清除浏览数据 香港DSE是什么&#xff1f; 台湾指考是什么&#xff1f; 王湘浩 生平 …

如何安装安卓(Android 7.0+)CA根证书

简介 写这个教程时&#xff0c;已经是2023年&#xff0c;现在最新的安卓系已经是Android 13 。从Android7.0以后系统不再信任用户的证书&#xff0c;导致我们在使用一些网络调试工具时非常不便&#xff0c;为了解决这个问题&#xff0c;本教程将教你如何一步步操作&#xff0c…

分类预测 | MATLAB实现PCA-LSTM(主成分长短期记忆神经网络)分类预测

分类预测 | MATLAB实现PCA-LSTM(主成分长短期记忆神经网络)分类预测 目录 分类预测 | MATLAB实现PCA-LSTM(主成分长短期记忆神经网络)分类预测预测效果基本介绍程序设计参考资料致谢 预测效果 基本介绍 MATLAB实现PCA-LSTM(主成分长短期记忆神经网络)分类预测。Matlab实现基于P…

Unity中Shader的屏幕坐标

文章目录 前言一、屏幕坐标1、屏幕像素的坐标2、屏幕坐标归一化 二、在Unity中获取 当前屏幕像素 和 总像素1、获取屏幕总像素,使用_ScreenParams参数2、获取当前片段上的像素怎么使用:在片元着色器传入参数时使用 前言 Unity中Shader的屏幕坐标 一、屏幕坐标 1、屏幕像素的坐…