汇编语言有必要学吗如何只改一个字节中的一位?

笔记基于《汇编语言程序设计(第五版)》——钱晓捷一、首先来解决为什么要学习汇编语言这个问题汇编语言优点:有效控制硬件,可直接对处理器内的寄存器、主存储器的存储单元与外设端口。执行速度快、占用存储空间小。缺点:最接近机器语言,复杂难懂。编写程序烦琐,调试、维护、交流和移植困难。适用场景:需反复调用的子程序、动态链接库。eg:操作系统核心程序、实时控制系统的软件。程序与硬件密切相关场景。eg:外设驱动、I\O接口初始化程序段。低层软件、加密软件、计算机病毒防治。高级语言(如c\c++、python、java)与汇编语言相对,高级语言类似自然语言,简单易学。并且功能强大,具有可移植性...汇编语言应被称为低层程序设计语言,这些语言适应于计算机系统的不同层次结构,没有高低之分。二、计算机系统概述1. 硬件处理器(CPU),内包括运算器、控制器和寄存器。存储器,分为主存(内存)、辅存(外存)。外部设备,如键盘、鼠标、显示器、打印机......系统总线,是各个部件信息交换的公共通道。注1:主存(内存)与系统总线直接相连。注2:我们熟知的硬盘属于辅存,通过I\O接口间接与总线相连。注3:汇编语言程序设计时,处理器、存储器和外设被分别转换为寄存器、存储器地址和输入输出地址。2. 软件系统软件,包括最重要的操作系统。应用软件。3. 程序设计语言低级语言——机器语言:0、1组成的代码,可被机器直接识别并执行。由操作码和操作数构成。低级语言——汇编语言:用助记符表示指令操作码,更易理解。高级语言,与具体计算机硬件无关,易被掌握使用。三、数制这个部分有系统学习过C语言的同学相信已经很熟悉了,这里简单带过一下。1. 名称C语言中可以直接使用十进制数,二进制数需加前缀0b,十六进制数需加前缀0x;汇编语言 中则采用后缀的形式来区分不同数制:十进制(Decimal)——D;二进制(Binary)——B;十六进制(Hexadecimal)——H;2. 运算原则和十进制没有任何差别,唯一需要注意的是十进制小数的转化!3. 数值编码其最主要的作用反映在有符号数的表达上。
原码:最高位代表符号,其余位直接表示数值大小。最高位0代表正数,1代表负数。
反码:意为直接取反,0变1,1变0,包括符号位。补码:先取反再加一。注1:计算机中,有符号数默认采用补码形式。注2:所有有符号数都有上述三种编码方式。正数即为其二进制数本身。注3:反码中0可表现为+0和-0,故其存储范围为+127~-127。而补码存储范围为+127~-128。4. 字符编码BCD:用二进制4位对应十进制的一个数,浪费6个编码换来了直观性。eg:0100 1001 0111 1000.0001 0100 1001B = 4878.149 由于通常使用1字节(8个二进制位)表示一个数值,所以BCD码又分为压缩BCD码和非压缩BCD码。eg:压缩BCD:10000111B(87H) 非压缩BCD:00001000 00000111B(0807H) ASCII:7位二进制编码,共有128个。
Unicode:16位二进制编码,一个字符占据2字节。四、80x86系列处理器发展过程:4004->8086(16)->80286(16)->80386(32)->80486(32)->Pentium (奔腾)系列(32)->Intel 64 结构(64)->多核技术。五、微型计算机系统1. PC的硬件主机、键盘、鼠标、显示器。键盘和显示器合称控制台。2. 主存空间的分配8086 CPU有20位地址线,即可寻址
2^{20}B = 1MB 主存空间。包括一下4个部分:基本RAM区(640kb:00000H~9FFFFH):DOS管理,操作系统占用低地址。保留RAM区(128kb:A0000H~BFFFFH):存放屏幕显示信息。显卡提供支持。扩展ROM区(128kb:C0000H~DFFFFH):I/O接口卡ROM芯片提供支持。系统ROM区(128kb:E0000H~FFFFFH):系统占用,含重要ROM-BIOS程序注:区分RAM(随机存储器)和ROM(只读存储器),莫要混淆。六、8086 微处理器(CPU)从此处开始,由于软硬件的结合,相比过去单独学习编程语言刚开始会困难许多。1. 首先我们来认识一些基础术语。寄存器:寄存器存在于CPU中,作为高速存储单元,常用它来储存数据和地址。它们通常为16位寄存器,可存储 2^{16}KB = 64KB 的数据,部分(AX、BX、CX、DX)可以细分为两个8位寄存器。总线:用于数据传输,它的位数决定了传输数据的范围。CPU和内存(主存)间采用20位地址总线,可寻址1MB大小的内存。CPU内部,由于寄存器最大只有16位,故采用16位数据总线。取指:我们写的程序指令都保存在主存中,需要通过存储器中的地址将指令读取出来放进指令队列,等待执行。寻址:指令的执行离不开数据的交互,而数据有些存储在寄存器中,有些在内存中,它们都有各自的地址。所以指令中必须包括由地址寻找对应数据的过程,这个过程就叫寻址。同样,运算得到的数据不可能一直放在寄存器里,它们需要保存到主存里,这个过程同样需要“寻址”。CPU中每个部分各司其职,寄存器不仅要临时存储运算数据还要存储地址相关信息,是至关重要的部件,后面会着重讲解。2. 寄存器 8086的寄存器组由8个通用寄存器、4个段寄存器、1个标志寄存器和1个指针寄存器组成,它们都是16位的。寄存器的功能与它们的名字相对应,建议配合英文意思进行记忆。通用寄存器:
AX (accumulor)、BX (Base)、CX (Counter)、DX (Data):这四个寄存器又称数据寄存器,名称按ABCD顺序排列,首字母同时和意思相关联。
SI (Source Index)、DI (Destination):这两个寄存器称为变址寄存器,src/dest通常表示“源/目的”。通常与操作数
BP (Base Pointer)、SP (Stack Pointer):这两个寄存器又称为指针寄存器,采用堆栈的数据储存方式(先进进后出FILO)。作为指针(Pointer),SP指向堆栈顶,BP指向堆栈某位置。
标志寄存器Flag:
16位的其中0、2、4、6、7、8、9、10、11位均表示一个状态,分别是CF(carry进位)、PF(parity奇偶)、AF(adjust调整)、ZF(zero零)、SF(sign符号)、TF、IF、DF、OF(overflow溢出)。 指令指针寄存器IP(Instruction Pointer):IP是专用寄存器,它每执行一条指令IP就会增加该指令字节增量,指向下一条指令。不可被直接赋值修改。段寄存器:CS(code代码段)、SS(stack堆栈段)、DS(data数据段)、ES(extra附加段)。段寄存器体现了模块化程序设计思想,在后续寻址方式中有着重要作用。3. 8086的存储器组织在了解寻址方式前,我们先要知道主存中数据的存储方式,包括以下知识点。
字节、字、双字:一个字节占8位(二进制位),一个字由2字节(16位)组成,一个双字由4字节(32位)组成。
小端方式:低字节存入低地址,高字节存入高地址。对于书本中的图片习惯于低地址在下,高地址在上。地址边界对齐:为了更高的性能,根据数据的位数为单位,一个单位只存一个数。即:对于一个n字节的数据,在起始地址能被n整除存放。4. 硬件层面的寻址方式段基地址:1MB主存被分为16个大小为64KB的逻辑段,每个段初始地址mod16为0,即xxxx0H为段基地址。段内偏移地址:由于每个逻辑段大小为64KB,故可以采用16位地址来指定具体位置,该地址就称为段内偏移地址。逻辑地址:“段基地址:段内偏移地址”;又简称“段地址:偏移地址”。物理地址:即存储器固有地址00000H~FFFFFH20位。存储器的分段管理:数据线只有16位,而地址线却有20位,那多出来的4个二进制位该如何表示呢?根据上述知识点,不难发现只需要将段基地址取高四位(16进制位)即可在16位数据线内传输。所以我们采用逻辑地址来代替物理地址。逻辑地址换算物理地址:书面常用十六进制表示,即段基地址后加0(二进制数左移4位)再加上偏移地址。 eg:1460H:0100(逻辑地址) = 14600H + 0100H = 14700H(物理地址);段寄存器的作用:段寄存器常用来储存段基地址,搭配其他寄存器存储的偏移地址,经过地址加法器后即可变为20位物理地址进行主存中的寻址工作。有效地址:有效地址EA通常为直接给定的地址值或运算得到的地址值,它们均为偏移地址,需要搭配段地址使用。EA默认段寄存器为DS,若运算中使用BP则默认段寄存器为SS。若要强行更改段寄存器则需要使用段超越前缀。段超越前缀:CS:EA/ SS:EA/ DS:EA/ ES:ea,即超越有效地址EA的默认段寄存器,使用人为指定的段寄存器。独立段和重叠段:在主存中,代码段、数据段、堆栈段和附加段可以分别独立占据最大64KB空间,也可以重叠储存。重叠储存时,段基地址可以取相同值,使用不同的段内偏移地址取出需要的数据。独立段重叠段5. 代码层面的寻址方式汇编语言代码格式:执行性语句: 标号:
处理器指令助记符
操作数, 操作数
; 注释 说明性语句: 名字
伪指令助记符
参数, 参数, ...
; 注释 注:双操作数指令中“,”右边为源操作数(src),“,”左边为目的操作数(dest)。8086寻址方式注:此处示例都已MOV(数据传输指令)指令举例。 1. 立即数寻址方式:直接将立即数IMM传送给寄存器。 mov
al, 05h mov
ax, 0102h注:8位立即数传给8位寄存器,16位立即数传给16位寄存器,缺位用0补齐。2. 寄存器寻址方式:寄存器之间的数据传输,本质上没有用到主存的寻址操作。 mov
ax, [1234h]注:操作后bx = 1234h。3. 存储器寻址方式:通常将主存中的数据通过寻址定位后传递给通用寄存器。直接寻址方式:指令中包含有效地址EA。
mov
ax, [1234h]注1:中括号[ ]即表示括号内地址所对应主存存储单元内容。
注2:此处人为指定1234h为有效地址EA,默认段地址在DS中,所以此处寻址方式先将逻辑地址DS:EA转化为对应的物理地址,再将该地址下数据传入AX。
寄存器间接寻址方式:EA存放在寄存器中。 mov
ax, [si] 注:[SI]意为此时有效地址存放在SI(Source Index)中,默认段地址同样在DS中。
寄存器相对寻址方式:EA = BX/BP/SI/DI + 8/16。 mov
ax, [di + 06h]mov
ax, [bp + 06h] 注1:注意BP的段地址在SS(堆栈段寄存器)中,其余默认在DS中。
注2:此处8/16指8位或16位偏移量加在有效地址上。
注3:若计算后EA超出FFFFH,则取FFFFH(64 * 1024)的模。
基址变址寻址方式:EA = BX/BP + SI/DI。
mov
ax, [di + 06h] mov
ax, [bp + di]mov
ax, ds:[bp + di]注1:BX/BP即为基址寄存器(base),SI/DI为变址寄存器。
注2:DI默认段寄存器为DS,BP默认段寄存器为SS,而第三个例子中使用的段超越前缀。
相对基址变址寻址方式:EA = BX/BP + SI/DI + 8/16位位移量。 mov
ax, [di + si + 06h]注1:位移量可以用事先定义的变量或常量表示,不一定要是数值。
注2:除上述书写方式外还有不同的书写方式,例如mov
ax, [bx][si]等价于mov
ax, [bx + si];mov
ax, count[bx][si]等价于mov
ax, [bx + si + count]count是事先定义的变量。 注3:立即数只能作为源操作数(src),源操作数和目的操作数不能同时是主存储器。到此为止我们就学完了所有的寻址方式。知识是一个反复理解的过程,刚开始可能对于汇编语言知识中一些陌生的术语、概念感到困惑或难以记忆、理解。现在,在坚持学完了第一章的内容后,你会发现,有不少知识点是可以融汇贯通的。最后,就着目前的内容,来回溯一下前面一些比较抽象的概念。寄存器,究其根本不是主要存储数据的地方,只是数据操作中的中转站。通过寻址的内容,可以看到,大部分寄存器是用来辅助寻址操作的,例如SI/DI、BP/SP,以及所有的段寄存器。它们存储的内容直接或间接的构成了逻辑地址,即段地址:偏移地址。只有少部分通用寄存器用来存储数据:AX/DX。寄存器的名称,现在可以说豁然开朗了。例如,基址(BX/BP)、变址(SI/DI)寄存器。说白了就是存储有效地址EA的寄存器。有些名称中出现的堆栈(Stack)其实是指它所寻址对象,在主存中是采用堆栈的结构使用的,而并非寄存器本身使用堆栈的存储方式。至于段寄存器中出现的名称(Code、Data、Stack)同样是指主存中数据段的存储内容,而非寄存器中的存储内容。段寄存器存储的是这些数据段的基址,类似于“门牌号”而非“内容物”。数据大小:我们通常说的多少位,一般指的是二进制位,如16位、32位。这些数字与计算机硬件息息相关。如16位总线,它就只能传输16位以内的二进制信号;如16位寄存器,他最大也只能存储一个字(word)大小的数据,不能溢出。这些数由0、1构成,是纯粹的机器语言,人类很难理解,所以很多时候,我们将每4位转换换位16进制数,可以略微降低人为辨识的复杂程度。由于机器码理解起来有难度,为了便于食用,将单独出一章机器码的示例分析,敬请期待~

我要回帖

更多关于 汇编语言有必要学吗 的文章