汇编语言学习

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


一.汇编语言学习

1.基础知识

1.1指令组成

  • 汇编指令:机器码的助记符,有对应的机器码。
  • 伪指令:没有对应的机器码,由编译器执行,计算机不执行。
  • 其他符号:没有对应的机器码,由编译器识别,±*/

1.2存储器

  • 指令和数据在存储器中存放,即内存,CPU可以直接使用的信息在存储器中存放。

1.3指令和数据

  • 在内存和磁盘上没有任何区别,都是二进制信息

1.4存储单元

  • 一个存储器有 。。。个单元,0到。。。,一个存储单元存储1个字节,8个二进制位。磁盘的容量同内存一样。

1.5CPU对存储器的读写

必须与芯片进行3类信息的交互:

  • 存储单元的地址-----地址信息
  • 器件的选择,读或写的命令------控制信息
  • 读或写的数据--------数据信息

1.6地址总线

  • 一根导线可以传送的稳定状态只有两种:高电平及低电平,即1或0
  • 一个CPU有n根地址线,则可以说这个CPU的地址总线的宽度为n,这个CPU最多寻找2的n次方个内存单元。

1.7数据总线

  • 数据总线的宽度决定了CPU与外界的数据传送速度

1.8控制总线

  • 控制总线是一些不同控制线的集合,有多少根控制总线,就对芯片有多少种控制,控制总线的宽度就决定了CPU对外部器件的控制能力

1.9 …

  • 内存地址空间:通过地址总线找到的内存单元即cpu的内存地址空间
  • 主板
  • 接口卡:cpu控制接口卡,接口卡根据cpu的命令可控制外设。
  • RAM:随机存储器:存放大部分程序和数据
  • ROM:装有基本输入输出系统的只读存储器
  • CPU将各个物理存储器看作一个逻辑存储器,即内存地址空间。

2.寄存器

  • CPU由运算器,控制器,寄存器等构成,并通过内部总线相连。
  • 运算器进行信息处理,寄存器进行信息存储,控制器控制各种器件进行工作。

2.1通用寄存器

  • 包括AX,BX,CX,DX,分为高8位AH和低8位AL

2.2字在寄存器中的存储

  • 字:word,一个字由两个字节构成,分为高位字节与低位字节。

2.3汇编指令

  • 写汇编指令及寄存器名称时不区分大小写
  • 单独执行ah,al运算时认为两个为单独的8位寄存器
  • 指令的两个操作对象位数一致
  • mov add

2.4物理地址

  • 所有的内存单元构成的存储空间是一个一维线性空间,每一个内存单元在这个空间中都有唯一的地址,即物理地址
  • CPU通过总线送入存储器内的,必须是一个内存单元的物理地址,并先在内部生成这个物理地址

2.5 8086CPU给出物理地址的方法

  • 16位结构的CPU:运算器一次最多处理16位的数据,寄存器的最大宽度为16位,以上两者之间的通路为16位。CPU可以一次性处理,传输,暂时存储16位的地址。
  • 在内部用两个16位地址合成的方法形成一个20位物理地址,物理地址==段地址*16+偏移地址,前者为基础地址,且为一段内存单元的起始地址.
  • 段:地址连续,起始地址为16倍数的一组内存单元
  • 数据在21F60H内存单元中,说法为;数据存在内存2000:1F60单元中或 数据存在内存的2000H段中的1F60H单元中。

2.6段寄存器

  • 段地址由段寄存器发出
  • CS:代码段寄存器,IP:指令指针寄存器,任意时刻,CPU将CS:IP指向的内容当作指令执行。
  • CPU读取执行指令的过程:1)从CS:IP指向的内存单元中读取指令,读取的指令进入指令缓冲器。2)IP+=所读取指令的长度,从而指向下一条指令。3)执行指令。
  • 改变CS,IP指令的值:修改CS的内容:jmp指令,“jmp 段地址:偏移地址”修改IP的内容:jmp 某一合法寄存器,可以用该寄存器中的值修改IP的值。
  • 不能将数据直接用mov 存入段寄存器

2.7代码段

  • 要让CPU执行我们放在代码段中的指令,必须要将CS:IP指向所定义的代码段中的第一条指令的首地址。

3.寄存器(内存访问)

3.1内存中字的存储

  • 一个字用两个地址连续的内存单元存放,低位字节放在低地址单元中,高位字节放在高地址单元中
  • 字单元:存放一个字形数据的内存单元,1地址字单元,即起始地址为1的字单元。

3.2 DS和[address]

  • DS寄存器用来存放访问数据的段地址
  • mov指令可以将数据直接送入寄存器,将一个寄存器中的内容送到另一个寄存器,将一个内存单元中的数据送到一个寄存器中,[ ]表示一个内存单元,其中为内存单元的偏移地址。
  • 将一个内存单元的数据存入段寄存器,需要用一个寄存器进行中转,再把这个寄存器中数据传入目标寄存器。

3.3字的传送

mov bx,1000H
mov ds,bx
mov ax,[0]  #将1000:0的字型数据送入ax
mov [0],cx  #将cx中的16位数据送到1000:0处

3.4mov,aff,sub指令

mov ax,8
mov ax,bx
mov ax,[0]
mov [0],ax
mov ds,ax
mov ax,ds
#下为段寄存器与内存单元中的数据传递
mov ax,1000H
mov ds,ax
mov ds,[0]
#mov [0],ds也可以
add ax,8
add ax,bx
add ax,[0]
add [0],ax
#sub同add
#段寄存器不能用add,sub

3.5数据段

  • 存放数据的内存段

3.6栈

  • 可以把一段内存当作栈来使用

  • push ax 表示将 ax中的数据送入栈中,pop ax为从栈顶取出数据送入ax中,8086cpu入栈出栈操作都是以字为单位进行的

  • 任意时刻,SS :SP指向栈顶元素

  • push ax具体过程:1)SP=SP-2,SS:SP指向当前栈顶前面的单元,并以其为新栈顶 2)将ax中的内容送入SS:SP指向的内存单元处

  • 入栈时,栈顶由高地址向低地址方向增长

  • pop ax具体过程:1)将SS:SP指向的内存单元处的数据送入ax中
    2)SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。

  • 栈顶超界 :栈满push,栈空pop

  • 关于push 与 pop:

push ax
pop ax
push ds
pop ds
push [0]
pop[2]
#均以字为单位
#CPU要知道内存单元的地址,可以在push,pop指令中只给出内存单元的偏移地址,段地址在指令执行时,从ds中取得。

3.7栈段

  • 最大容量为64KB
  • 对于数据段,将他的段地址放在DS中,用mov,add,sub等访问内存单元的指令时,CPU就将我们定义的数据段中的内容当作数据来访问。
  • 对于代码段,将他的段地址放在CS中,将段中的第一条指令的偏移地址放在IP中,这样CPU就将执行代码段中的指令
  • 对于栈段,将他的段地址放在SS中,将栈顶单元的偏移地址放在SP中,CPU会将栈段当作栈空间使用。

4.第一个程序

4.1一个源程序从写出到执行的过程

  • 第一步:编写汇编源程序,使用文本编辑器
  • 第二步:对源程序进行编译连接,使用编译程序进行编译,产生目标文件,再用连接程序对目标文件连接,生成可在操作系统中直接运行的可执行文件。
  • 可执行文件包括:1)程序(从源程序的汇编指令中翻译的机器码)和数据(源程序定义的数据)。2)相关的描述信息(比如:程序占的内存空间)
  • 第三步:执行可执行文件的程序

4.2源程序

asssume cs:codesg
codesg segment
		mov ax,0123H
		mov bx,0456H
		add ax,bx
		add ax,ax
		mov ax,4c00H
		int 21H
codesg ends
end
  • 源程序包括两种指令:汇编指令与伪指令,前者有对应机器码的指令,可以被编译成机器指令,最后有CPU执行;后者没有对应机器码,只能被编译器执行。
  • 上述程序中出现3种伪指令:
    1)XXX segment XXX ends,一对指令,必须用到,可以定义一个段,segment说明段开始,ends说明段结束,XXX是一个段名
    2)end是一个汇编程序的结束标记。
    3)assume:假设某一段寄存器和程序中的某个被定义的段相关联
  • 将源程序中所有内容称为源程序,将源程序中最终由计算机执行,处理的指令数据,称为程序
  • 标号:codesg,这个是一个段的名称,也是标号,一个标号指代了一个地址,编译链接后即为一个段的段地址
  • 程序返回:move ax 4c00H int 21 # 是汇编指令
  • 编辑源程序:编辑后成为asm或其他格式文件
  • 编译:1)输入源程序文件名,接着是目标文件文件名.obj 2)列表文件名称,交叉引用文件,可以不输入
  • 连接:1)输入目标文件名,确定可执行文件的文件名,2)后面有映像文件与库文件的生成,可以全部忽略
  • 简化的编译连接:在第一个命令行后加上源程序文件的路径,文件名,结尾加上分号,回车键,即可编译或连接

4.3操作系统的外壳

在这里插入图片描述
在这里插入图片描述

4.4程序执行过程的跟踪

5.[BX]和loop指令

  • [bx]表示一个内存单元,偏移地址在bx中,段地址在ds中
  • ()表示一个寄存器或一个内存单元中的内容,内存单元的地址为物理地址,一个20位数据
    在这里插入图片描述
  • (X)的应用
    在这里插入图片描述
(al),(bl),(cl)得到的数据为字节型
(ds),(ax),(bx)得到的数据为字型
  • idata表示常量,mov ax,[idata]

5.1[BX]

  • 注意(ax)=((ds)*16+(bx))与((ds)*16+(bx))=(ax)的区别
  • inc BX ,将BX中的内容加1

5.2loop指令

  • loop + 标号
  • CPU会进行两步操作:(cx)=(cx)-1;判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。cx记录循环次数。
  • 标号s标识了一个地址,这个地址处有一条指令:add ax,ax
mov cx,11
s:add ax,ax
loop s
  • 注意:在汇编源程序中,数据不能以字母开头,则需要前面加0
    在这里插入图片描述
  • 对于[idata]的解释:Debug中将其解释为内存单元即其偏移地址,而编译器将其解释为idata常数
#计算ffff:0~ffff:b单元中数据的和,并存储在dx中
asssume cs:code
code segment
	mov ax,0ffffh
	mov ds,ax
	mov bx,0
	mov dx,0
	mov cx,12
s:  mov al,[bx]
    mov ah,0
    add dx,ax
    inc bx
    loop s
    mov ax,4c00h
    int 21h
  code ends
  end

5.3段前缀

在这里插入图片描述
其中,ds:即为段前缀

  • 将内存ffff:0-ffff:b单元中的数据复制到0:200-0:20b中
assume cs:code
code:segment
	mov ax,0ffffH
	mov ds,ax
	mov ax,0020h
	mov es,ax
	mov bx,0
	mov cx,12
s:	mov dl,[bx]
	mov es:[bx],dl
	inc bx
	loop s
	mov ax 4c00h
	int 21h
code ends
end

6.包含多个段的程序

  • 通过在源程序中定义段来进行内存空间的获取,在一个程序加载的时候为程序分配空间

6.1在代码段中使用数据

  • dw含义是定义字形数据dw 0123h,0456h,0789h,0abch.....
    程序的框架

6.2在代码段中使用栈

#利用栈,将程序中定义的数据逆序存放
assume cs:codesg
codesg segment
	dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
	dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	#用dw定义16个字形数据,程序加载后,得到16个字的内存空间,后面的程序将这段空间当作栈使用
start: mov ax,cs
	 mov ss,ax
	 mov sp,30h   
# 前16个字节存放数据,则需要将cs:10--cs:2F内存空间当作栈使用,则设置ss:sp指向cs:30
	mov bx,0
	mov cx,8
s:	push cs:[bx]
	add bx,2
	loop s
	mov bx,0
	mov cx,8
s0: pop cs:[bx]
	add bx,2
	loop s0
	mov ax,4c00h
	int 21h
	codesg ends
	end start

6.3将数据,代码,栈放入不同的栈

  • 程序中对段名的引用,段名会被编译器当成一个表示段地址的数值,故不能直接将其mov给段寄存器
#将6.2中程序如下改写
assume cs:a,ds:b,ss:c
a segment 
	dw 0123h...
a ends
c segment
	dw 0,0,0,0,0.....
c ends
b segment
d: mov ax,c
   mov ss,ax
   mov sp,20h
   mov ax,a
   mov ds,ax
   mov bx,0
   mov cx,8
s:	push [bx]
	add [bx],2
	loop s
	mov bx,0
	mov cx,8
s0: pop[bx]
	add bx,2
	loop s0
	mov 4c00h
  	int 21h
b ends
end d

7.灵活定位内存地址的方法

7.1 and和or指令

  • and指令:逻辑与指令,按位进行与运算
  • or指令:逻辑或指令,按位进行或运算

7.2以字符形式给出的数据

  • 在汇编程序中,用’ ‘方式指明数据是以字符形式给出
#改变字符大小写
#位数从0开始算
assume cs:codesg,ds:datasg
datasg segment
  db 'BaSiC'
  db 'iNfOrMaTiOn'
datasg ends
codesg segment
start:mov ax,datasg
	  mov ds,ax
	  mov bx,0
	  mov cx,5
	  s:mov al,[bx]
	    and al,11011111B   #将asc码第5位置值为0,即变为大写字母
	    mov [bx],al
	    inc bx
	    loop s
	    mov bx,5
	    mov cx,11
	  s0:mov al,[bx]
	  or al,00100000B   #将asc码第5位置为1,变为小写字母
	  mov [bx],al
	  inc bx
	  loop s0
	  mov ax,4c00h
	  int 21h
	  codesg ends
	  end start

7.3[bx+idata]

  • [bx+idata]表示一个内存单元,偏移地址为(bx)+idata
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,5
s:mov al,[bx]#前提是两个字符串长度相同
and al,11011111b
mov [bx],al#或0[bx]
mov al,[5+bx]#或5[bx]
or al,00100000b
mov [bx+5],al
inc bx
loop s

7.4 SI和DI

  • SI和DI是8086CPU中和bx功能相近的寄存器,不能分成两个8位寄存器
  • [bx+si]表示一个内存单元,偏移地址为(bx)+(si)
  • mov ax,[bx+si]:段地址在ds中,等同于mov ax,[bx][si]
  • mov ax,[bx+200+si]==mov ax,200[bx][si]==movax,[bx].200[si]

7.5综合运用编程

#将data段中每个字符串改为大写,字符串长度为3
#双层循环,在每次开始内层循环时,都将外层循环中的cx重新保存到dx寄存器中
#dx寄存器在循环中被占用,则用一个内存单元来保存数据,直接在data段dw 0
#每个都用内存单元存,就会难记,一般来说,暂存数据用栈
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
db 'ibm            '
db 'dec            '
db 'dos            '
db 'vax            '
datasg ends
stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends
codesg segment
start:mov ax,stacksg
mov ss,ax
mov sp,16
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0:push cx
mov si,0
mov cx,3
s:mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s
add bx,16
pop cx
loop s0
mov 4c00h
int 21h
codesg ends
end start


8.数据处理的两个基本问题

  • 基本问题:处理的数据在哪个地方,要处理的数据有多长

8.1 bx,si,di,bp

  • 在8086中,只有这4个寄存器可以用在[…]中进行内存单元的寻址
  • 在[…]中,这4个可以单独出现,也可以组合
  • 使用bp时不给定段地址,则默认其在ss中
  • 机器处理的数据在3个地方:CPU内部,内存,端口
mov bx,[0]  #指令执行前在内存单元中
mov bx,ax   #CPU内部,ax寄存器
mov bx,1    #CPU内部,指令缓冲器

8.2 数据长度

  • 1)通过寄存器名指明数据尺寸
  • 2)没有寄存器名时,用操作符 word ptr或 byte ptr来说明

8.3 div指令

  • div为除法指令
  • div reg div 内存单元
    在这里插入图片描述
    在这里插入图片描述
#100001/100
mov dx,1
mov ax,86A1H
mov bx,100
div bx

8.4 伪指令

  • dd定义双字型数据,db定义字节型数据,dw定义字形数据
  • dup操作符,进行数据的重复db 3 dup(0,1,2)#等于db 0,1,2,0,1,2,0,1,2

9.转移指令的原理

  • 可以修改ip,或同时修改CS和IP的指令统称为转移指令,他可以控制cpu执行内存中某处代码的指令
    转移行为分为:
  • 只修改IP时,称为段内转移,jmp ax
  • 同时修改cs和ip时,为段间转移,jmp 1000:0
  • 段内转移分为短转移(ip修改范围-128-127),近转移(-32768-32767)
    转移指令分为
  • 无条件转移指令
  • 条件转移指令
  • 循环指令
  • 过程
  • 中断

9.1操作符 offset

  • 取得标号的偏移地址
#将s处的一条指令复制到s0处
assume cs:codesg
codesg segment
s:mov ax,bx  #此句机器码站两个字节
mov si,offset s
mov di,offset s0
mov ax,cs:[si]
mov cs:[di],ax
s0:nop
nop
codesg ends
end s

9.2依据位移进行转移的jmp指令

  • jmp short 标号(转到标号处执行指令)

  • 属于段内短转移,向前最多越过128字节,向后最多越过127个字节

  • 该句在机器码中,并不包含转移的目的地址,包含的是转移的位移

-

9.3 转移的目的地址在指令中的jmp指令

jmp far ptr 标号 实现段间转移,即远转移,cs=标号所在段的段地址,ip=标号在段中的偏移地址

9.4 转移地址在寄存器中的jmp指令

格式:jmp 16位reg
功能:(IP)=(16位reg)

9.5 转移地址在内存中的jmp指令

1)jmp word ptr 内存单元地址(段内转移)
功能:从内存单元地址处开始存放一个字,是转移的目的偏移地址
2)jmp dword ptr 内存单元地址(段间地址)
功能:从内存单元地址处开始存放两个字,高地址的字是目的段地址,低地址是偏移地址

9.6 jcxz指令

  • jcxz指令为有条件转移指令,所有的有条件转移指令都是短转移,对应的机器码中包含转移的位移
    在这里插入图片描述

9.7loop指令

  • 循环指令,都是短转移,对应的机器码中包含转移的位移
    在这里插入图片描述

10.CALL和RET指令

call和ret都是转移指令,都修改ip或同时修改cs和ip

10.1ret和retf

  • ret指令用栈中的数据,修改ip的内容,实现近转移
  • retf指令用栈中的数据,修改csip内容,实现远转移
    在这里插入图片描述

10.2 依据位移进行转移的call指令

在这里插入图片描述

10.3转移的目的地址在指令中的call指令

在这里插入图片描述

10.4 转移地址在寄存器中的call指令

在这里插入图片描述

10.5转移地址在内存中的call指令

1)call word ptr 内存单元地址
相当于:push IP \n jmp word ptr 内存单元地址
2)call dword ptr 内存单元地址
相当于:push CS \ n push IP \n jmp dword ptr 内存单元地址

10.6 call和ret的配合使用

在这里插入图片描述
在这里插入图片描述

10.7 mul指令

在这里插入图片描述

10.8寄存器冲突的问题

在这里插入图片描述

#将4个长度均为5的字符串变为大写
code segment
start: mov ax,data
	mov ds,ax
	mov bx,0
	mov cx,4
s:	mov si,bx
	call capital
	add bx,5
	loop s
	mov ax,4c00h
	int 21h
capital:push cx
	push si
change:mov cl,[si]
	mov ch,0
	jcxz ok
	and byte ptr [si],11011111b
	inc si
	jmp short change
ok:	pop si
	pop cx
	ret
code ends
end start

11. 标志寄存器

  • 其中存储的信息被称为程序状态字(PSW),标志寄存器简称为flag
    在这里插入图片描述

11.1 ZF标志

  • 第6位,即零标志位,记录相关指令执行后,其结果是否为0,如果结果为0,则该位为1,否则为0

11.2 PF标志

  • 第2位,即奇偶标志位,记录相关指令执行后,其结果的所有bit位中1的个数是否为偶数,是则pf=1

11.3 SF标志

  • 第7位,即符号标志位,记录相关指令执行后,其结果是否为负,是,则SF=1,当然进行的运算应为有符号运算,无符号运算时,SF值无意义
    在这里插入图片描述

11.4 CF标志

  • 第0位,即进位标志位

在这里插入图片描述

11.5 OF标志

  • 溢出:进行有符号数运算时,结果超出机器所能表示的范围。

二.python学习

1.正则表达式

正则表达式描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。

1.1正则表达式语法

1.1.1普通字符
  • 普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。
  • [ABC]匹配 […] 中的所有字符
  • [^ABC]匹配除了 […] 中字符的所有字符
  • [A-Z]表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母。
  • . 匹配除换行符(\n、\r)之外的任何单个字符,相等于 [^\n\r]。
  • [\s\S] 匹配所有。\s 是匹配所有空白符,包括换行,\S 非空白符,不包括换行。
  • \w 匹配字母、数字、下划线。等价于 [A-Za-z0-9_]
1.1.2特殊字符
  • $ 匹配输入字符串的结尾位置。
  • *匹配前面的子表达式零次或多次。
  • +匹配前面的子表达式一次或多次。
  • [ 标记一个中括号表达式的开始
  • ? 匹配前面的子表达式零次或一次,
  • ^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。
1.1.3限定符
  • 限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。
  • *匹配前面的子表达式零次或多次。
  • +匹配前面的子表达式一次或多次。
  • ?匹配前面的子表达式零次或一次。
  • {n}n 是一个非负整数。匹配确定的 n 次。
  • {n,}n 是一个非负整数。至少匹配n 次。
  • {n,m} m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。
1.1.4定位符
  • ^ 匹配输入字符串开始的位置。
  • $ 匹配输入字符串结尾的位置。
  • \b 匹配一个单词边界,即字与空格间的位置。
  • \B 非单词边界匹配。
1.1.5 选择
  • 用圆括号 () 将所有选择项括起来,相邻的选择项之间用 | 分隔。
  • exp1(?=exp2):查找 exp2 前面的 exp1。
  • (?<=exp2)exp1:查找 exp2 后面的 exp1。
  • exp1(?!exp2):查找后面不是 exp2 的 exp1。
  • (?<!exp2)exp1:查找前面不是 exp2 的 exp1。

1.2 正则表达式修饰符

在这里插入图片描述

1.3 运算符优先级

  • 正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似。
  • 相同优先级的从左到右进行运算,不同优先级的运算先高后低。
    在这里插入图片描述
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值