计算机组成原理 - 程序如何执行 (学习笔记)

指令和运算 – 指令

  • CPU最底层的运算单元 – 计算机指令集, instruction set, 亦是机器语言

  • 程序 – 也是数据 – 位于存储器 ( 存储程序型计算机)

  • 程序如何成为计算机可以识别并且进行执行的代码?代码 – 经过编译 compile --> 汇编语言 ASM Assembly Language-- 经过汇编器 Assembler --> 机器语言 machine language

  • Linux c,c程序,先转变为汇编语言,再转变为机器语言

gcc -g -c test.c
objdump -d -M intel -S test.o

指令的类型

  • 算术类指令
  • 数据传输类指令
  • 逻辑类指令
  • 条件分支类指令
  • 无条件跳转指令

MIPS 指令集

  • 一个指令最底层是如何表达的? 相当于是一串二进制码,里面有些位数代表指令的类型,有些位数代表指令具体的执行逻辑,操作符,操作数之类。
  • MIPS 的指令是一个 32 位的整数,高 6 位叫操作码(Opcode),也就是代表这条指令具体是一条什么样的指令,剩下的 26 位有三种格式,分别是 R、I 和 J。
  • R 指令是一般用来做算术和逻辑操作
    I 指令,则通常是用在数据传输、条件分支
    J 指令就是一个跳转指令

CPU如何执行指令

  • CPU = 一堆寄存器 ; 寄存器 – 触发器(Flip-Flop)或者锁存器(Latches)
  • N 个触发器或者锁存器,就可以组成一个 N 位(Bit)的寄存器,能够保存 N 位的数据

寄存器类型

  • PC 寄存器(Program Counter Register),我们也叫指令地址寄存器(Instruction Address Register)。
  • 指令寄存器(Instruction Register),用来存放当前正在执行的指令。
  • 条件码寄存器(Status Register),比如溢出,进位这些标识符
  • 整数寄存器、浮点数寄存器、向量寄存器和地址寄存器等等。有些寄存器既可以存放数据,又能存放地址,我们就叫它通用寄存器。

if…else – 示例,具体的c程序转化成汇编码

 
    if (r == 0)
  3b:   83 7d fc 00             cmp    DWORD PTR [rbp-0x4],0x0
  3f:   75 09                   jne    4a <main+0x4a>
    {
        a = 1;
  41:   c7 45 f8 01 00 00 00    mov    DWORD PTR [rbp-0x8],0x1
  48:   eb 07                   jmp    51 <main+0x51>
    }
    else
    {
        a = 2;
  4a:   c7 45 f8 02 00 00 00    mov    DWORD PTR [rbp-0x8],0x2
  51:   b8 00 00 00 00          mov    eax,0x0
    } 

除了简单地通过 PC 寄存器自增的方式顺序执行外,条件码寄存器会记录下当前执行指令的条件判断状态,然后通过跳转指令读取对应的条件码,修改 PC 寄存器内的下一条指令的地址,最终实现 if…else 以及 for/while 这样的程序控制流程

关于函数 – CPU如何执行相关指令

  • add 函数编译之后,代码先执行了一条 push 指令和一条 mov 指令
  • 在函数执行结束的时候,又执行了一条 pop 和一条 ret 指令
  • 这四条指令的执行,压栈(Push)和出栈(Pop)操作。
  • 整个函数 A 所占用的所有内存空间,就是函数 A 的栈帧(Stack Frame)
  • rbp 是 register base pointer 栈基址寄存器(栈帧指针),指向当前栈帧的栈底地址
  • rsp 是 register stack pointer 栈顶寄存器(栈指针),指向栈顶元素

编译、链接和装载:拆解程序执行

add_lib.o 以及 link_example.o 目标文件 – 通过链接器(Linker)把多个目标文件以及调用的各种函数库链接起来 – 可执行文件(Executable Program)

  • 第一个部分由编译(Compile)、汇编(Assemble)以及链接(Link)三个阶段组成。 --> 一个可执行文件。
  • 第二部分,我们通过装载器(Loader)把可执行文件装载(Load)到内存中

ELF(Execuatable and Linkable File Format),可执行与可链接文件格式

ELF 文件格式把各种信息,分成一个一个的 Section 保存起来。

  • text Section,也叫作代码段或者指令段(Code Section)
  • data Section,也叫作数据段(Data Section)
  • .rel.text Secion,叫作重定位表(Relocation Table)
  • .symtab Section,叫作符号表(Symbol Table)

程序装载到内存
实际的可执行文件:ELF文件,和PE文件

  • 在内存里,找到一段连续的内存空间,然后分配给装载的程序,然后把这段连续的内存空间地址,和整个程序指令里指定的内存地址做一个映射。
  • 指令里用到的内存地址叫作虚拟内存地址(Virtual Memory Address),实际在内存硬件里面的空间地址,我们叫物理内存地址(Physical Memory Address)
  • 分段(Segmentation),系统分配出来的那个连续的内存空间
  • 内存碎片(Memory Fragmentation)
  • 内存交换(Memory Swapping),通过和硬盘进行IO,倒腾出位置,解决内存碎片
  • 内存分页:分页是把整个物理内存空间切成一段段固定尺寸的大小。 进行程序加载,内存交换的最小单元,这样就可以大大减少IO的数据量,减少因为程序交换停顿的时间。
  • 缺页错误(Page Fault):当要读取特定的页,却发现数据并没有加载到物理内存里的时候

动态链接

  • 期望:同样功能的代码,在不同的程序里面,不需要各占一份内存空间
  • 共享库:Windows 下,.dll 文件, Dynamic-Link Libary(DLL,动态链接库)。Linux 下,.so 文件,Shared Object(一般我们也称之为动态链接库)
  • PLT,程序链接表(Procedure Link Table)
  • 全局偏移表(GOT,Global Offset Table)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值