汇编修炼心法
文章平均质量分 80
学习汇编语言,我们能够感知,体会和理解机器的逻辑功能。向上为理解各种软件系统的原理,打下技术理论基础;向下为掌握硬件系统的原理,打下实践应用基础,并掌握底层的程序调试和错误分析方法。
song->_->
调试的错误就是编程给你最好的东西,因为在每个错误上面都标志着前进的一步
展开
-
汇编语言修炼目录
参考资料:《x86汇编语言:从实模式到保护模式》《汇编语言》预备知识1-计算机和汇编语言2-8086CPU给出的物理地址方法3-浅谈8086CPU的内存分段机制4-计算机的启动过程5-安装虚拟机和NASM汇编器16位实模式6-如何显示文字和图像7-第一个汇编程序hello world8-div指令和进制转换9-常用的汇编指令10-x86...原创 2019-01-01 10:53:22 · 1130 阅读 · 0 评论 -
27-通过调用门实现提权
参考资料:9-调用门(无参)1. 什么是调用门在之前的学习中,JMP FAR指令实现代码跨段的本质是修改CS段寄存器,并不会改变程序的特权级别(即修改CPL的值),如果我们即想要实现代码跨段和提权的话,就需要用到调用门。调用门是CPU提供的一个功能,它允许一个3环(CPL=3)的程序通过这扇“门”来修改CS段寄存器并实现提权到0环(CPL=0),实际上调用门是一个系统段描述...原创 2019-06-27 21:37:43 · 1368 阅读 · 0 评论 -
26-代码跨段跳转
1. 什么是代码跨段简单来讲,代码跨段本质上就是修改CS段寄存器的值,即把另一个代码段的描述符加载到cs段寄存器。前面我们也说过,CS段寄存器不能单独修改,需要和EIP寄存器一起修改才行,因此想要实现代码跨段访问就需要使用一些特定的指令来完成,例如jmp far指令就可以完成代码跨段访问。2. 代码间跳转流程2.1 查表得到段描述符然后CPU根据段选择子查找G...原创 2019-06-15 19:34:24 · 832 阅读 · 0 评论 -
25-段权限检查
1. CPU分级保护模式下的CPU分成了4个级别,通常称为0环,1环,2环,3环。处在最中间的0环是CPU运行特权指令的,0环的特权级别最高,通常我们所写的内核程序,驱动程序就运行在0环。基于操作系统写的用户程序则运行在3环,同理,3环的特权级别最低(为了方便理解,你可以把0环理解为内核程序运行的内核空间,3环是用户程序运行的用户空间)。需要明白的一点是,所谓0环也好,3环也好,都是对...原创 2019-06-11 00:05:56 · 421 阅读 · 0 评论 -
24-段描述符属性
1. 段描述符属性S位S位用于指定描述符的类型,当S=0表示是一个系统段,S=1则表示是一个数据段或代码段,对于系统段我们将在后面介绍。2. 段描述符属性Type域Type字段有4位,用于指定描述符的子类型。对于Type来说,当S=1或0时,Type所表示的含义是完全不一样的,这里我们只讨论S=1的情况。对于数据段来说,Type有E,W,A三位;对于代码段来说,Type有C,...原创 2019-06-08 21:25:41 · 702 阅读 · 0 评论 -
23-段描述符与段选择子
1. GDT表现在思考一个问题,当你写一个段寄存器的时候,只给了一个16位的数,但段寄存器有96位,那剩下的80位是怎么来的?这个16位的数是随便写的吗?事实上是,通常在执行MOV DS,AX这些指令时,CPU会查表,并根据AX的值来决定查找GDT(全局描述符表)还是LDT(局部描述符表),查找表的什么位置,查出多少数据。有同学可能会好奇GDT表在哪里,表的大小有多大呢?这就要说到gd...原创 2019-06-08 13:12:03 · 5634 阅读 · 6 评论 -
22-从段寄存器开始
1. ds寄存器保护模式有2种非常重要的机制:段和页,这2种机制都是非常复杂的,无论是学习段或者页的机制,在此之前都要先了解段寄存器。来看下面这一段代码:mov dword ptr ds:[0x123456],eax在上面的代码中,有一个ds寄存器,根据前面学习实模式我们知道ds是一个数据段寄存器。eax是一个32位的寄存器,dword表示4字节,正好也是32位。换句话说,这段代...原创 2019-06-08 12:33:53 · 643 阅读 · 0 评论 -
21-32位处理器架构
在前面的学习中,8086CPU是基于16位的实模式,并且有20根地址线,寻址范围为1MB内存;32位的处理器架构是延续8086发展而来的,对8086有很好的兼容性。相信学过计算机的同学都知道,32位系统最大只识别4G内存,原因在于32位的处理器有32根地址总线,寻址长度为4G内存。另外,16位处理器的通用寄存器有8个,即AX、 BX、 CX、 DX、 SI、 DI、 BP 和 SP;而...原创 2019-05-29 22:56:55 · 532 阅读 · 0 评论 -
20-8086处理器的中断机制
中断就是打断处理器当前的执行流程,去执行另外一些和当前工作不相干的指令,执行完以后,还可以返回到原来的程序流程继续执行。在现实生活中我们也会经常遇到类似中断这样的事情,例如你正在用手机听歌,突然你的电话响了,这时处理器必须中断歌曲的播放,来处理这件更为重要的事件。中断可以分为两大类:CPU内部中断和CPU外部中断。1. 外部硬件中断从字面意思理解,外部硬件中断就是处理器外面...原创 2019-04-03 17:47:26 · 3667 阅读 · 0 评论 -
19-再谈8086CPU的分段机制
前面已经简单的讨论过8086CPU的分段机制了,如果已经忘了的同学赶快回去复习一遍(传送门:3-浅谈8086CPU的内存分段机制),在这一篇我们将针对前面的知识进行补充和应用。8086处理器的工作模式是逻辑上对内存分成各个段(程序员自己抽象),8086处理器在执行指令处理数据时,例如获取下一条指令或者获取某个数据信息,肯定会涉及到寻址,而在8086中一律按照“段地址 x 16 +偏移地址 ”的...原创 2019-01-01 12:33:34 · 1693 阅读 · 4 评论 -
18-子程序调用
1. 接口封装下面这个汇编程序是实现三数求和的功能:mov ax,0x0000mov ss,ax mov sp,0xFFFFmov bp,0xFFFF;计算100+200+300push 100push 200push 300mov ax,word[ss:bp-2] ;把第一个数加数放到ax中。add ax,word[ss:bp-4] ;把第一个数和第二个数相加,...原创 2018-12-28 20:34:40 · 2946 阅读 · 0 评论 -
17-equ伪指令和jmp指令
1. equ指令equ指令(英文为:equal),在Nasm汇编器中是一条伪指令。我们知道伪指令不能直接执行,需要经过编译器处理转换成纯汇编指令。类似equ指令的语法,在很多编程语言中都存在,有的叫做定义常量,比如我们学习C语言会接触到一个#define的语法,跟equ指令的作用是一样的,因为equ指令的本质就是替换。 直接上代码吧:mov ax,100mov bx,100m...原创 2018-12-27 09:56:58 · 3285 阅读 · 0 评论 -
16-8086处理器的寻址方式
CPU作为计算机的中央处理器,每天忙忙碌碌,只要它工作着就会不断地运行指令,处理各种数据。既然要处理数据,就会涉及两个问题:1. 数据在哪里,如何获取2. 处理完之后,把数据送到哪里去而在计算机中,寻址方式就是如何找到要操作的数据,以及把数据处理完存放到哪里。对于8086处理器来说,它的寻址方式大致分为这几类:寄存器寻址,立即寻址,内存寻址,下面我们分别来讨论这几种寻址方式。 ...原创 2018-12-25 17:13:41 · 501 阅读 · 0 评论 -
15-栈和栈的初始化
计算机工程师们为了设计出更高效,更易于控制管理的程序,把内存分成一些不同的区域(详细见4-计算机的启动过程中的图3),其中有一块区域就是“栈”,本质上栈是一段内存空间,在计算机里领域里代表:数据临时存储的地方。同时栈也是一种数据存储结构,这对于学过数据结构这门课的同学来说并不难理解,我们知道“栈”在程序设计中是经常使用的,在早期,设计8086处理器的计算机工程师为了更方便的管理“栈”这段内存,...原创 2018-12-24 16:11:44 · 2160 阅读 · 1 评论 -
14-movesb指令和movesw指令
1. movesb指令movsb可以理解为 move string byte,即字节传送指令。 来看一个示例,汇编代码如下:mov ax,0x0050mov es,axmov ax,0x07C0mov ds,axjmp near Code;把这5个数据复制到起始地址0x00500的位置Data:db 0xAA,0x11,0x22,0x33,0x44Cod...原创 2018-12-23 14:30:08 · 4029 阅读 · 0 评论 -
13-ZF标志位,JB和JNB跳转指令
1. ZF标志位这一节我们将来学习一下标志寄存器的ZF(Zero Flag)零标志位。对于ZF标志位,当运算结果为0的时候,那么ZF=1,当运算结果不为0的时候,ZF=0。 例如下面这段汇编指令:mov ax,10mov dx,10sub ax,dx但sub指令一旦运行,就会修改寄存器里面的值,当ax和dx进行减法运算的结果为0时,那么ZF标志位就会被置为1。有些...原创 2018-12-22 16:36:33 · 21032 阅读 · 0 评论 -
12-数据宽度
现在有一个十进制数字123,如果我们希望用4位数来表示这个数字可以写成0123,如果用7位数来表示可以写成0000123。同理,对于负数-233,用5位数来表示就是-00233。乍一看用这种方式来表示数字好像也没啥意义,前面我们学习的寄存器都是8位或16位的,但是,如今的大多数CPU都使用了64位寄存器。我们知道一个十进制数字15D以有符号数格式存放在8位寄存器al中,用二进制来表示...原创 2018-12-19 16:00:35 · 835 阅读 · 0 评论 -
11-有符号数和无符号数
1. 有符号数和无符号数无符号数,因为没有符号位,所以只能表示一个正数。有符号数,因为存在符号位,符号位如果是0的话,代表这是一个正数,符号位如果是1的话,代表这个数是一个负数。 我们可以用db伪指令来声明一些数字: 编译之后:10D的十六进制表示就是0x0A,11D的十六进制表示就是0x0B,17D的十六进制表示就是0x11 但自从学习汇编语言,我们还...原创 2018-12-18 18:24:41 · 2632 阅读 · 0 评论 -
10-x86汇编——大小端模式
汇编语言实际上是和内存以及寄存器打交道的,当处理器执行汇编指令时,影响的不是内存变化就是寄存器的变化,前面我们已经详细介绍过寄存器了,这一小节我们主要讨论数据在内存中的存储——大小端模式。当我们对内存读写时,实际上是操作的内存地址(又可以称为内存编号),每一个内存地址都对应着一个内存存储单元,而每个内存单元对应1个字节(相当于8个比特位)。如上图所示,假设我们需要在以0x08001为起...原创 2018-12-18 14:22:23 · 2407 阅读 · 0 评论 -
9-常用的汇编指令
1. 逻辑运算指令 在汇编语言中逻辑运算指令有:与运算指令,或运算指令,非运算指令,异或运算指令。分别用and、or、not、xor来表示。 以and指令举例:mov ax,0xFFFF ;ax=1111 1111 1111 1111mov bx,0xF0F0 ;bx=1111 0000 1111 0000and ax,bx ;ax...原创 2018-12-17 20:39:51 · 1561 阅读 · 0 评论 -
8-div指令和进制转换
1. 十进制与N进制之间的转换在学习计算机基本原理时,大家应当知道,在计算机中最常使用的进制就是二进制,二进制是现代主流电子计算机的基础。并且二进制与我们熟悉的十进制之间有着一对一的关系,比如十进制数5对应的二进制数是101,任何一个十进制数都对应一个二进制数,以及十六进制数,不信你可以自己推导一遍.....哈哈,开个玩笑,显然是不可能全部都推导一遍的,但我们可以看几个示例。来看一个十...原创 2018-12-16 16:19:56 · 869 阅读 · 0 评论 -
7-第一个汇编程序hello world
经过前面的一段学习,现在终于进入到实战阶段了,这是我们要写的第一个汇编程序,在屏幕上显示hello world字符。访问显存和访问内存一样,需要用到逻辑地址,即“段地址:偏移地址”的形式。我们知道文本模式下起始物理地址为0xB8000(即显存的起始地址),因此我们可以把0xB8000看成是段地址0xB800,偏移地址为0x0000到0xFFFF区域。 注意,这里我们使用ES寄存器指向显...原创 2018-12-15 13:27:26 · 955 阅读 · 2 评论 -
6-如何显示文字和图像
当处理器加电或复位之后,BIOS-ROM程序就会读取硬盘的主引导扇区(即0面0道1扇区),并将它加载到0x0000:0x7c00处,即物理地址0x07c00,并判断是否有效。那么计算机如何判断这是一个有效的主引导扇区?一个有效的主引导扇区的最后两字节是0x55和0xAA,BIOS-ROM程序会判断这两个标志(非常重要),如果有效就执行jmp 0x0000:0x7c00指令并跳转到指定...原创 2018-12-14 16:37:23 · 1136 阅读 · 0 评论 -
5-安装Bochs和NASM汇编器
从上一篇中,我们知道计算机的启动过程是从主引导扇区才真正开始的,而操作系统就是从这开始一步一步把自己运行起来的。其实换个角度想一下,如果我们把编译好的程序放在主引导扇区,不也能够让处理器执行吗? 正常来说是可以的,而且还是在不依赖操作系统的情况下,让编译好的程序可以执行的唯一方法;但是,如果改写了硬盘的主引导扇区,那么windows和linux操作系统就会瘫痪,无法启动,显然这并不是我们...原创 2018-12-13 20:49:50 · 841 阅读 · 0 评论 -
4-计算机的启动过程
现在我们思考这样一个问题:处理器是如何执行编译好的程序。1.如何将编译好的程序交给处理器执行通常程序运行必须要借助操作系统,以我们熟悉的windows为例,当我们用鼠标点击图标运行一个软件时,在我们看不到的层面上,操作系统必须给运行的程序分配空闲的内存空间,并在合适的时候交给处理器执行。图1-执行程序操作系统对运行的程序是有严格要求的,例如编译好的程序是针对哪种操作...原创 2018-12-12 22:01:04 · 514 阅读 · 0 评论 -
3-浅谈8086CPU的内存分段机制
1. 内存分段在上一篇我们知道8086CPU在访问内存使用了分段机制,即通过“(段地址×16)+偏移地址=物理地址”的方式来确定内存单元的物理地址,需要明白的是内存空间是一个连续的线性空间,对于内存本身来说并没有划分段,这其实是CPU为了方便寻址而使用了内存分段机制。简单一句话理解就是内存本身并不分段,而是CPU为了方便寻址对内存进行了分段(对于这种说法,可能会对初学者产生一种误解,误...原创 2018-12-10 22:39:09 · 3613 阅读 · 0 评论 -
2-8086CPU给出的物理地址方法
这一小节,我们主要介绍CPU在访问内存单元的数据是如何确定物理地址的,但在这之前,我们先来学习mov和add两个简单的汇编指令,当然这只是为了讲CPU访问内存单元的寻址做铺垫。1.简单学习mov和add指令图1-mov和add指令mov指令是用于传递数据的,而mov ax , 18指令就是将18送入寄存器ax,用高级语言来描述就是把18赋值给AX。mov ah , 78指令是将78...原创 2018-12-10 15:00:46 · 1475 阅读 · 0 评论 -
1-计算机和汇编语言
1. 什么是汇编语言汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言,是计算机高级程序设计语言的鼻祖。汇编语言不像其他大多数的程序设计语言一样被广泛用于程序设计,但是汇编语言运行效率非常高,快速执行和响应,在某些场合下仍然有着不可替代的作用,例如操作系统内核,工业控制,驱动设备等领域具有广泛的应用。2. ...原创 2018-12-09 00:36:30 · 2514 阅读 · 0 评论