8086汇编语言学习笔记
- 格式:pdf
- 大小:141.83 KB
- 文档页数:5
汇编语言学习笔记《汇编语言》--王爽前言学习汇编目的:充分获得底层编程体验;深刻理解机器运行程序的机理。
原则:没有通过监测点不要向下学习;没有完成当前实验不要向下学习。
第一章基础知识有三类指令组成汇编语言:汇编指令;伪指令;其他符号。
8bit = 1byte = 一个存储单元有n根地址线,则可以寻址2的n次方个内存单元。
1.1节--1.10节小结(1)汇编指令是机器指令的助记符,同机器指令一一对应。
(2)每一种cpu都有自己的汇编指令集。
(3)cpu可以直接使用的信息在存储器中存放。
(4)在存储器中指令和数据没有任何区别,都是二进制信息。
(5)存储单元从零开始顺序编号。
(6)一个存储单元可以存储8个bit,即八位二进制数。
(7)每一个cpu芯片都有许多管脚,这些管脚和总线相连。
也可以说,这些管脚引出总线。
一个cpu可以引出的三种总线的宽度标志了这个cpu不同方面的性能。
地址总线的宽度决定了cpu的寻址能力;数据总线的宽度决定了cpu与其他器件进行数据传送时的一次数据传送量;控制总线的宽度决定了cpu对系统中其他器件的控制能力。
监测点:1KB的存储器有1024个存储单元?存储单元的编号从0到1023.内存地址空间:最终运行程序的是cpu,我们用汇编编程时,必须要从cpu的角度思考问题。
对cpu来讲,系统中的所有存储器中的存储单元都处于一个统一的逻辑存储器中,它的容量受cpu寻址能力的限制。
这个逻辑存储器即是我们所说的内存地址空间。
第二章寄存器(cpu的工作原理)mov ax, 2add ax, axadd ax, axadd ax, ax(1)cpu中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;(2)段地址和偏移地址通过内部总线送人一个称为地址加法器的部件;(3)地址加法器将两个16位地址合成为一个20位的物理地址;(4)地址加法器通过内部总线将20位物理地址送人输入输出控制电路;(5)输入输出控制电路将20位物理地址送上地址总线;(6)20位物理地址被地址总线传送到存储器;段地址*16+偏移地址= 物理地址的本质含义内存并没有分段,段的划分来自cpu。
第三章宏汇编语言每种计算机语言都规定了自己的字符、基本词汇、典型语句和语法规则。
同样,汇编语言也有自己的字符、基本词汇、典型语句和语法规则。
字符:ASCII字符基本词汇:符号指令(MOV、ADD)伪指令(DB、SEGMENT等)典型语句:●机器指令语句——对应机器指令的一种操作。
●伪指令语句——无机器语言与之对应,不生成机器指令。
●宏指令语句——一条宏指令对应多条机器指令,产生一组目标代码。
语法规则:基本语法单位(常量、变量、标号、表达式)前面的例子已介绍了源程序的基本结构、格式、名字的定义、语句格式,下面将更深入地介绍有关语法规则。
3.1表达式汇编程序的语句及程序格式都比较固定,语句中除正确选择操作符之外,主要问题在于正确表示操作数地址,这涉及到寻址方式,可以归结到地址表达式的使用。
表达式:由常数、寄存器、标号、变量加上运算符构成的式子。
3.1.1.常量与数值表达式一.常量常量:从源程序翻译成目标程序期间已经有确定数值的量。
用途:赋值、作立即数、位移量。
由常量与运算符组成的式子。
数值表达式在汇编期间进行运算,结果为常量。
汇编期间允许对常量进行3种运算:1.算术运算包括:+、–、*、/、模除(MOD,取余数)、右移、左移。
2.逻辑运算●逻辑乘:AND(与)●逻辑加:OR(或)●按位加:XOR(异或)●逻辑非:NOT(非)3.关系运算包括:相等(EQ)、不等(NE)、小于(L T)、大于(GT)、小于等于(LE)、大于等于(GE)。
运算结果:关系不成立,结果为0;关系成立,结果为–1(0FFFFH)。
如:N = 50M = (N EQ 50)该关系成立,M =–1。
3.1.2.变量、标号与地址表达式一.变量变量:数据存贮单元的名字。
(存放地址的符号表示)。
变量有三个属性:段、EA、类型。
其中类型由定义时的伪指令确定(DB、DW、DD、DT)。
变量的定义:格式:[变量名] 数据定义伪指令表达式[,…]数据定义伪指令:DB、DW、DD、DQ、DT等。
汇编语言学习笔记段寄存器一、CPU 的典型构成•CPU 中有很多部件,但一般最主要的有:寄存器运算器控制器 ,如下图是CPU 的主要结构:CPU 的典型构成.png(1)寄存器: 存东西的,比如我们做加法计算 20 + 30 ,那么数据20 和30 先存在寄存器中,在运算器中计算后再存储到寄存器中.CPU 中的寄存器,运算器等部件通过CPU中的控制器(总线)与外面的内存等其他部件相连.•对于程序员来说,CPU中最主要的部件是寄存器,可以通过改变寄存器的内容来实现对CPU的控制.(汇编学的好不好和寄存器学的好不好直接相关)•不同的CPU,寄存器的个数 \ 结构是不同的,8086 是16位的结构的CPU,但是地址总线是20位,可以访问1M的存储空间.•8086 有14个寄存器(都是16位的寄存器(可以存放2个字节))8086的14个寄存器.png二、通用寄存器•AX BX CX DX 这4个寄存器通常用来存放一般性的数据(eg: int a = 10 , int b =10 ) 称为通用寄存器(有时也有特殊用途).•通常,CPU会先将内存中的数据存储到通用寄存器中,然后在对通用寄存器中的数据进行运算.•假如,内存中有块红色内存空间的值是3,现在想把他加1,并将结果存储到内存中的蓝色内存空间,那么处理流程大致如下:数据操作流程.png1.CPU 首先会将红色内存空间中的值放到 AX 寄存器中(通用寄存器)中,即: movax , 红色内存空间 (将右边边红色内存空间的值存到左边AX 中 )2.然后让AX 寄存器(通用寄存器)与1相加.即: add ax ,1 (将右边的值1,与左边AX中的值相加并将结果存入左边AX中)3.最后将值(结果)赋值给蓝色内存空间.即: mov 蓝色内存空间, AX (将右侧AX中的值移动到左侧蓝色内存中)•AX BX CX DX 这4个通用寄存器都是16位的,可以存储2个字节,如下如: 8086通用寄存器.png•注意: 上一代8086 的寄存器都是8位的,为了保证兼容, AX BX CX DX 都可以分为2个8位的寄存器来使用.如下图:通用寄存器的拆分.png高8位低8位的拆分.png三、字节与字•在汇编的数据存储中,有两个比较常用的单位:字节和字. (相当于高级语言中的 int,long,float等数据类型).因此我们在汇编中只能定义两种数据类型的数据,字节类型(byte类型),字类型(word 类型))字节: byte ,1个byte 由8个bit组成,可以存储在8位寄存器中.字:word,1个字由两个字节组成,这两个字节分别称为字的高字节和低字节. •比如数据20000 (4E20H,01001110 00100000B),高字节值78,低字节值32. 字表示.png•1个字可以存储在一个16位寄存器中,这个字的高字节\低字节分别存储在这个存储器的高8位和低8位寄存器中.四、段寄存器•8086 在访问内存时要由相关部件提供内存单元的段地址和偏移地址送入地址加法器合成物理地址•是什么部件提供段地址? 答:段地址在8086的段寄存器中存放. (段segment )代码段寄存器: CS (code segment) 存放代码的数据段寄存器: DS (datasegment ) 存放数据的堆栈段寄存器: SS (stack segment ) 对象放堆里面,局部对象放栈里面附加段寄存器: ES (Extra segment)8086段寄存器.png•8086 有4个段寄存器,CS DS SS ES,当要访问内存时由这4个段寄存器提供内存单元段地址.•每个段寄存的具体作用是什么呢?一旦程序运行装载到内存当中,所有的代码\全局变量\局部变量\对象都装载到了内存当中,所以内存当中存在具体的代码和数据,也存在堆栈等等 ,那么CPU想访问内存段代码,那么他会访问法代码段寄存器,如果CPU想想问堆栈中的数据那么他会访问栈寄存器,依次类推就是这样的.。
x86汇编语⾔:从实模式到保护模式笔记(⼆)1.我们都知道,8086可以访问1MB内存,其中,0xF0000~9FFFF属于常规内存,由内存条提供;0xF0000~0xFFFFF由主板上的⼀个芯⽚提供,即ROM-BIOS。
这样⼀来,中间还有⼀个320KB的空间,即0xA0000~0xEFFFF。
传统上,这段地址空间由特定的外围设备来提供,其中就包括显卡。
因为显⽰功能对于现代计算机来说实在太重要了。
2.由于历史原因,所有在个⼈计算机上使⽤的显卡,在加电⾃检之后都会把⾃⼰初始化到80*25的⽂本格式。
在这种模式下,屏幕上可以显⽰25⾏,每⾏80个字符(⼀个字符两个字节组成)。
每屏总共2000个字符(4000字节)。
3.⼀直以来,0xB8000~0xBFFFF这段物理地址空间,是留给显卡的。
tip:不允许将⽴即数传送到段寄存器。
4.屏幕上的每个字节对应着显存中的两个连续字节,前⼀个是字符的ASCLL代码,后⾯是字符的显⽰属性,包括字符颜⾊(前景⾊)和底⾊(背景⾊)。
字符的显⽰属性(1字节)分为两部分,低4位定义的是前景⾊,⾼4位定义的是背景⾊。
格式:K R G B + I R B G(K是闪烁位,为0时不闪烁,为1时闪烁;I是亮度位,为0时正常,为1时⾼亮)RGB:(000⿊;001蓝;010绿;011青;100红;101品红;110棕;111⽩)tip:mov指令的⽬的操作数不允许为⽴即数,⽽且,⽬的操作数和源操作数不允许同时为内存单元。
5.在源程序的编译阶段,编译器会把源程序整体上作为⼀个独⽴的段来处理,并从0开始计算和跟踪每⼀条指令的地址。
因为该地址是在编译期间计算的,故称汇编地址。
汇编地址是在源程序编译期间,编译器为每条指令确定的汇编位置,指⽰该指令相对于程序或者段起始处的距离,以字节计。
当编译后的程序装⼊物理内存后,它⼜是该指令在内存段内的偏移地址。
6.在NASM汇编语⾔中,每条指令的前⾯都可以拥有⼀个标号,以代表和指⽰指令所在的汇编地址。
8086汇编语⾔学习(六)8086处理结构化数据(模拟⾼级语⾔结构体、数组)⼀、8086汇编定义数据 要处理结构化数据,必须先定义数据。
8086汇编作为⼀门编程语⾔,定义数据的⽅式⽐起复杂的⾼级语⾔要简单不少。
汇编语⾔贴近机器底层,所处理的数据逻辑上都可以视为⼆进制数据,按照对不同⼤⼩内存单元的处理,分为三种:db、dw、dd。
1.db db 即define byte,定义⼀个字节变量。
例如 db 1h,代表着db指令后的值占⽤⼀个字节的内存空间 1h=>01h。
特别的,使⽤db可以⽐较简单的定义字符串数据,例如db "ABC",代表着定义A、B、C三个连续的字符。
2.dw db 即define word,定义⼀个字变量。
例如 dw 1h,代表着dw指令后的值占⽤⼀个字/两个字节的内存空间 1h=>0001h。
3.dd dd 即define doubleword,定义⼀个双字变量。
例如 dd 1h,代表着dw指令后的值占⽤两个字/四个字节的内存空间 1h=>0000 0001h。
在连续定义数据时,可以通过逗号进⾏缩写。
例如 db 1h,2h,3h等价与db 1h;db 2h;db 3h。
同时上述三种⽅式都可以与dup关键字(duplicate)使⽤。
例如,定义3个值为1h的字形数据,可以写为dw 3 dup(1h),其等价于dw1h,1h,1h。
在定义复数个相同的数据时,可以简化程序,增强可读性。
db、dw、dd、dup都属于8086汇编的伪指令,由汇编器在编译时进⾏处理,并没有对应的机器指令。
⼆、8086汇编处理结构化数据 之前介绍了8086各种不同⽅式的内存寻址⽅式,下⾯介绍8086如何利⽤这些多样的寻址⽅式来处理结构化的数据。
举⼀个简单的例⼦,假设存在⼀个结构化的数据(公司),拥有五个属性。
公司属性: 公司名称: BLZ 总裁名称: Deckard Cain 公司排名: 15 年收⼊(亿元): 50 产品: WOW 需求是,在内存中定义该数据并且对其中的部分属性进⾏修改,将公司排名修改为10,年收⼊修改为80,产品名称修改为OWO。
8086汇编语⾔学习(⼀)8086汇编介绍1. 学习汇编的⼼路历程 进⾏8086汇编的介绍之前,想先分享⼀下我学习汇编的⼼路历程。
rocketmq的学习 其实我并没有想到这么快的就需要进⼀步学习汇编语⾔,因为汇编对于我的当前的⼯作内容来说太过底层。
但在⼏个⽉前,当时我正尝试着阅读rocketmq的源码。
和许多流⾏的java中间件、框架⼀样,rocketmq底层的⽹络通信也是通过netty实现的。
但由于我对netty并不熟悉,在⼯作中使⽤spring-cloud-gateway的时候甚⾄写出了⼀些导致netty内存泄漏的代码,却不太明⽩个中原理。
出于我个⼈的习惯,在学习源码时,抛开整体的程序架构不论,希望⾄少能对其中涉及到的底层内容有⼀个⼤致的掌握,能让我像⿊盒⼦⼀样去看待它们。
趁热打铁,我决定先学习netty,这样既能在⼯作时更好的定位、解决netty相关的问题,⼜能在研究依赖netty的开源项⽬时更加得⼼应⼿。
netty的学习 随着对netty学习的深⼊,除了感叹netty统⼀规整的api接⼝设计,内部交互灵活可配置、同时⼜提供了⾜够丰富的开箱即⽤组件外;更进⼀步的,netty或者说java nio涉及到了许多更底层的东西,例如:io多路复⽤,零拷贝,事件驱动等等。
⽽这些底层技术在redis,nginx,node-js等以⾼效率io著称的应⽤中被⼴泛使⽤。
扪⼼⾃问,⾃⼰在多⼤程度上理解这些技术?为什么io多路复⽤在io密集型的应⽤中,效率能够⽐之传统的同步阻塞io显著提⾼?⼀次⽹络或磁盘的io传输内部到底发⽣了什么,零拷贝到底快在了哪⾥? 如果没有很好的弄明⽩这些问题,那么我的netty学习将是不完整的。
我有限的知识告诉我,答案就在操作系统中。
操作系统作为软硬件的⼤管家,对上提供应⽤程序接⼝(程序员们通常使⽤⾼级语⾔提供的api间接调⽤);对下控制硬件(cpu、内存、磁盘⽹卡等外设);依赖硬件提供控制并发的系统原语;其牵涉的许多模块内容都已经独⽴发展了(多系统进程间通信->计算机⽹络、⽂件系统->数据库)。
8086汇编语⾔学习(⼆)8086汇编开发环境搭建和Debug模式介绍1. 8086汇编开发环境搭建 在上篇博客中简单的介绍了8086汇编语⾔。
⼯欲善其事,必先利其器,在8086汇编语⾔正式开始学习之前,先介绍⼀下如何搭建8086汇编的开发环境。
汇编语⾔设计之初是⽤于在没有操作系统的裸机上直接操作硬件的,但对于⼤部分⼈来说,在8086裸机上直接进⾏编程将会⾯临各种困难。
好在我们可以使⽤软件模拟器来模拟硬件进⾏8086的学习实践。
在《汇编语⾔》中作者推荐通过windows环境下的masm和debug进⾏学习。
masm介绍: masm是⼀款DOS下的汇编⼯具包,在8086汇编的学习中我们需要其中的⼏个⽂件,分别是masm.exe,link.exe。
masm.exe 汇编器,⽤于将⽂本格式的汇编语⾔源⽂件编译为.obj结尾的⼆进制⽂件,其⽣成的.obj结尾的⼆进制⽬标⽂件是被编译的源⽂件的对应的机器码。
单独的源程序⽬标⽂件通常是⽆法直接运⾏的,还需要和互相依赖的其它同样编译完成的⼆进制⽂件链接在⼀起才能⽣成最终的可执⾏⽂件(⽐如所需要的静态库函数) 。
因此,obj⽂件通常也被叫做中间⽂件。
link.exe 链接器,obj⽂件需要通过链接才能转换成可执⾏程序,⽽链接器就是负责完成这⼀任务的。
链接器能将多个obj⽬标⽂件以及其所依赖的库程序进⾏统⼀处理(例如多个⽬标⽂件中指令、数据内存地址的偏移处理),并⽣成可执⾏⽂件。
debug介绍: debug.exe 调试器,windows提供了⼀个在dos中调试8086汇编程序的⼯具debug.exe,提供了展⽰程序运⾏时CPU中各寄存器、内存中数据,指令级的单步调试等功能。
debug程序的使⽤会在本篇博客的后半段进⾏详细介绍。
64位操作系统兼容性问题: 由于《汇编语⾔》⼀书出版较早,当时的windows系统还是32位的,32位windows系统都默认安装了masm与debug,能打开dos窗⼝直接使⽤。
进位与溢出无符号数运算主要考虑进位/借位问题,而有符号数的运算主要考虑溢出问题。
两个有符号数进行加减运算时,如果运算结果超出了该符号数可表示的范围,就会发生溢出,使计算出错。
1.无符号数运算时的借位当最高位向更高位有进位(或借位)时,即CF=1时,运算结果会超出该无符号数字长所表示的范围。
11111100+ 00000111+ 1 000000118位无符号数的表示范围为0~255,上例中,被加数为252,加上7就超出了8位无符号数的表示范围,向更高位有进位,运算的结果导致CF=1,8位数据不能反映两数相加的和。
2.有符号数运算时的溢出最高位进位状态⊕次高位进位状态=1,则溢出。
怎么理解呢?首先要知道⊕(异或)是什么:相同为0,相异为1;然后是“状态”一词,状态指的是有没有进位。
这句话的意思就是:若最高位和次高位中,一个有进位而另一个没有进位,则异或结果为1,表示有符号的运算结果有溢出,此时OF置1。
来看一下微机原理里面判断OF位的经典例题:将10011100和11100101相加后,标志寄存器中OF为何值?首先,我们都知道OF为溢出标志位(有溢出为1,无溢出为0);然后,他的定义就是判断补码运算时的溢出情况,既然是补码,那就一定是有符号数。
那就用判断有符号数溢出的方法判断,先进行运算:10011100+ 11100101+ 1 10000001由此看出,最高位有进位,次高位也有进位,则没有溢出,所以OF=0。
总之,要始终牢记一点:CF是无符号数溢出标志(暂且也称为溢出),OF 是有符号数溢出标志。
通俗一点说就是,即使有符号数相加/相减导致了CF=1,不能说明结果的正确与否。
此时,若OF=1,则说明结果溢出,出现错误;OF=0,说明结果正确。
这个判断过程根本和CF没关系,CF=1/0,都不会影响。
同理也可以得出OF对无符号数的运算结果判断也无影响。
汇编语言重点知识总结汇编速查手册汇编语言总结概要寄存器与存储器1. 寄存器功能. 寄存器的一般用途和专用用途. CS:IP 控制程序执行流程. SS:SP 提供堆栈栈顶单元地址. DS:BX(SI,DI) 提供数据段内单元地址. SS:BP 提供堆栈内单元地址. ES:BX(SI,DI) 提供附加段内单元地址. AX,CX,BX 和CX 寄存器多用于运算和暂存中间计算结果,但又专用于某些指令( 查阅指令表)。
. PSW 程序状态字寄存器只能通过专用指令( LAHF, SAHF) 和堆栈(PUSHF,POPF) 进行存取。
2. 存储器分段管理. 解决了16 位寄存器构成20 位地址的问题. 便于程序重定位. 20 位物理地址= 段地址* 16 + 偏移地址. 程序分段组织: 一般由代码段, 堆栈段,数据段和附加段组成, 不设置堆栈段时则使用系统内部的堆栈。
3. 堆栈. 堆栈是一种先进后出的数据结构, 数据的存取在栈顶进行, 数据入栈使堆栈向地址减小的方向扩展。
. 堆栈常用于保存子程序调用和中断响应时的断点以及暂存数据或中间计算结果。
. 堆栈总是以字为单位存取指令系统与寻址方式1. 指令系统. 计算机提供给用户使用的机器指令集称为指令系统, 大多数指令为双操作数指令。
执行指令后,一般源操作数不变,目的操作数被计算结果替代。
. 机器指令由CPU 执行,完成某种运算或操作,8086/8088 指令系统中的指令分为6 类: 数据传送,算术运算,逻辑运算,串操作,控制转移和处理机控制。
2. 寻址方式. 寻址方式确定执行指令时获得操作数地址的方法. 分为与数据有关的寻址方式(7 种) 和与转移地址有关的寻址方式(4)种。
. 与数据有关的寻址方式的一般用途:(1) 立即数寻址方式--将常量赋给寄存器或存储单元(2) 直接寻址方式-- 存取单个变量(3) 寄存器寻址方式--访问寄存器的速度快于访问存储单元的速度(4) 寄存器间接寻址方式--访问数组元素(5) 变址寻址方式(6) 基址变址寻址方式(7) 相对基址变址寻址方式(5),(6),(7) 都便于处理数组元素. 与数据有关的寻址方式中,提供地址的寄存器只能是BX,SI,DI 或BP . 与转移地址有关的寻址方式的一般用途:(1) 段内直接寻址-- 段内直接转移或子程序调用(2) 段内间接寻址-- 段内间接转移或子程序调用(3) 段间直接寻址-- 段间直接转移或子程序调用(4) 段间间接寻址-- 段间间接转移或子程序调用汇编程序和汇编语言1. 汇编程序. 汇编程序是将汇编语言源程序翻译成二进制代码程序的语言处理程序, 翻译的过程称为汇编。