汇编语⾔开头写C清零是为啥,这个汇编语⾔代码是什么意思?让我们分解⼀下:
.file "delta.c"
编译器使⽤它来告诉您程序集来⾃的源⽂件.这对汇编程序来说意义不⼤.
.ction .rodata
这将开始⼀个新的部分. “rodata”是“只读数据”部分的名称.本节最终将数据写⼊可执⾏⽂件,该数据库将内存映射为只读数据.可执⾏映像的所有“.rodata”页⾯最终都被所有进程共享男人梦见蛇是什么意思
加载图像.
通常,源代码中的任何“编译时常量”都⽆法优化到汇编内部函数中,最终将存储在“只读数据部分”中.
.LC0:
.string "%d"
.LC0“部分是⼀个标签.它提供了⼀个符号名称,它引⽤⽂件中后⾯出现的字节.在这种情况下,”LC0“表⽰字符串”%d“.GNU汇编程序使⽤标记开头的约定带有“L”的被认为是“本地标签”.这具有技术含义,对编写
编译器和链接器的⼈来说⾮常有趣.在这种情况下,编译器使⽤它来引⽤特定⽬标⽂件专⽤的符号.在这种情况下,它表⽰⼀个字符串常量.
云空.text
这将开始⼀个新的部分. “text”部分是存储可执⾏代码的⽬标⽂件中的部分.
.globl main
“.global”指令告诉汇编器将其后⾯的标签添加到⽣成的⽬标⽂件“导出”的标签列表中.这基本上意味着“这是⼀个应该对链接器可见的符号”.例如,“C”中的“⾮静态”函数可以由声明(或包括)兼容函数原型的任何c⽂件调⽤.这就是为什么你可以#include stdio.h然后调⽤printf.编译任何⾮静态C函数时,编译器会⽣成声明指向函数开头的全局标签的程序集.将此与不应链接的内容(如字符串⽂字)进⾏对⽐.⽬标⽂件中的汇编代码仍然需要⼀个标签来引⽤⽂字数据.那些是“本地”符号.
.type main, @function
我不确定GAS(gnu汇编程序)如何处理“.type”指令.但是,这指⽰汇编程序标签“main”是指可执⾏代码,⽽不是数据.
main:
这定义了“main”函数的⼊⼝点.
.LFB0:
这是⼀个“本地标签”,指的是函数的开头.
.cfi_startproc
这是⼀个“调⽤帧信息”指令.它指⽰汇编程序发出矮调格式的调试信息.岳飞的简介
pushl %ebp
这是汇编代码中函数“序⾔”的标准部分.它保存了“ebp”寄存器的当前值. “ebp”或“ba”寄存器⽤于在函数内存储堆栈帧的“基础”. “esp”(“堆栈指针”)寄存器可以在函数内调⽤函数时更改,⽽“ebp”保持固定.始终可以相对于“ebp”访问函数的任何参数.通过ABI调⽤约定,在函数可以修改EBP寄存器之前,它必须保存它,以便在函数返回之前恢复原始值.
.cfi_def_cfa_offt 8
.cfi_offt 5, -8
我没有详细研究过这些,但我相信它们与DWARF调试信息有关.
movl %esp, %ebp
GAS使⽤AT& T语法,这是英特尔⼿册使⽤的语法.这意味着“设置ebp等于esp”.这基本上为函数的其余部分建⽴了“基指针”. .cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
这也是该功能的epilouge的⼀部分.这会对齐堆栈指针,然后从中减去⾜够的空间来容纳函数的所有本地.
movl $4, 28(%esp)
这将32位整数常量4加载到堆栈帧的插槽中.阳光词语
movl $.LC0, %eax
这会将上⾯定义的“%d”字符串常量加载到eax中.
movl 28(%esp), %edx
这将堆栈中偏移量28中存储的值“4”加载到edx.有可能你的代码是在关闭优化的情况下编译的.
movl %edx, 4(%esp)
然后,将值4移动到堆栈上,在调⽤printf时需要的位置.
movl %eax, (%esp)
这会将字符串“%d”加载到调⽤printf时所需的堆栈上的位置.
著名化学家梦见出血call printf
这称为printf.
movl $0, %eax
这将eax设置为0.鉴于下⼀条指令是“leave”和“ret”,这相当于C代码中的“return 0”. EAX寄存器⽤于保存函数的返回值. leave
冰雪飞该指令清除呼叫帧.它将ESP设置回EBP,然后从修改后的堆栈指针中弹出EBP.像下⼀条指令⼀样,这是函数结尾的⼀部分.
.cfi_restore 5
.cfi_def_cfa 4, 4
这是更多DWARF的东西
ret
这是实际的返回指令.它从功能中返回建国公园
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.ction .note.GNU-stack,"",@progbits