汇编语言的学习

本文详细介绍了8086汇编语言中的各种指令、内存管理、数据处理方法(如and、or运算、div、mul等)、标志寄存器、中断系统(包括内中断和外中断)以及BIOS接口操作,帮助读者理解汇编编程的基本原理和实践应用。
摘要由CSDN通过智能技术生成

汇编-补

总线

地址总线:对存储单元的地址存取

一个地址总线能存一个字节

地址总线宽度决定了寻址能力

数据总线:CPU与内存之间的数据通过它来传输

数据宽度决定传输数据量

控制总线:CPU通过控制总线进行控制

控制总线宽度决定了控制能力

通用寄存器

AX分出高八位和低八位即AH、AL这是为了能向下兼容,即向八位的寄存器兼容

段寄存器

CS代码段寄存器、IP指令指针寄存器

修改CSIP内容使用JMP指令

主要使用段地址X16+偏移地址=物理地址也就是说CSX16+IP=物理地址

在内存中存储以栈的形式表现

用ss、sp来表示栈顶指针,其中ss为段地址sp为偏移地址

在内存没有使用之前,栈顶指针指向栈底的下一个地址,这就类似于数据结构中头结点一样

从数据结构角度来看,在一段内存单元范围内ss+sp表示的地址,ss基本上不会发生改变,而sp在入栈和出栈的过程中会不断的改变,这不就是栈顶指针的表现形式,这样让我明白为什么会先声明一个头结点

每次进栈出栈要-2/+2因为段里面进行字操作

ds

ds作用是将一个地址作为段地址,这是因为在程序运行时会产生两个位的字节引导PSP

而这个在二进制下就是256个字节,用ds来存储或指向段地址,而后程序由CS开始

loop和bx

mov ax,[0]

如上语句在debug中是指将ax偏移地址为0的内存内容赋值给ax

但是在masm中这样的表达形式不成立,masm中会将0这个值赋给ax而不是ax偏移地址下的内存

在masm中可以这样表示

mov bx,0
mov ax,[bx]
;或者
mov ax,bs:[0]

loop就是循环

其中次数由cx来存储

mov cx,2
s:add ax,ax
loop s

意思就是执行一个数乘2,众所周知CPU实现乘法是由加法实现的

这里很明显loop表示为循环,一般要执行整个过程要在debug中t命令

这里还有两个指令gp

其中g是指向特定的地址,可以实现达到特定位置,不用一次一次的t

而p就是一步到位到程序最后,类似高级语言时的debug的断点的跳过

0:200~0:20h是一段安全空间 这里有一个点就是es这个寄存器,它是一段内存里面的多余的段

程序段

引入程序段更好的书写程序和操作 同时认识了dw对字型数据的存储,就类似字符串,以及db字节型数据

开始引入start代码段的标志,这个标志会使得计算机开始读取指令从这里开始而不是从它之上的声明数据等开始,这是因为CPU一开始会读取end来寻找代码段,如果没有就从头开始逐行执行

start:mov ...
	....
code  ends
end start

开始进行类似封装的模块化,引入数据段、栈段从不同内存段进行程序的编写

assume cs:code,ds:data,ss:stack ;注意这里ds:data读取一个数据还是不能直接读取依然需要ax通用寄存器来搬运
data segment ;数据段
	dw 0213H,0456H,0789H,····
data ends

stack segment
	dw 0,0,····
stack ends ;栈段

code segment
start:mov ax,stack
	mov ss,ax
	······
code ends
end start

以上明确的表示了程序段的运用

另外段中数据占N个字节,程序加载后实际空间为16X(N/16+1)

定位内存地址

andor运算

and表示与运算,即两个数为1结果为1其余结果为0

or表示与运算,即两个数为0结果为1其余结果为0

而这可以用在判断字母大小写上,还不需要用if

A的ASCII码为65,即01000001,B为01000010

而a的ASCII码为97,即01100001,b为01100010

可见字母大小写至于第五位有关

那么在判断大小时只需要第五位置0或1,从而可以改变大小写

[bx+data]

[bx+data]表示(bx)+data即bx的值加上一个数值

[bx+i]

[i+bx]

i[bx]

[bx].i

以上为表现形式

这样有一个好处就是不修改bx的值来达到移动到相应的偏移地址,同时还可以用这个表示一个数组

si和di

si用于指向源始代码字符串空间

di用于指向目的地空间

这个可以用[bx+i]的形式来变式,还可以[bx][si]

当然还可以继续向后组合

在进行双重循环的时候就可以用栈来存储cx的值使得循环之间不干扰

数据处理

引入概念描述regsreg

reg表示寄存器

sreg表示段寄存器

8086处理器只有四个寄存器可以放在[]里面即si di bp bx

组合有bx和si、bx和di、si和bp、bp和di

bp寄存器是服务于ss寄存器的,类似sp

这里通过数据结构的概念更好的联系高级语言之间的相似处

抽象数据类型以及对一些数据类型进行结构化声明

定义了字节型数据以及字型数据

字节型数据byte ptr 字型数据word ptr

div

div除法指令

除数被除数
8位16位
16位32位
div reg
div 内存单元
div 

除数为八位时商存在al余数存在ah

div byte ptr ds:[0]
;那么  (al)=(ax)/((ds)*16+0)
		(ah)=(ax)/((ds)*16+0)

除数为16位时高16位存在dx中,低16位存在ax

div word ptr es:[0]
; (ax)=[(dx)*10000H+(ax)]/((ds)*16+0)
	(dx)=[(dx)*10000H+(ax)]/((ds)*16+0)

dup

dup重复操作符,可以设置重复次数,避免录入大量字节或字时进行重复性的繁琐操作

转移指令

offset替换指令

jmp

jmp无条件转移需要指出转移的目的地址以及距离

jmp在执行时是不需要目的地址的,CPU不需要目的地址就可以实现对ip的修改,所以jmp执行时是用偏移地址

jmp short 字节转移

jmp far ptr段间转移

jmp word ptr字型转移

jmp dword ptr双字型转移

jcxz

jcxz有条件转移

jcxz cxcx为零才可以转移

call ret

ret 用栈里面数据修改ip的内容,即出栈将值取出,实现短转移

retf用栈里面的数据修改cs ip内容,实现短转移

call指令将cs ip入栈,不能实现短转移,与jmp类似

因为call和jmp类似所以也有类似段内转移以及段间转移

call word ptr

call dword ptr

这俩个指令结合类似于C语言的函数调用,而ret就类似return

这就比较形象的展现C语言里面写一个函数的执行过程,进行段间的转移然后出栈入栈的操作执行函数

mul

mul乘法指令与除法指令类似

字节型和字型表示相同,高16位和低16位

标志寄存器(flag)

zf结果为0其值为0,反之为1

第二位pf奇偶位标志,偶数为1奇数为0

sf符号标志位,负为1正为0,它的值对有符号数来说有意义,对无符号数没有意义

cf标志,flag第0位,无符号运算时记录了对高位借位值

例如两个八位相加有一个九数,多出来的一位用cf记录,减法借位也一样

有借位在debug时会表现出来,修改标志寄存器为CY没有则为NC

of进行由符号位运算时的溢出,用其记录

df方向控制位控制si:di增减,0增加1减少

标志值为1值为0
OFOVNV
SFNGPL
ZFZRNZ
PFPEPO
CFCYNC
DFDNUP

abc sbb

带借位的加减法运算

cmp

运算结束后记录flag值,不记录运算的值

进行有符号数运算时,观察SF与OF值来判断运算数之间关系

无符号数观察ZF和CF

条件跳转指令:JE

JE (Jump if Equal): 如果前一条指令的结果导致零标志(ZF)被设置(即相等),则跳转到指定的标签或地址。这是基于比较操作的结果进行的条件跳转,广泛用于循环和分支决策中。

数据传输指令:MOVS系列

MOVS指令是用于数据传输的串操作指令,根据方向标志(DF)决定数据传输的方向。

MOVSB (Move Byte): 将源地址(DS:SI)的一个字节数据传输到目标地址(ES:DI),并根据DF的值自动调整SI和DI的值(增加或减少)。
MOVSW (Move Word): 功能与MOVSB相似,但是传输的是一个字(2字节)而不是字节。

方向标志控制指令

**方向标志(DF)**决定了串操作指令处理数据时SI和DI指针的移动方向。
CLD (Clear Direction Flag): 将DF置为0,使得SI和DI在串操作后自增,即向高地址移动。
STD (Set Direction Flag): 将DF置为1,使得SI和DI在串操作后自减,即向低地址移动。

与之相似的指令

除了上述指令,x86汇编语言中还有许多其他用于条件跳转和数据传输的指令:

条件跳转指令: 如JNE(Jump if Not Equal), JG(Jump if Greater), JL(Jump if Less)等,它们根据比较操作后的标志寄存器的状态来决定是否跳转。

串操作指令: 如MOVSD(Move Doubleword)用于传输双字型数据,REPE/REPZ和REPNE/REPNZ前缀用于重复串操作直到计数器ECX为0或者满足/不满足零标志ZF的条件。

串传送

movsb以字节型数据传输,将ds:si值传入es:di,根据df进行增减

movsw传输字型数据

clddf置零

stddf置一

中断

内中断

中断向量表位于内存的0000:0000到0000:03ff里1024个单元

一个地址由四个字节存放,一共256个中断向量,存放一个段地址和偏移地址就

TF

中断标志寄存器,1为中断

CPU对sssp连续设置不会响应单步中断

int

int n有不同中断码

intiret使用过程与calret相似

int 10h中断

ah设置光标位置,且BIOS里用ah传输数据

bh设置页号

dh设置行号

dl设置列号

补充:在B8000h到BFFFFh里32KB空间有80*25彩色字符空间

端口

CMOS RAM对软件开设的端口

in写入数据、out输出数据

只能用ax或者al来存放数据,访问8位端口用al访问16位的端口用ax

在RAM内有128个存储单位来存储时钟即系统配置信息,这样关机后也能继续计时,且用主板上电池供电

shl逻辑左移以及shr逻辑右移,移动位数存于cl所移最后一位存入CF

BCD码RAM中存储的信息

一个字节可以表示两个BCD码

外中断

外设通过端口与CPU交互

if为了禁止可屏蔽中断而设置为0

键盘产生扫描码,送入60H

扫描码长度为一个字节,分为按下时的通码和松开时的断码

通码第七位为0,断码为1

断码=通码+80H

CPU进行int 9中断进行输入

直接定址表

引入标号,数据标号

不加:的数据标号可以指向地址或长度,还可以在其他段使用

想在代码段中用数据标号访问数据需要用assume将标号所在的段与段寄存器联系起来

BIOS输入及读写

BIOS提供nt 16h用于读取键盘缓冲区

ah为扫描码,al为ASCII码

int 16h中断例程时刻检测键盘缓冲区是否有数据

int 9从键盘读入数据,int 16h从缓冲区读出数据

int 9在键盘按下的时候进行读取

int 16h在程序调用时将数据从键盘缓冲区读出

int 13h是BIOS访问磁盘的中断例程

int 13h里面,(ah)=int 13h功能号

(al)=读取扇区数、(ch)=磁道号、(cl)=扇区号、(dh)=磁头号

通码第七位为0,断码为1

断码=通码+80H

CPU进行int 9中断进行输入

直接定址表

引入标号,数据标号

不加:的数据标号可以指向地址或长度,还可以在其他段使用

想在代码段中用数据标号访问数据需要用assume将标号所在的段与段寄存器联系起来

BIOS输入及读写

BIOS提供nt 16h用于读取键盘缓冲区

ah为扫描码,al为ASCII码

int 16h中断例程时刻检测键盘缓冲区是否有数据

int 9从键盘读入数据,int 16h从缓冲区读出数据

int 9在键盘按下的时候进行读取

int 16h在程序调用时将数据从键盘缓冲区读出

int 13h是BIOS访问磁盘的中断例程

int 13h里面,(ah)=int 13h功能号

(al)=读取扇区数、(ch)=磁道号、(cl)=扇区号、(dh)=磁头号

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

庞奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值