跳至主要內容

汇编

Mr.Lexon大约 4 分钟os

汇编

流程

.file   "example.c" #定义文件名称  
        .text #定义文件类型  
        .globl  add_a_and_b #定义变量名称为全局变量名称  
        .type   add_a_and_b, @function #定义类型为函数  
add_a_and_b: #定义  
.LFB0: #局部函数块的开始.lfb[x] 这里[x]指代的是区域编号  
        .cfi_startproc #起始调用帧指令  
        pushq   %rbp # pushq为指令 %rbp为寄存器 目的是将寄存器压入栈中  
        .cfi_def_cfa_offset 16 #定义当前堆栈指针  
        .cfi_offset 6, -16 #定义堆栈偏移量 目标是6号寄存器空间 -16是堆栈指针  
        movq    %rsp, %rbp #将%rbq寄存器移动到%rsp中  
        .cfi_def_cfa_register 6 #定义当前指针使用的寄存器 在这里6号寄存器指的是%rbp  
        movl    %edi, -4(%rbp) #将%edi寄存器的值移动到%rbp偏移4个字节的内存地址位置  
        movl    %esi, -8(%rbp) #将%esi寄存器的值移动到%rbp偏移8个字节的内存地址位置  
        movl    -4(%rbp), %edx #将%rbp寄存器偏移4个字节的值移动到%edx的内存地址位置  
        movl    -8(%rbp), %eax #将%rbp寄存器偏移8个字节的值移动到%eax的内存地址位置  
        addl    %edx, %eax #把两个寄存器的值相加  
        popq    %rbp #rbq退出堆栈  
        .cfi_def_cfa 7, 8 #在当前堆栈定义七号寄存器,8个字节的偏移量  
        ret #函数返回指令  
        .cfi_endproc #标记函数结束  
.LFE0: #定义局部函数块结束  
        .size   add_a_and_b, .-add_a_and_b #指定函数大小 首先定义符号为函数名,其次返回当前位置,那么就可以得到函数大小了  
        .globl  main #声明全局变量 这里则是声明入口变量  
        .type   main, @function #将main定义为函数  
main:  
.LFB1:#1号局部函数域  
        .cfi_star tproc #声明堆栈开始  
        pushq   %rbp #将寄存器%rbp压入堆栈中  
        .cfi_def_cfa_offset 16 #定义堆栈大小为16个字节  
        .cfi_offset 6, -16 #定义偏移量  
        movq    %rsp, %rbp #同上  
        .cfi_def_cfa_register 6 #注册6号寄存器至堆栈中  
        movl    $3, %esi #将立即数3添加到%esi  
        movl    $2, %edi #将立即数2添加到%edi中  
        call    add_a_and_b #函数调用  
        popq    %rbp #%rbp退出函数  
        .cfi_def_cfa 7, 8 #定义7号寄存器,8个字节的偏移量  
        ret #函数变量  
        .cfi_endproc #函数结束  
.LFE1:#1号函数域结束  
        .size   main, .-main #定义函数大小  
        .ident  "GCC: (Debian 10.2.1-6) 10.2.1 20210110" #定义程序元信息  
        .section        .note.GNU-stack,"",@progbits #定义新的代码段或数据段

gpt解释:

这段代码的大致结构是:

  1. 定义文件信息(.file.ident

  2. 定义代码段(.text

  3. 声明全局变量 add_a_and_b 为函数类型

  4. 定义函数 add_a_and_b

  5. 定义局部函数块 .LFB0

  6. 一系列汇编指令用于设置堆栈帧和执行函数的操作

  7. .cfi_endproc 标记函数结束

  8. 使用 .size 定义函数大小

  9. 声明全局变量 main 为函数类型

  10. 定义函数 main

  11. 定义局部函数块 .LFB1

  12. 一系列汇编指令用于设置堆栈帧、调用函数和执行函数的操作

  13. .cfi_endproc 标记函数结束

  14. 使用 .size 定义函数大小

  15. 定义程序元信息

  16. 定义新的代码段(.note.GNU-stack

根据上下文,第 34 行和第 35 行的代码针对立即数的作用如下:

34 行:movl $3, %esi 这一行的作用是将立即数值 3 移动到寄存器 %esi 中。在 x86 汇编中,$ 符号用于表示立即数(即直接的数值),这表示不是从内存中读取数据,而是直接将数值加载到寄存器。因此,movl $3, %esi 将数值 3 直接加载到 %esi 寄存器,这里可能表示一个参数或临时变量的赋值。

35 行:movl $2, %edi 这一行的作用是将立即数值 2 移动到寄存器 %edi 中。同样,$ 符号表示立即数,这里将数值 2 直接加载到 %edi 寄存器,可能表示另一个参数或临时变量的赋值。 综合来看,这两行指令在上下文中可能是为了准备函数 add_a_and_b 的参数。它们将数值 3 和 2 分别加载到 %esi%edi 寄存器,以便在后续的函数调用中使用。根据上下文,这可能是将这两个值传递给 add_a_and_b 函数进行计算。

总结

  1. 定义文件信息和元信息。
  2. 定义代码段和全局变量。
  3. 定义函数 add_a_and_b
    • 设置堆栈帧并保存寄存器。
    • 计算两个参数之和。
    • 恢复堆栈和寄存器状态。
    • 返回结果。
  4. 定义函数 main
    • 设置堆栈帧并保存寄存器。
    • 设置函数参数。
    • 调用函数 add_a_and_b
    • 恢复堆栈和寄存器状态。
    • 返回。
  5. 结束程序。
上次编辑于:
贡献者: Lexon