只是不愿随波逐流 ...|

lidongdongdong~

园龄:2年7个月粉丝:14关注:8

1、基础汇编

汇编语言

1、基础知识

(1)汇编指令是机器指令的助记符,同机器指令一一对应
(2)每一种 CPU 都有自己的汇编指令集
(3)CPU 可以直接使用的信息在存储器中存放
(4)在存储器中指令和数据没有任何区别,都是二进制信息
(5)存储单元从零开始顺序编号
(6)一个存储单元可以存储 8 个bit,即 8 位二进制数
(7)1 Byte = 8 bit、1 KB = 1024 B、1 MB = 1024 KB、1 GB = 1024 MB
(8)每一个 CPU 芯片都有许多管脚,这些管脚和总线相连,也可以说,这些管脚引出总线
一个 CPU 可以引出 3 种总线的宽度标志了这个 CPU 的不同方面的性能
地址总线(AB)的宽度决定了 CPU 的寻址能力
数据总线(DB)的宽度决定了 CPU 与其他器件进行数据传送时的一次数据传送量
控制总线(CB)的宽度决定了 CPU 对系统中其他器件的控制能力
内存地址空间
最终运行程序的是 CPU,我们用汇编语言编程的时候,必须要从 CPU 的角度考虑问题
对 CPU 来讲,系统中的所有存储器中的存储单元都处于一个统一的逻辑存储器中,它的容量受 CPU 寻址能力的限制
这个逻辑存储器即是我们所说的内存地址空间
对于初学者,这个概念比较抽象,我们在后续的课程中将通过一些编程实践,来增加感性认识

image

2、寄存器

(1)段地址在 8086CPU 的段寄存器中存放,当 8086CPU 要访问内存时,由段寄存器提供内存单元的段地址
8086CPU 有 4 个段寄存器,其中 CS 用来存放指令的段地址
(2)CS 存放指令的段地址,IP 存放指令的偏移地址,8086 机中,任意时刻,CPU 将 CS:IP 指向的内容当作指令执行
(3)8086CPU 的工作过程
1、从 CS:IP 指向的内存单元读取指令,读取的指令进入指令绥冲器
2、IP = IP + 所读取指令的额长度,从而指向下一条指令
3、执行指令(转到步骤 1,重复这个过程)
(4)8086CPU 提供转移指令修改 CS、IP 的内容
这本书基于 8086 讲寄存器,事实上 8088 也是一样的,都是 16 位
在这里我用 80386,也叫 i386,它是 32 位的
EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP
CS、DS、SS、ES、FS、GS
EIP、EFLAGS
b 字节 8
w 字 16
l 双字 32
q 四字 64

image
image
image
image
image

3、内存访问

(1)字在内存中存储时,要用两个地址连续的内存单元来存放,字的低位字节存放在低地址单元中,高位字节存放在高地址单元中
(2)用 mov 指令访间内存单元,可以在 mov 指令中只给出单元的偏移地址,此时,段地址默认在 DS 寄存器中
(3)[address]表示一个偏移地址为 address 的内存单元
(4)在内存和寄存器之间传送字型数据时,高地址单元和高 8 位寄存器、低地址单元和低 8 位寄存器相对应
(5)mov、add、sub 是具有两个操作对象的指令,jmp 是具有一个操作对象的指令
8086 的入栈和出栈操作都是以字为单位进行的
(1)8086CPU 提供了栈操作机制
在 SS、SP 中存放栈顶的段地址和偏移地址,提供入栈和出栈指令,它们根据 SS:SP 指示的地址,按照栈的方式访问内存单元
(2)push 指令的执行步骤
1、SP = SP - 2
2、向 SS:SP 指向的字单元中送入数据
(3)pop 指令的执行步骤
1、从 SS:SP 指向的字单元中读取数据
2、SP = SP + 2
(4)任意时刻,SS:SP 指向栈顶元素
(S)8086CPU 只记录栈顶,栈空间的大小我们要自己管理
(6)用栈来暂存以后需要恢复的寄存器的内容时,寄存器出栈的顺序要和入栈的顺序相反
(7)push、pop 实质上是一种内存传送指令,注意它们的灵活应用
段的综述
我们可以将一段内存定义为一个段,用一个段地址指示段,用偏移地址访问段内的单元,这完全是我们自己的安排
我们可以用一个段存放数据,将它定义为 “数据段”
我们可以用一个段存放代码,将它定义为 “代码段”
我们可以用一个段当作栈,将它定义为 “栈段”
我们可以这样安排,但若要让 CPU 按照我们的安排来访问这些段,就要
1、对于数据段,将它的段地址放在 DS 中,用 mov、add、sub 等访问内存单元的指令时,CPU 就将我们定义的数据段中的内容当作数据来访问
2、对于代码段,将它的段地址放在 CS 中,将段中第一条指令的偏移地址放在 IP 中,这样 CPU 就将执行我们定义的代码段中的指令
3、对于栈段,将它的段地址放在 SS 中,将栈顶单元的偏移地址放在 SP 中
这样 CPU 在需要进行栈操作的时候,比如执行 push、pop 指令等,就将我们定义的栈段当作栈空间来用
可见,不管我们如何安排
CPU 将内存中的某段内容当作代码,是因 CS:IP 指向了那里
CPU 将某段内存当作栈,是因为 SS:SP 指向了那里
我们一定要清楚,什么是我们的安排,以及如何让 CPU 按我们的安排行事
一段内存,可以既是代码的存储空间,又是数据的存储空间,还可以是栈空间,也可以什么也不是
关键在于 CPU 中寄存器的设置,即 CS:IP、SS:SP、DS 的指向

4、推荐学习

4.1、Intel 开发手册

Intel 开发手册

卷一和卷三需要细看,卷二和卷四用来当字典用
Volume 1:基础架构
Chapter 3 基本执行环境
Chapter 6 过程调用、中断和异常
Volume 3:系统编程指南
Chapter 2 系统架构概述
Chapter 3 保护模式内存管理
Chapter 4 分页
Chapter 5 保护
Chapter 6 中断和异常处理
Chapter 7 任务管理
Chapter 8 多处理器管理
Chapter 9 处理器管理和初始化
Chapter 10 高级可编程中断控制器(APIC)
Chapter 11 内存缓存控制

4.2、Linux 内核完全注释

Linux 内核完全注释 V5.0

建议阅读《Linux 内核完全注释 V5.0》第四章 80X86 保护模式及其编程
对学习汇编、C、操作系统有很大帮助

5、cmpxchg

CAS:lock; cmpxchg xxx, xxx;
cmpxchg 内存中的值,修改后的新值(AL、AX、EAX、RAX 中为期望值)
1、若内存中的值 == 期望值:内存中的值 = 修改后的新值,ZF = 1
2、若内存中的值 != 期望值:期望值 = 内存中的值,ZF = 0
保证线程安全的两种方式:1、上锁 2、无锁(单线程处理某个事情)
cmpxchg cx, dx
ax = 2300H
cx = 2300H
dx = 2400H
cx == ax
cx = dx = 2400H, ZF = 1
cmpxchg cx, dx
ax = 2500H
cx = 2300H
dx = 2400H
cx != ax
ax = 2300H, ZF = 0
posted @   lidongdongdong~  阅读(20)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开