程序编码

在编译时指定'-Og'选项让GCC产生符合原始程序结构的机器代码

机器级代码

对C语言隐藏, 但对汇编代码可见的:

输出c源码的机器表示

gcc -Og -S mstore.c

机器代码与反汇编的特性:

关于格式的注解

.file    "mstore.c"
    .text
    .globl    mulstore
    .type    mulstore, @function
mulstore:
.LFB0:
    .cfi_startproc
    pushq    %rbx
    .cfi_def_cfa_offset 16
    .cfi_offset 3, -16
    movq    %rdx, %rbx
    call    mult2
    movq    %rax, (%rbx)
    popq    %rbx
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE0:
    .size    mulstore, .-mulstore
    .ident    "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-36)"
    .section    .note.GNU-stack,"",@progbits

以上是gcc完整生成的.s文件

所有. 开头的是伪指令, 可以忽略

ATT汇编代码格式

.file    "mstore.c"
    .text
    .globl    mulstore
    .type    mulstore, @function
mulstore:
.LFB0:
    .cfi_startproc
    pushq    %rbx
    .cfi_def_cfa_offset 16
    .cfi_offset 3, -16
    movq    %rdx, %rbx
    call    mult2
    movq    %rax, (%rbx)
    popq    %rbx
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE0:
    .size    mulstore, .-mulstore
    .ident    "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-36)"
    .section    .note.GNU-stack,"",@progbits

数据格式

访问信息

x86-64的CPU包含一组16个存储64位的通用目的寄存器

...

栈指针(%rsp)

操作数指示符

数据传送指令

压入栈和弹出栈数据

. 将四字压入栈
pushq S 

. 将四字弹出栈
popq D

%rsp 是栈指针 %rax是返回值

算术和逻辑操作

加载有效地址

. x= y+x*4
leaq    (%rdi,%rsi,4), %rax

一元和二元操作

. 从%edi中减去%esi
subl    %esi, %edi

移位操作

. 将x左移四位
salq    $4, %rax

特殊的算术操作

控制

条件码

读取条件码

跳转指令

用条件控制实现分支控制

cmpq    %rsi, %rdi
        jg      .L4
        movq    %rdi, %rax
        subq    %rsi, %rax
        ret
.L4:
        leaq    (%rdi,%rsi), %rax
        ret

对应的c代码:

if (x > y){
    return x+y;
}else{
    return x-y;
}

用条件传送实现条件分支

分支预测

循环

switch语句

跳转表

过程

运行时栈

转移控制

保存当前程序地址,将程序计数器设置为新过程地址 返回时读取保存的地址,继续执行

数据传送

栈上的局部存储

寄存器中的局部存储空间

递归过程

数组的分配和访问

基本原则

T A[N]

指针运算

&D [ i ] [ j ] = X

D

L(Ci+j)

定长数组

变长数组

异质的数据结构

都是对地址进行偏移得到的

在机器级程序中将控制与数据结合起来

理解指针

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值

GDB调试器

UNIX及UNIX-like下的调试工具

内存越界引用和缓冲区溢出

对抗缓冲区溢出攻击

变长帧

浮点代码

%ymm0 ~ %ymm15

浮点传送和转换操作

指令 目的 描述
vmovss $M_{32}$ X 传送单精度数
vmovss X $M_{32}$ 传送单精度数
vmovsd $M_{64}$ X 传送双精度数
vmovsd X $M_{64}$ 传送双精度数
vmovaps X X 传送对齐的封装好的单精度数
vmovapd X X 传送对齐的封装好的双精度数
指令 目的 描述
vcvttss2si $X/M_{32}$ $R_{32}$ 用截断的方法把单精度数转换成整数
vevttsd2si $X/M_{64}$ $R_{32}$ 用截断的方法把双精度数转换成整数
vcvttss2siq $X/M_{32}$ $R_{64}$ 用截断的方法把单精度数转换成四字整数
vcvttsd2siq $X/M_{64}$ $R_{64}$ 用截断的方法把双精度数转换成四字整数
指令 源1 源2 目的 描述
vcvtsi2ss $M_{32}/R_{32}$ X X 把整数转换成单精度数
vcvtsi2sd $M_{32}/R_{32}$ X X 把整数转换成双精度数
vcvtsi2ssq $M_{64}/R_{64}$ X X 把四字整数转换成单精度数
vcvtsi2sdq $M_{64}/R_{64}$ X X 把四字整数转换成双精度数

过程中的浮点代码

使用XMM寄存器来传递浮点参数

浮点运算操作

单精度 双精度 效果 描述
vaddss vaddsd D←S2+S1 浮点数加
vsubss vsubsd D←S2-S1 浮点数减
vmulss vmulsd D←S2XS1 浮点数乘
vdivss vdivsd D←S2/S1 浮点数除
vmaxss vmaxsd D←max(S2,S1) 浮点数最大值
vminss vminsd D←min(S2,S1) 浮点数最小值
sgrtss sqrtsd $D←\sqrt{S1}$ 浮点数平方根

定义和使用浮点常数

浮点操作不能把立即数作为操作数

编译器必须为所有浮点常量初始化存储空间

在浮点代码中使用位级操作

单精度 双精度 效果 描述
vxorps vorpd D←S2·S1 位级异或(EXCLUSIVE-OR)
vandps andpd D←S2&S1 位级与(AND)

浮点比较操作