Machine-Level Programming 笔记(更新中)
Machine-Level Programing
Basic
现在的主流架构有 x86 系列和 arm 系列,前者是 CISC(复杂指令),后者是 RISC(精简指令)。
定义: ISA instruction set architecture 指令集:一组微指令的集合。
数据类型
integer : 存放地址和整数,大小有 \(1,2,4,8 \space \mathrm{bytes}\)。
floating number : \(4, 8, 10 \space \mathrm{bytes}\) 。
编译过程和简单的工具
c program 经过 compiler 编译成 asm program(汇编代码),再经 gcc/as 拼接成目标代码。
gcc 的选项 -S 将编译过程停留在 asm 级别,但是通常,即便是 -O1 也会追求比较强的优化使得 asm 的可读性比较差,而不经优化的代码过于复杂, -Og 是一种折衷的方案,有比较强的可读性,对于 debug 以及观察汇编比较友好。
gcc sample.c -S -Og -o sample.s
对于目标代码,通过反汇编(disassembling)可以得到汇编代码。
常见的 disassembler 有:
-
objdump
objdumo -d xx.o将在屏幕上打印反汇编的结果,通常可以将这个结果重定向到一个文件存下来。
-
gdb
gdb 打开文件后,用命令:
disassemble xx.o即可得到反汇编代码。
寄存器
x86-64 中共有 16 个寄存器。
| 64位版本 | 32位版本 | 64位版本 | 32位版本 |
|---|---|---|---|
| %rax | %eax | ||
| %rbx | %ebx | ||
| %rcx | %ecx | ||
| %rdx | %edx | ||
| %rsi | %esi | ||
| %rdi | %edi | ||
| %rsp | %esp | ||
| %rbp | %ebp |
通过 %ax 可以访问到 16 位版本,并且可以访问其高 8 位 %ah 和低 8 位 %al。
指令
移动
move指令,格式
movq Source, Dest
其中 q 代表 quad word(64位), 对应的有 l 代表 long word(32位)。
参数类型:
Source 的参数可以为 register, memory 和 immediate number。
立即数的表示方式: $0x01, $-147。
Dest 的参数,当 Source 为 register 或者 immediate number 的时候,可以为 register 或者 memory;Source 为 memory 时只能是 register (即不能从 memory 移动到 memory)。
例子
| movq Src, Dest | C analog |
|---|---|
movq $0x4, %rax |
temp = 0x4 |
movq $-147, (%rax) |
*temp = -147 |
movq %rax, %rbx |
temp2 = temp1 |
movq %rax (%rdx) |
*p = temp |
movq (%rax) %rdx |
temp = *p |
内存寻址
memory addressing
general type:
D(Rb, Ri, s)
参数要求:
Rb :base register,can be any one of the 16 registers.
Ri:Index Register ,除 %rsp 以外的寄存器。
s:Scale,规模。
实际结果:\(Rb + Ri * s + D\)。
其中 Rb 和 Ri 为寄存器的值, s 和 D 为常量。
特殊形式:
(R) ,D(R) , (Rb, Ri), D(Rb, Ri) , (Rb, Ri, s) 。
前两种比较常用。
地址计算指令
名为 lea 的指令。
格式 leaq Src, Dest 。
将 Src 所在的地址赋值给 Dest,c analog: dest = &src 。
常用于优化计算(lea 使用单独电路,也没有寄存器开销,较快):
x * 12 优化为这个样子:
leaq (%rax, %rax, 2), %rax ;; %rax *= 3
salq $2, %rax ;; %rax <<= 2
也就是把地址运算的值赋回去,运算的量其实都是数值量。
地址数值计算指令
2元
| operation | operand | |||
|---|---|---|---|---|

浙公网安备 33010602011771号