0基础学习汇编语言整理的知识点

发布于 2022-08-23 11:06:42

整理学习汇编语言收集的知识点

查看更多

浏览量
8302
16 个回答
猫哥
猫哥 项目组成员 2022-08-23
希望我的回答能对你有所帮助

汇编指令之跳转指令(J开头)

跳转指令 是通过修改CS:IP来控制CPU跳转到新的地址的。

JMP
JMP 指令无条件跳转到目标地址,该地址用代码标号来标识,并被汇编器转换为偏移量
格式:

JMP destination

当 CPU 执行一个无条件转移时,目标地址的偏移量被送入指令指针寄存器,从而导致迈从新地址开始继续执行。
JMP 指令提供了一种简单的方法来创建循环,即跳转到循环开始时的标号:

top:
    .
    .
    jmp top     ;不断地循环

JMP 是无条件的,因此循环会无休止地进行下去,除非找到其他方法退岀循环。
jmp指令的机器码里是没有目的地址的,他包含的是需要跳转的字节长度,然后吧ip = ip + 跳转字节长度,这样就指向了新的地址。

JZ,JE
这两个指令是一个意思,通过 ZF 标志位是否跳转,当执行到 JZ 或者 JE 指令时,如果 ZF=1 则跳转,如果 ZF=0,不跳转

cmp eax,ecx
je 0040100c

如果此时 eax=ecx=1,执行完cmp 命令,标志位 ZF=1,执行 je 会跳转到 0040100c 出执行。

JNE,JNZ
这两条语句同一个意思,只是叫法不同,当执行到这两条语句时,如果标志位 ZF=0,则跳转,反正,不跳转

cmp eax,ecx
jne 0040100c

此时 eax=0,ecx=1,执行完 cmp 命令,zf=0,执行 jne 会跳转到 0040100c 处执行

jcxz 有条件转移指令
当cx==0,则跳转。

jb jnb 根据CF位确定是否转移 (jump blelow)
前者小于后者,cf=1 jb跳转。
前者大于等于后者,cf=0 jnb跳板

ja jna 根据CF/zf位确定是否转移 (jump above)
前者大于后者 cf=0,zf=0 ja跳转
前者小于等于后者 cf=1 zf=1 jna跳转

猫哥
猫哥 项目组成员 2022-08-26
希望我的回答能对你有所帮助

ADD SUB指令

add xx,yy 将xx的数据加上yy的数据。xx|yy 同mov指令,可以是数据、寄存器、[内存偏移地址];
sub xx,yy 将xx的数据减去yy的数据。

adc ax,bx 对带符号的数据进行加法运算。运算过程中要带上CF进位标志一块运算。ax = ax + bx + cf
sbb ax,bx 对有符号的数据进行减法运算, ax = ax - bx - cf

猫哥
猫哥 项目组成员 2022-08-24
希望我的回答能对你有所帮助

汇编语言,作用到硬件上的编程语言。所以需要了解硬件的结构,才能更好的使用汇编语言。

机器语言,是由一堆机器指令集合组成。

指令:01010000 就是指 push ax,指将ax寄存器的数据加入栈内存。

01:脉冲电信号,广义上脉冲性质的东西都可以作为指令信号。

汇编语言相较于机器指令,更优势在于,将01等难以辨识的信息变的直观、易书写。

这便是一个代码浓缩、提炼的过程,一行字代表一堆01的操作

如 1000 10001 1101 1000 升级为 MOV AX,BX 表示 寄存器BX的内容送到AX。

汇编语言如何在机器上执行? 通过编译器,它负责编译成01代码供机器执行。

猫哥
猫哥 项目组成员 2022-08-24
希望我的回答能对你有所帮助

寄存器

CPU中存储数据的元件,一个CPU拥有超多的寄存器。
MOV AX,BX 中 AX BX都是寄存器的代号。

16位寄存器
ax(ah,al)
bx(bh,bl) 基址寄存器,存放段偏移地址。
cx(ch,cl) 计数寄存器,在循环和串操作总充当计数器,指令执行后自动修改。
dx(dh,dl) 数据寄存器

BP 基址指针寄存器
SP 栈指针寄存器,常与SS连用
SI 源变址寄存器
DI 目的变址寄存器 常与DS连用

IP 指令指针寄存器,永远指向下一条要执行的指令的地址

CS 代码段寄存器,和 IP连用
DS 数据段寄存器
SS 栈段寄存器
ES 扩展段寄存器 这四种存放的地址称之为“段基址”

16位的标志寄存器
9个存放程序的状态标志(标识运行状态)、和控制标志(控制CPU的操作)
CF(0) 进位标志位,如果两个值相加超出位数,则进位标志CF=CY(1),没有进位CF=NC(0),如果是相减导致借位CF=CY
PF(2) 奇偶标志,结果的二进制中1的个数为偶数 pf=PE(1) 否则 pf=PO(0)
AF
ZF(6) 零标志位,指令执行结果为0,zf=ZR(0) 不为0 zf=NZ(0)
SF(7) 符号标志位,结果为负数,sf=NG(1) (扩展:有符号的数字,首位为符号标志 10000001,符号数表示-127,无符号表示+129) 否则sf=PL(0)
OF() 溢出标志位,有符号数运算超过机器所能表示的范围,OF=OV(1) 否则 OF=NY(0)

IF
DF(10) 方向标志位,当df=0,si di自动递增 ;df=1,si di自动递减。通过cld指令将DF设置为0,通过std指令将DF设置为1
TF

猫哥
猫哥 项目组成员 2022-08-26
希望我的回答能对你有所帮助

MOV指令,将数据复制到另一个寄存器中

mov bx,2000 将数据存入bx寄存器
mov ax,bx 将一个寄存器的数据复制到另一个寄存器
mov ds,ax 将数据寄存器的内容存入ds段地址寄存器,这是一个跳转操作。不能将数据直接放入段寄存器。
mov ax,ds 上一步反过来
mov ax,[2] 将当前内存指向地址做[...]偏移后的数据存入ax
mov [0],dx 将dx寄存器的数据存入偏移地址为0的内存中。
mov ax,cs:[0] 将cs代码段地址寄存器偏移0内存的内容存入ax中
mov ax,[bx + 2] 将bx偏移处+2处的内存数据存入ax中,这种方式适合处理数组数据。
mov ax,2[bx] 这种写法更接近于数组的感觉了
mov ax,[bx].2 是上面的变体写法。
mov ax,[bx+si] 将偏移地址bx/si之和后的ds内容端地址数据存入ax.
mov ax,[bx+si+2]
mov ax,2bx
mov ax,datasg 将data数据内存地址存入ax
mov ds,ax 将datasg的内容地址转移入ds段

猫哥
猫哥 项目组成员 2022-08-25
希望我的回答能对你有所帮助

CPU

CPU由运算器、控制器、寄存器等组件组成,它们通过内部总线进行沟通。

寄存器将数据临时存放。比如8086CPU就有14个寄存器,分别为
AX、BX、CX、DX;(这四个常存放一般的数据,X指定它为16位长度,可拆分成ah,al)
CS、SS、DS、ES;(段地址寄存器,用于存放段地址)
SP、BP、IP;(段地址偏移寄存器)
SI、DI;(性质和bx一样,默认是数据段偏移地址寄存器,不能差分成两个8字节)
PSW;
每个寄存器都是16位的,存放2个字节。

对于一些老旧系统,比如8位系统,它的数据一次只有8位,这是AX里就会区分成AH(高段)、AL(低段)两段,AL里存放8位数据,AH补0。

段寄存器(由来查看CPU相关部分知识点)

CS和IP的组合寄存器,可以指示CPU当前要读取的指令的地址;
CS 为代码段寄存器
IP 为指令指针寄存器(指令偏移地址)
一个读取指令的流程:

  1. 根据CS:IP算出指令地址(CS*16+IP),读取出这个位置的指令内容。
  2. 将指令存放到指令缓冲器(比如mov ax 18,就是将18存放到ax中)。
  3. IP = IP + 读取的指令长度,算出下一条指令的偏移地址
  4. 重复1步骤读取下一条指令。

CS 存放代码的段地址寄存器 cs:ip
DS 存放数据内容的段地址寄存器
SS 存放栈顶的段地址寄存器,SS:SP结合使用,指向栈顶内存地址。

猫哥
猫哥 项目组成员 2022-08-26
希望我的回答能对你有所帮助

栈 先入后出结构

push ax 将ax中的数据入栈低,放入一段定义为栈的内存区域中的最高危地址空间。
pop ax 将栈顶中的第一个元素取出放入ax中。
push ds
pop ds 将段寄存器的数据入栈或出栈到段寄存器
push [0]
pop [0] 将偏移为0处内存的字数据入栈或出栈

那CPU怎么知道一段内存是栈呢?CPU怎么知道那个是栈顶单元?
通过SS:SP指向栈顶内存地址。
push ax 就相当于 sp = sp - 2;
pop ax 就相当于 sp = sp + 2;
当栈为空时,sp 为栈底内存地址 - 1;

如何保证入栈、出栈不超出栈空间?
超出栈的行为称之为栈益处,是很危险的。

mov ax,1000
mov ss,ax 设置栈的段地址为1000,不能直接向段寄存器赋值
mov sp,0010 设置栈顶偏移地址,加入设计的栈空间范围是 10000~1000F。那么栈底地址是1000F,sp就是000F+一个字节=0010.
push ax
push bx 分别将ax bx入栈,两次入栈后 sp=0010-2-2=000C

猫哥
猫哥 项目组成员 2022-08-24
希望我的回答能对你有所帮助

位 b

内存的最小存储单位,一个位上能表示0或1。

字节 byte B

一个字节通常只8位长,1byte=8b 1B=8b, 可以存储一个8位的无符号数,范围0~255。一般4个字节代表一个字。
1kb = 1024byte
1mb = 1024kb

字 word

字为机器处理指令的最小单位,也就是机器单次最少处理一个字的指令。字长代表字的位数,表示机器一次可以处理的二进制位数,比如32 64位机器,就是指单次处理32 64位的数据。
字长是衡量计算机性能的一个重要指标。
存储器中,通常每个存储单元存放一个字,因此每个字都是可以寻址的。

mov word ptr ds:[0] 1 //应该这里使用word ptr 所以1是一个字型数据,16位的1,0001H。
mov byte ptr ds:[0] 1 //这里是字节数据,01H

猫哥
猫哥 项目组成员 2022-08-24
希望我的回答能对你有所帮助

汇编语言的组成

  • 汇编指令,核心。
  • 伪指令
  • 其他符号

汇编指令(不区分大小写)

mov ax,18 将18存 入ax中
mov ah,78 将78存入ah(ax中的高段位)
add ax,8 对ax中的值加8
mov ax,bx 将bx中的数据存入ax中
add ax,bx 对ax中的数据加上bx中的数据

猫哥
猫哥 项目组成员 2022-08-29
希望我的回答能对你有所帮助

中断向量表

中断向量表在内存中保存,其中存放了256个中断源所对应的中断处理程序的入口地址。
CPU使用8位的中断类型码获取中断源程序地址。8位码则对应了包含256项信息的中断向量表。
中断过程:

  1. 取得中断类型码N
  2. pushf 保存当前标志信息入栈
  3. TF=0 IF=0
  4. push cs push ip 入栈当前指令位置信息
  5. ip = N4, cs = N4+2 获取中断向量表中的入口地址并赋值给指令指针寄存器cs:ip去执行。

恢复过程:使用iret指令

  1. pop ip pop cs
  2. popf
猫哥
猫哥 项目组成员 2022-08-29
希望我的回答能对你有所帮助

CPU对端口的访问
CPU通过端口访问各个设备的数据。对端口的读写使用in和out两个指令。

in al,60h   从60h端口读入一个字节
out 61h,al  向61h端口写入一个字节
猫哥
猫哥 项目组成员 2022-08-26
希望我的回答能对你有所帮助

LOOP循环指令

loop在循环是,循环次数由cx的值决定,它存放有循环的次数,cx=0退出循环,例子:2^12

mov ax,0          ax复制为2
mov cx,12         设定循环次数为11
s: add ax,ax      循环体s 执行ax叠加运算
loop s            判断cx后,执行循环s,每次执行后cx = cx -1 
猫哥
猫哥 项目组成员 2022-08-25
希望我的回答能对你有所帮助

存储器

从读写属性上看,可以分为:

  • 随机存储器 RAM,断电数据丢失。
  • 只读存储器 ROM,数据永久保存。比如主板、显卡、网卡等上的BIOS(基础输入输出系统)就含有ROM。

各个电子设备的存储单元,在逻辑上可以看做一块完整的逻辑存储器。每个物理的存储器在这个逻辑存储器中占有一个专用地址空间。CPU对这个空间进行读写操作就是对这个设备进行操作。

不同计算机系统拥有不同的内存地址空间分配方案。通常RAM主存储空间在低地址段,ROM等在高地址段。

16位的CPU,它的内存寻址范围为2的16次方,而外部总线如果是20位,那理论可以寻址2的20次方,如何解决这个问题?
CPU采用 段地址 * 16 + 偏移地址 = 实际内存地址 来升级为可寻址20位内存地址的能力。

在内存中如何存数据?
内存地址从小到大顺序,低位置存放小数据,高位置存放大数据,比如要存储数据4E20,在内存中就是204E。

猫哥
猫哥 项目组成员 2022-08-28
希望我的回答能对你有所帮助

call 与 ref 指令

ret使用栈顶的数据,修改ip内容,从而实现跳转。
retf使用栈顶的数据,修改cs/ip内容,从而现实远跳转。
使用的时候直接用ret/retf即可。(这个其实有种return的意思)

call将当前代码地址cs/ip存入栈中,然后在远跳转。
格式1:call 标号
call的过程就相当于:
push ip
jmp near ptr 标号
ret

格式2:call far ptr 标号。这个过程相当于
push cs
push ip
jmp far ptr 标号
retf

格式3:call 寄存器,相当于:
push ip
mov ip 寄存器。执行新的地址。

格式4:call word prt 内存地址
格式5:call dword prt 内存地址

猫哥
猫哥 项目组成员 2022-08-26
希望我的回答能对你有所帮助

inc指令
inc bx bx自加1

dw指令
定义字数据,dw 0123h,0456h,0789h
就是将这三个字型数据存放入代码内存段中

db指令
定义字符数据,ascii码数据 db 'unix'
mov ax,'a'

dd指令 双字节指令
dd 1 表示00000001H

and 按位逻辑与运算
当两个值都是1,结果为1,其他情况为0.

作用1:将操作对象某位设为0,其他位不变,比如将第4为为0,其他不变
and al,11110111b

or 按位逻辑或运算
当两个值有一个为1,结果为1,两个都是0结果为0.

用法1:将操作对象某位定位1,其他位不变。比如将第4为为0,其他不变
or al,00001000b

div 除法指令*
除数:如果是8位,则被除数就是16位。除数存放在寄存器或数据内存中
被除数:存放在AX、DX

div reg  表示用ax中的数据除以reg

dup指令 重复定义数据指令
db 3 dup('abc') 重复输出3次abc

mul 乘法指令
mul byte ptr ds:[0] 八位数据相乘,就相当于将al和ds偏移0的数据相乘存放在ax,dx(低位存放在ax,高位存放在dx)中。

cmp指令 对两个值进行比较,修改标志寄存器的值
比如cmp ax,ax 就相当于 ax-ax,这时候各标志位的值是:zf=1 pf=1 sf=0 cf=0 of=0
如果 ax=bx zf=1 否则 zf=1
如果 ax>=bx cf=0 否则 cf=1

movsb 将ds:si区域的一个字节传入es:di中,然后根据DF标志位进行递增1或递减1。
movsw 将ds:si区域的一个字传入es:di中,然后根据DF标志位进行递增2或递减2。

pushf popf 将标志寄存器的值入栈和出栈。

int N指令 主动触发N类型的中断。

shl 逻辑左移指令 将寄存器或内存中的数据左移,将最后移出的一位写入cf中,最低位以0补充。比如左移3位,移动要移出3个值,最后移出的那个写入cf中。
shr 逻辑右移指令 将寄存器或内存中的数据右移,将最后移出的一位写入cf中,最高位以0补充。比如右移3位,移动要移出3个值,最后移出的那个写入cf中。

猫哥
猫哥 项目组成员 2022-08-24
希望我的回答能对你有所帮助

CPU和内存

cpu负责运算,而运算的指令和数据则存放在内存中。数据不加载到内存中,cpu是无法使用到这份数据的。
所以你可以认为cpu具有读取内存地址的能力
内存可以被划分为多个存储单元。每个存储单元从0开始编号。
cpu要和内存进行沟通,首先要知道存储单元的地址,然后读取或写入存储的数据。这里的关键词是存储单元地址,操作和数据。

指令和数据

它们在机器面前都是二进制信息。指令是特殊的数据。
同样的一串01代码通过不同类型的总线发送出去就代表了不同的类型信息。
比如0101010101通过控制总线过去就可能是读命令、通过数据总线就代表一串数字、通过地址总线就表示一个内存地址。

总线

CPU和各个芯片、存储单元进行沟通,通过的就是数据总线,他是所有电线路的总称。
逻辑上分为

  • 地址总线
  • 数据总线
  • 控制总线

CPU有N根地址总线,则地址总线的宽度为N,这样CPU可以寻址2的N次方个存储单元。64位CPU指一次可以处理64位的二进制数据,也就是8个字节。如果这时候的总线宽度也为64,表示一次可以传输64位的信息。

cpu与内存通过总线进行沟通的过程

  1. cpu通过地址总线找到内存的地址。
  2. cpu通过控制总线发送控制信息,比如读或者写指令
  3. cpu通过数据总线对1中内存进行2要求的读取或写入数据。

这样CPU就执行了一次完整的指令操作。

那CPU的要执行的指令哪里来的?就是刚才3中通过数据中线读取里的一条数据,他可能就是一条新的指令,像MOV AX,BX。
那第一条CPU指令怎么发起的呢?

处理器加电以后,马上就会尝试执行指令。但此时内存中还没有数据和指令,那要从什么地方找指令呢?
cpu执行的第一条指令并不在内存中,一般内存是由ram组成的 ,而ram不断电,可以保存信息,一旦断电,ram中的信息将会丢失,所以cpu要执行的第一条指令被固化在rom中,rom的地址在ram以外。
cpu读取的第一条指令为一组固定的CS:IP,CS=FFFF IP=OOOO,也就是从FFFF0位置读取第一条指令信息。

学习
记录

发布
问题

分享
好友

手机
浏览

扫码手机浏览