指令

\(和\) (NASM)

$ 相当于本行行首一个隐藏的标号。是当前行的汇编地址。

例如:

jmp near $
infi: jmp near infi
;两者等价

$$ 代表当前汇编段的起始汇编地址,当程序未定义节或段,就默认自称一个汇编段,而且起始的汇编地址是0(程序起始处)。这样,用当前汇编地址减去程序开头的汇编地址(0),就是程序实体的大小。

adc

adc(Add With Carry)带进位加法指令。

要求:

目的操作数可以是8位或16位的通用寄存器和内存单元,源操作数可以是与目的数宽度一致的通用寄存器、内存单元和立即数(目的操作数和源操作数都为内存单元的除外)。

结果:

adc执行时,将目的操作数和源操作数相加,再加上CF位。也就是说,视CF位的状态,再加0或加1.

好处:

adc配合add可以进行16位以上的加法。

adc对OF、SF、ZF、AF、CF和PF的影响视计算结果而定。## add

  • add是加法指令,用于两个数相加

    add 指令需要两个操作数,目的操作数可以是 8 位或者 16 位的通用寄存器,或者指向 8 位或者 16 位实际操作数的内存地址;源操作数可以是相同数据宽度的 8 位或者 16 位通用寄存器、指向 8 位或者 16 位实际操作数的内存地址,或者立即数,但不允许两个操作数同时为内存单元。相加后, 结果保存在目的操作数中。

add有以下几种形式

mov 寄存器, 数据     ;mov ax, 8
mov 寄存器, 寄存器    ;mov ax, bx
mov 寄存器, 内存单元    ;mov ax, 0000:0000
mov 内存单元, 寄存器    ;mov 0, ax

and

逻辑“和”,两者都为真才是真,若0代表假,1代表真,则:

例:

0 and 0 = 0
0 and 1 = 0
1 and 0 = 0
1 and 1 = 1

and 指令的两个操作数都应当是字节或者 字。其中,目的操作数可以是通用寄存器和内存单元;源操作数可以是通用寄存器、内存单元或者 立即数,但不允许两个操作数同时为内存单元,而且它们在数据宽度上应当一致。

例:

and al, 0x55
and ch, cl
and ax, dx
and [label a], ah
and word [label_a], 0xf0f0
and dx, [label_a]

结果:两个操作数对应的各个比特位分别进行逻辑“与”,结果保存在目的 操作数中。

and 指令执行后,OF 和 CF 位被清零,SF、ZF、PF 位的状态依计算结果而定,AF 位的状态未定义。

cmp

cmp:比较指令。需要两个操作数,目的操作数可以是 8 位或者 16 位通用 寄存器,也可以是 8 位或者 16 位内存单元;源操作数可以是与目的操作数宽度一致的通用寄存器、 内存单元或者立即数,但两个操作数同时为内存单元的情况除外。

例:

cmp al, 0×08
cmp dx, bx
cmp [label_a], cx

cmp 指令在功能上和 sub 指令相同,唯一不同之处在于,cmp 指令仅仅根据计算的结果设置相 应的标志位,而不保留计算结果,因此也就不会改变两个操作数的原有内容。cmp 指令将会影响到 CF、OF、SF、ZF、AF 和 PF 标志位

结果:

若ZF=1,则两个数相等

当无符号时,若:

CF=1,则说明有了进位或结尾,cmp是进行的减操作,因此可以看出是结尾,所以oprd1< oprd2

CF=0, 则说明无借位,此时如果ZF=0,说明oprd1-oprd2!=0,因此oprd1>oprd2

当有符号时:

若SF=0, OF=0,则说明此时的值为正数,没有溢出,故 oprd1< oprd2

db、dw和dd

db,b是byte的意思。是以字节为单位,定义一组数据,每个操作数占有1个字节(8bits)

dd,第二个d是double的意思。是以2个字,即4个字节(32bits),每个操作数占用4个字节。

dw,w是word的意思。是以一个字,即2个字节(16bits),每个操作数占用2个字节。

dword:32位## div

8086CPU提供了除法指令div,它可以做两种除法

16位二进制除以8位二进制

要求:被除数在AX中,除数可以由8位通用寄存器或内存单元提供。

结果:商在AL中,余数在AH中。

例:

div cl
div byte [0×0023]

前一条指令中,寄存器 CL 用来提供 8 位的除数。假如 AX 中的内容是 0x0005,CL 中的内容 是 0x02,指令执行后,CL 中的内容不变,AL 中的商是 0x02,AH 中的余数是 0x01。 后一条指令中,除数位于数据段内偏移地址为 0x0023 的内存单元里。这条指令执行时,处理 器将数据段寄存器 DS 的内容左移 4 位,加上偏移地址 0x0023 以形成物理地址。然后,处理器再次 访问内存,从此处取得一个字节,作为除数同寄存器 AX 做一次除法

32位除以16位

要求:被除数的高16位在DX中,低16位在AX中。除数可以由16位通用寄存器或者内存单元提供。

结果:商在AX中,余数在DX中。

例:

mov dx, 0
mov ax, 0×8
mov bx, 0×3
div bx

equ

伪指令。意为“等于”,相当于C中的宏。

例:

app_lba_start equ 100

本语句的意思是:用标号app_lba_start来代表数值100.

例:

mov al, app_lba_start    ;= mov al, 100

in和out

in和out用于端口的访问

in

指令是从端口读。例:

in al, dx
in ax, dx
in指令的目的操作数必须是寄存器AL或AX。当访问8位的端口时,使用寄存器AL;访问16位的端口时,使用AX。in指令的源操作数应当是寄存器DX。

in指令不影响任何标志位。

out指令是向端口发送数据。

out指令的目的操作数可以是8位立即数或者寄存器DX,源操作数必须是AL或AX。

例:

out 0x37, al    ;写0x37端口(8位)
out 0xf5, ax    ;写0xf5端口(16位)
out    dx, al    ;这是一个8位端口,端口号位于寄存器DX中
out    dx, ax    ;这是一个16位端口。端口号位于寄存器DX中
out指令不影响任何标志位。#### inc

加一指令。

例:

inc bx    ;=add bx, 1

jle

条件转移指令:小于或等于则转移## jmp

jmp是转移指令

例:

jmp 0×5000:0×f0c0    ;将CS:IP指向0×5000:0×f0c0,CPU从此处读取指令
  • 相对近转移

    infi:
    jmp near infi
    在编译阶段,编译器是这么做的:用标号(目标位置)处的汇编地址减去当前指令的

    汇编地址,再减去当前指令的长度(3),就得到了 jmp near infi 指令的实际操作数。

jne

条件转移指令

当ZF=0,转移到标号执行## jns和js

jns:SF=0则转移

js:SF=1则转移## jz(js)条件转移

jz(jump if zero) 即ZF(zero flag)为1跳转

jz的另一种写法就是je,je=jump if equal,jz和je的作用是完全一样的。## loop

循环,每次执行loop它会:

CX的内容减一

如果CX的内容不为零,转移到指定位置处执行,否则顺序执行后面的指令

例:

mov cx, 5    ;循环5次
flagt:
mov ax, 1
loop flagt

loop的指令长度是2## MOV

mov有以下几种形式:

mov 寄存器, 数据     ;mov ax, 8
mov 寄存器, 寄存器    ;mov ax, bx
mov 寄存器, 内存单元    ;mov ax, 0000:0000
mov 寄存器, 段寄存器    ;mov ax, ds
mov 段寄存器, 寄存器    ;mov ds, ax
mov 段寄存器, 内存单元    ;mov ds, 0
mov 内存单元, 寄存器    ;mov 0, ax
mov 内存单元, 段寄存器    ;mov 0, ds

mov指令对以下寄存器有效

通用寄存器:ax, bx, cx, dx

段寄存器:cs, ds, es, fs, gs, ss都无效

变址寄存器:si, di

栈寄存器:sp, bp## movsb和movsw

这两个指令通常用于把数据从内存中的一个地方批量地传送(复制)到另一个地方

区别:

movsb的传送是以字节为单位的,而movsw的传送石以字为单位的。

要求:

原始数据串的段地址由DS指定,偏移地址由SI指定。即    **DS:SI**

传送目的地址由**ES:DI**指定

传送的字节数(movsb)或者字数(movsw)由CX指定。

此外,还要指定是正向传送还是反向传送。

正向传送:传送操作由内存区域的低地址段到高地址段

反向传送:传送操作由内存区域的高地址段到低地址段


每个要显示的字符实际上占两个字节:ASCII码和属性

neg

用0减去操作数。

例:

neg al     ;0-al
neg dx     ;0-dx
neg word [label_a]    ;0-[label_a]

or

逻辑“或”,当两者有一个为真时即为真

or 指令的目的操作数可以是 8 位或者 16 位的通用寄存器,或者包含 8/16 位实际操作数的内存地址,源操作数可以是与目的操作数数据宽度相同的通用寄存器、内存单 元或者立即数。

例:

or al, al

or ax, dx

or [label_a], bx

or byte [label_a], 0x55

or 指令不允许目的操作数和源操作数都是内存单元的情况。当 or 指令执行时,两个操作数相 对应的比特之间分别进行各自的逻辑“或”运算,结果位于目的操作数中


or 指令对标志寄存器的影响是:OF 和 CF 位被清零,SF、ZF、PF 位的状态依计算结果而定, AF 位的状态未定义。

pop

,pop 指令的操作数可以是 16 位的寄存器或者内存单元。

例:

pop ax
pop word [label_a]

pop 指令执行时,处理器将堆栈段寄存器 SS 的内容左移 4 位,再加上堆栈指针寄存器 SP 的内 容,形成 20 位的物理地址访问内存,取得所需的数据。然后,将 SP 的内容加操作数的字长,以指 向下一个堆栈位置。 pop 指令不影响任何标志位。

push

在 16 位的处理器上,push 指令的操作数可以是 16 位的寄存器或者 内存单元。

例:

push ax
push word [label_a]

你可能觉得奇怪,push 指令只接受 16 位的操作数,为什么要对内存操作数使用关键字“word”。 事实上,8086 处理器只能压入一个字;但其后的处理器允许压入字、双字或者四字,因此,关键字 是必不可少的。 就 8086 处理器来说,因为压入堆栈的内容必须是字,所以,下面的指令都是非法的:

push al
push byte [label_a]

处理器在执行 push 指令时,首先将堆栈指针寄存器 SP 的内容减去操作数的字长(以字节为单 位的长度,在 16 位处理器上是 2),然后,把要压入堆栈的数据存放到逻辑地址 SS:SP 所指向的内 存位置(和其他段的读写一样,把堆栈段寄存器 SS 的内容左移 4 位,加上堆栈指针寄存器 SP 提供 的偏移地址)

ret和retf

过程返回 指令

ret 和 retf 经常用做 call 和 call far 的配对指令。ret 是近返回指令,当它执行时,处理器只做一 件事,那就是从堆栈中弹出一个字到指令指针寄存器 IP 中。

retf 是远返回指令(return far),它的工作稍微复杂一点点。当它执行时,处理器分别从堆栈中 弹出两个字到指令指针寄存器 IP 和代码段寄存器 CS 中。

,尽管 call 指令通常需要 ret/retf 和它配对,遥相呼应,但 ret/retf 指令却并不依赖于 call 指令

ret/retf 指令对标志位也没有任何影响。

rol

循环左移(ROtate Left)

ror

循环右移(ROtate Right)。循环右移指令执行时,每右移一次,移出的比特既送 到标志寄存器的 CF 位,也送进左边空出的位。

shl

逻辑左移指令(SHift logical Left)

shr

逻辑右移指令(SHift logical Right)

例:

shr ax, 4     ;将ax中的内容右移4位

逻辑右移指令执行时,会将操作数连续地向右移动指定的次数,每移动一次, “挤”出来的比特被移到标志寄存器的 CF 位,左边空出来的位置用比特“0”填充。

shr 指令的目的操作数可以是 8 位或 16 位的通用寄存器或者内存单元,源操作数可以是数字 1、 8 位立即数或者寄存器 CL。

sub

sub是减法运算, 有以下几种形式

mov 寄存器, 数据     ;mov ax, 8
mov 寄存器, 寄存器    ;mov ax, bx
mov 寄存器, 内存单元    ;mov ax, 0000:0000
mov 内存单元, 寄存器    ;mov 0, ax

times

times是一个伪指令,可用于重复它后面的指令若干次。

例:

times 20 mov ax, bx    ;编译时重复生成mov ax, bx指令20次
times 203 db 0    ;编译时生成203个为0的字节

xor

在数学逻辑中xor是异或(eXclusive OR)的意思,或者叫互斥或、互斥的或运算。

例:若0代表假,1代表真

0 xor 0 = 0
0 xor 1 = 1
1 xor 0 = 1
1 xor 1 = 0

xor 指令的目的操作数可以是通用寄存器和内存单元,源操作数可以是通用寄存器、内存单元 和立即数(不允许两个操作数同时为内存单元)。而且,异或操作是在两个操作数相对应的比特之间单独进行的。

用法:

xor dx, dx    ;清空dx
Last moify: 2022-12-04 15:11:33
Build time:2025-07-18 09:41:42
Powered By asphinx