丽水专业网站建设公司,襄阳公司网站建设,360搜索入口,网站关键词优化哪家正规Lecture 05 Machine Level Programming I Basics 机器级别的程序 文章目录 Lecture 05 Machine Level Programming I Basics 机器级别的程序intel 处理器的历史和体系结构芯片的构成AMD 公司(Advanced Micro Devices#xff0c;先进的微型设备) C, 汇编, 机器代码定义汇编/机器…Lecture 05 Machine Level Programming I Basics 机器级别的程序 文章目录 Lecture 05 Machine Level Programming I Basics 机器级别的程序intel 处理器的历史和体系结构芯片的构成AMD 公司(Advanced Micro Devices先进的微型设备) C, 汇编, 机器代码定义汇编/机器代码C程序转换为目标代码编译为汇编代码汇编的特性数据类型汇编的特性操作机器指令解析示例反汇编代码反汇编器 objdump反汇编 gdb 汇编基础寄存器操作数移动寄存器移动数据 mov简单的内存地址模式地址模式示例 实际中交换方法 完整的内存地址模式地址计算指令 lea示例 算术运算 和 逻辑运算示例 《深入理解计算机系统》书籍学习笔记 intel 处理器的历史和体系结构
复杂指令集电脑complex instruction set computer精简指令集电脑 Reduced Instruction Set Computers(RISC)
芯片的构成
broadwell 型号模型
一个芯片有多个内核。芯片的边缘有许多接口连接其余的设备。DDR是连接到主存储器的方式即所谓的DRAM 动态 RAM。PCI 是与外围设备的连接。SATA 是与不同类型盘的连接。以太网接口连接到一个网络。
因此所有集成到单个芯片上的不仅仅是处理器本身而是很多逻辑单元粘在一起所组成的更大的系统。
AMD 公司(Advanced Micro Devices先进的微型设备)
紧随Intel公司的后面相对落后一点但是价格便宜。
C, 汇编, 机器代码
定义
架构ISA: Instruction set architecture, 指令集架构 需要理解或编写汇编/机器代码的处理器设计部分。
指令和指令集这是编译器的目标为你提供一系列指令告诉机器确切地做什么。 发明硬件地人们想到了各种巧妙地实施指令方式其中一些非常快但需要大量地硬件有些很慢但根本不需要太多硬件。因此他们设法创建了这种称为指令集架构地抽象。 编译器地目标就是他们。 而如何最好地实现它是硬件研究者地工作。 微架构 对架构的补充。 低级别地东西如何实现它被称为微结构 代码形式 机器代码 处理器执行的字节级程序。汇编代码 机器代码的文本表示形式。
一些指令架构集 * intel: x86IA32, Itaniu, x86-64. * ARM Acorn RISC Machine橡树种子精简指令机器 ARM指令体系结构。 他们向公司出售使用其涉及的许可权力他们真正卖的是知识产权而不是芯片。
汇编/机器代码 处理器部分 PC: Program counter 程序计数器 存储下一条指令的地址。 Register file 寄存器文件寄存器集 大量使用的程序文件 Condition Code 条件码 状态寄存器。 存储最近的算术或者逻辑运算的结果状态产生的值为0为正值或者负值 用于实现条件分支
存储部分
Memory 内存 字节可寻址数组 代码和用户数据 用于支持程序的堆栈
内存是你可以逻辑地认为只是一个字节数组这就是机器程序员所看到的。 如前所述它实际上是一种用不同方式实现虚构对象操作系统和硬件之间存在一种协作他们称之为虚拟内存使处理器上运行的每个程序看起来拥有自己独立的字节数组它们可以访问。即使它们实际上在物理内存内部都是共享这些字节数组。
C程序转换为目标代码
你有一个程序是c程序包含多个文件将使用一些库代码。 编译过程将你写的代码内容转换为机器代码并将其与编译后的编译器为库生成合并代码最终生成一个文件可执行文件。
步骤
文本形式的c程序文件通过编译器生成文本形式的汇编代码汇编代码通过汇编器生成二进制的目标程序字节形式通过链接器将不同的文件融合在一起包含你单独的文件已编译版本和库代码,最终生成一个可执行程序。实际有一些库在程序首次开始执行时动态导入的。
汇编器
将.s汇编文件转换为.o目标文件二进制编码指令几乎完整的可执行代码映像缺少不同文件中代码之间的链接链接器来完成
链接器
解决文件之间的引用与静态运行时run-time库结合使用例如malloc(),printf()等一些库是动态链接的。当程序开始执行时链接。
编译为汇编代码
c编码
long plus(long x, long y);void sumstore(long x, long y, long *dest)
{long t plus(x,y);*dest t;
}汇编码 运行命令,生成汇编代码: gcc -Og -S sum.c
-Og: O optimize 优化。指定编译器做什么样的优化的规范。 如果不给它指示它将生成完全未经过优化的代码实际上很难读该代码它的运行过程非常繁琐。 -O1: 这是过去打开优化器的过程gcc 做了很多优化为了优化目的使代码很难理解。 因此最近几代GCC中的一个出现这个名未g的调式级别 .file sum.c.text.globl sumstore.type sumstore, function
sumstore:
.LFB0:.cfi_startprocpushq %rbx.cfi_def_cfa_offset 16.cfi_offset 3, -16movq %rdx, %rbxcall plusmovq %rax, (%rbx)popq %rbx.cfi_def_cfa_offset 8ret.cfi_endproc
.LFE0:.size sumstore, .-sumstore.ident GCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-15.0.2).section .note.GNU-stack,,progbits以句点开头的.这些实际上指示它们是别的东西它们与某些被需要的信息有关要给调试器提供使他能够定位程序的各个部分一些信息告诉链接器这是一个全局定义的函数还有一些其他信息我们暂时不需要考虑忽视这些信息是它们更具有可读性。
百分号前缀%: 寄存器名称 pushq: 将东西推到栈上。 movq: 将它从一个地方复制到另一个地方。 call调用一些过程 popq: 和pushq相对的命令从栈中取出东西。 ret特定函数的返回。
每一行都是一个指令用文本写的每条都将变成目标代码文件中的一个实际指令。
汇编的特性数据类型 整型数据类型1248 字节 在整数数据类型它们不区分符号与无符号的存储方式。 地址和指针都是以数字形式存储在计算机中。 浮点数数据类型4810 字节 代码一系列指令编码的字节序列 没有聚合类型数组和结构体 只是在内存中巧妙地分配了字节
汇编的特性操作 实现算术运算方法通过寄存器和内存数据 在内存和寄存器之间转换数据 从内存中将数据加载到寄存器将寄存器的数据存储到内存 转移控制 非条件跳转 到/从 过程条件分支
机器指令解析示例
c代码 将t的值存存储到dest指定的位置。
*dest t汇编代码
movq %rax, (%rbx)移动8字节值到内存4字 操作数 * t: 寄存器 %rax* dest: 寄存器 %rbx* *dest: 内存 M[%rbx]目标代码 3 字节指令。
0x40059e: 48 89 03存储地址 0x40059e
拓展 变量的所有名称在汇编代码级别机器代码级别完全丢失东西都变成了寄存器和内存中的某个位置。
反汇编代码
先生成目标代码gcc -Og sum.c -c
反汇编器 objdump
objdump -d sum.o用于检查目标代码分析一系列指令的代码产生汇编代码的进士索引可以在a.out(可执行文件) 或者 .o(目标文件)运行
反汇编得到的汇编代码
0000000000000000 sumstore:0: 53 push %rbx1: 48 89 d3 mov %rdx,%rbx4: e8 00 00 00 00 callq 9 sumstore0x99: 48 89 03 mov %rax,(%rbx)c: 5b pop %rbxd: c3 retq反汇编 gdb
gdb 是一个非常强大的调试程序。 你可以单步检查程序并对其中的程序进行一些操作如果它的源代码可用可以用它来调试。
安装gdb:
yum install gdb调试程序
gdb sum
disassemble sumstoregdb 作用:
可以单步检查程序并对其中的程序进行一些操作。源代码调试可以用来反汇编
反汇编是一种可以用作任何逆向工程工具的工具。
反汇编Microsoft Word Microsoft Word 和其他程序一样只是一个可执行文件而那个可执行文件只是一堆编码指令的字节。 如果你能找到文件位置应用程序的实际可执行文件的位置。
objdump -d WINWORD.EXE汇编基础寄存器操作数移动
寄存器 如果使用的是%r 开头的寄存器你会得到64位。 如果使用的是 %e 开头的寄存器版本你会得到32位。 %e 版本指示较大%r 实体低32位。 实际用法更多你也可以引用低阶16位和低8位。
从IA32 到 x86-64的变化之一是将寄存器数量增加一倍。
移动数据 mov
指令
movq Source, Dest操作数类型 立即数 Immediate: 整型常数 示例$0x400, $-533 和C常量但是以$为前缀 编码1,2,4字节 寄存器 Register 16个寄存器中的一个 示例%rax, %r13 %rsp 保留自己的特殊用途 其他的寄存器有特殊用途对于特殊指令。 内存 Memory: 在寄存器给出的地址上有8个连续字节的内存 最简单的示例(%rax) 各种其他“地址模式”
注意事项
将立即值作为目的地没有意义它是常数出于硬件设计者的方便它不允许你直接从一个内存位置复制到另一个内存位置。 你需要两个指令一个从内存中读取值将其复制到寄存器。第二个是在寄存器中取值并将其写入内存。
q: quad 四字节
简单的内存地址模式
正常模式
(R) Mem[Reg[R]]寄存器R指定内存地址。
示例
movq (%rcx), $rax位移模式Displacement
D(R) Mem(Reg[R] D)寄存器R指定内存区域开始的位置。 常量位移D指出偏移量。
示例
movq 8(%rbp), %rdx地址模式示例
c语言代码
void swap(long *xp, long*yp)
{long t0 *xp;long t1 *yp;*xp t1;*yp t0;
}汇编代码 运行命令gcc -S -Og swap.c
swap:movq (%rdi), %rax # t0 *xpmovq (%rsi), %rdx # t1 *ypmovq %rdx, (%rdi) # *xp t1movq %rax, (%rsi) # *yp t0ret寄存器对应的值
%rdi xp%rsi yp%rax t0%rdx t1
操作流程
实际中交换方法
实际中我们只会使用中间变量来进行交换
void swap(long *xp, long*yp)
{long t0 *xp;*xp *yp;*yp t0;
}我们用命令得到汇编代码会发现和上面的汇编代码是一样的。
为什么 回到前面我们所说的mov指令。它不允许你直接从一个内存位置复制到另一个内存位置。 你需要两个指令一个从内存中读取值将其复制到寄存器。第二个是在寄存器中取值并将其写入内存。
所以 *xp *yp的执行就是
long t1 *yp
*xp t1所以实际中我们这么只使用一个中间变量进行操作和使用两个中间变量进行操作并没有多大影响。 只是代码更简洁一点而已。
完整的内存地址模式
常用形式
D(Rb, Ri, S) Mem[Reg[Rb] S*Reg[Ri]D]D: Displacement, 位移。恒定位移 124 字节 Rb: Base Register, 基础寄存器。 16个寄存器中的一个。 Ri: Index Register, 索引寄存器。特别是%rsp。 S: Scale, 缩放。 1248 固定是这些数。
这是实现数组索引的一种自然方式。 如果这是一组数组索引我们必须通过我的数据类型的字节数来缩放索引值如果它是一个int我们必须将索引缩放四倍如果它是long我们必须将其缩放八倍。这就是S必须是1,2,4,8这些数
特殊形式 缺失其中一些项。
(Rb,Ri) Mem[Reg[Rb]Reg[Ri]] D(Rb,Ri) Mem[Reg[Rb]Reg[Ri]D] (Rb,Ri,S) Mem[Reg[Rb]S*Reg[Ri]] 示例
0xf000 1111 0000 0000 0000 2 * 0xf000 二进制左移1位 0001 1110 0000 0000 0000 0x1e000 2 * 0xf000 2 * 15 30 0x1e000
地址计算指令 lea
lea : load effective address, 加载有效地址。 对上面内存地址模式的运用。
leaq Src, DstSrc : 地址模式表达式 Dst : 设置dst为用表达式表示的地址
使用 计算没有内存引用的地址 例如p x[i] 计算算术表达式 x k*y k 1,2,4,或8
示例
c 代码
long m12(long x)
{return x*12;
}汇编码 教程中得到
leaq (%rdi,%rdi,2), %rax # t - xx*2
salq $2, %rax # return t2我得到
leaq (%rdi,%rdi,2), %rdx
leaq 0(,%rdx,4), %rax算术运算 和 逻辑运算
两个操作数的指令
格式 计算
addq Src,Dest Dest Dest Src
subq Src,Dest Dest Dest - Src
imulq Src,Dest Dest Dest * Src
salq Src,Dest Dest Dest Src
sarq Src,Dest Dest Dest Src
shrq Src,Dest Dest Dest Src
xorq Src,Dest Dest Dest ^ Src
andq Src,Dest Dest Dest Src
orq Src,Dest Dest Dest | Src一个操作数的指令
incq Dest Dest Dest 1
decq Dest Dest Dest - 1
negq Dest Dest - Dest
notq Dest Dest ~Dest注意事项
操作数的顺序与你期望他们的顺序相反源操作数在前目的操作数在后面。
示例
c代码
long arith(long x, long y, long z)
{long t1 xy;long t2 zt1;long t3 x4;long t4 y * 48;long t5 t3 t4;long rval t2 * t5;return rval;
} 汇编代码
leaq (%rdi,%rsi), %rax # t1
addq %rdx, %rax # t2
leaq (%rsi,%rsi,2), %rdx # 3y
salq $4, %rdx # t4 4 * 3y
leaq 4(%rdi,%rdx), %rcx # t5
imulq %rcx, %rax # rval寄存器对应的变量
%rdi x
%rsi y
%rdx z
%rax t1,t2, rval
%rdx t4
%rcx t5《深入理解计算机系统》书籍学习笔记
《深入理解计算机系统》学习笔记 - 第一课 - 课程简介 《深入理解计算机系统》学习笔记 - 第二课 - 位字节和整型 《深入理解计算机系统》学习笔记 - 第三课 - 位字节和整型 《深入理解计算机系统》学习笔记 - 第四课 - 浮点数 《深入理解计算机系统》学习笔记 - 第四课 - 机器级别的程序