编译选项知识
-Og:这是 GCC 和 Clang 编译器提供的优化选项之一。-Og 的含义是"优化级别为 g",其中的 "g" 代表了"g优化"。这个选项的作用是启用一些基本的优化 ,以尽量保持生成的代码易读易调试。它通常会保留变量名和源代码结构,以方便调试。但是,它并不会进行像 -O1、-O2 或 -O3 这样的更加激进的优化。因此,当你希望在调试时仍然能够方便地查看源代码和变量名时,可以使用 -Og。
-g:这是另一个编译选项,用于生成调试信息。使用 -g 选项编译程序会在生成的可执行文件中包含调试信息,包括源代码中的行号、变量名等,以便在调试器中进行调试时能够准确定位到源代码的位置。-g 选项通常与其他优化选项一起使用,以便在优化后的代码中进行调试。
-S: 生成汇编
-c: 生成目标文件
汇编代码
- 不区分有符号和无符号整数
- 点开头的都是汇编代码中的注释
gdb
- x:显示
- xb: 16进制格式,举例,x/14xb 结果会显示14个字节(以16进制显示,53, 。。。5b, c3)
- i r: 显示所有寄存器状态,info registers rax查看具体的某个寄存器信息
objdump
- -d: 可以将目标文件反汇编成汇编语言
- 会省略一些指令结尾的'q',不过会给call和ret添加q后缀
- nop指令主要是为了内存对其,使得下一个代码块的首地址为16的整数倍
通用寄存器
- rip寄存器是存放pc, 也就是下一次执行代码的地址
- 由于架构升级,所以寄存器的开头rax->eax->ax->al,对应大小:8->4->2->1
- 生成1字节或者2字节的指令会保持剩下的字节不变,比如movb $-1 %al, 那么rax中只有al位置为FF,其他不变,movw同理
- 生成4字节的指令会把高位4字节置为0,比如movl $-1 %eax, 那么eax中为F,rax中其他位置为0
操作数指示符
- 立即数用表示,如-577或者$0x1F
- 寄存器用%提取,如%rax
- 内存地址的值,直接写地址0x104
数据传送指令
-
movb, movw, movl, movq ,不能输入和输出全是内存,简单解释两个内存数据搬移,必须经过寄存器
-
movabsq 和 movq 都是 x86/x86-64 汇编语言中的指令,用于将数据从一个位置移动到另一个位置。它们之间的主要区别在于处理数据的方式。
movabsq 指令:
- movabsq 是一个较新的指令,引入了 x86-64 架构(即 64 位处理器体系结构)。
- 它用于将 64 位立即数(immediate)加载到 64 位寄存器中。
- 该指令的操作数是一个立即数,表示为立即数前缀 0x,后面跟着一个 64 位的立即数值。
- movabsq 不会对目标寄存器进行符号扩展。
movq 指令:
- movq 指令用于将数据从一个位置移动到另一个位置,通常用于寄存器之间的数据传输,也可以用于内存和寄存器之间的数据传输。
- 它可以用于处理 64 位数据,但也可以用于处理 32 位或 16 位数据,取决于操作数的大小。
- 如果源操作数是 64 位的,则将其完全复制到目标操作数,否则进行符号扩展或零扩展,以适应目标操作数的大小。
示例:
假设我们有一个 64 位立即数 0x123456789abcdef0,我们要将它加载到 rax 寄存器中。
使用 movabsq 指令:
movabsq $0x123456789abcdef0, %rax
使用 movq 指令:
movq $0x123456789abcdef0, %rax
在这两个例子中,我们将立即数 0x123456789abcdef0 移动到 rax 寄存器中。使用 movq 指令时,如果立即数没有 64 位,则会对其进行符号扩展或零扩展。(书上说是符号扩展, 实测也是)
-
MOVZ和MOVS分别代表0扩展和符号扩展,其中没有movzlq, 因为可以利用movl和通用寄存器的规则达到这样的效果,省一条指令
-
cltq 这个没有显示指示出源和目的,其实等于movslq %eax, %rax, 注意是符号扩展
-
pushq, popq 压入四字或者弹出四字,popq的话不会删除栈的值,只会更改%rsp