SCAU 汇编语言第三章复习

寻址方式

1,立即寻址
直接将操作数放在指令中,例如
mov al,5;
mov ax,3064H
2,寄存器寻址方式
将操作数放在寄存器中,对寄存器进行操作
mov bx,5; 这个是直接寻址
mov ax,bx ;这个就是寄存器寻址

在8086中,把操作数的偏移地址称为有效地址,用EA来表示
基址:存放在基址寄存器中的值(如bp,bx)
变址:和上面的同理(si,di)
位移量;8,0,16位
段跨越前缀:用段跨越前缀来改变系统所指定的默认段,例如可以不用ds段来保存数据,用es来保存数据,不过此时就要使用段跨越前缀。但有以下几种情况不能使用段跨越前缀:
1,串处理指令自能用es段
2,push,pop只能用ss段
3,指令只能放在cs段

3,直接寻址:
操作数的有效地址只包含位移量,其值放在指令操作码后,如:mov ax,[2000H],这个代表将以2000h为偏移地址,以ds为数据段,将这个地址里面的字数据赋给ax。

4,寄存器间接寻址:
将直接寻址里面的地址用寄存器来存,只能使用基址寄存器和变址寄存器(bx,bp,si,si),注意其他的寄存器不行!但使用bp时段为ss段,其余的段为ds段。

使用段跨越前缀:mov ax,es:[bx],在这个时候段不再为ds,而是为es。

5,寄存器相对寻址:
操作数的有效地址为基址寄存器或变址寄存器内容和指令中指定的位移量之和。
如:mov ax,count[si]或者[count+si],这里count自行定义。

使用段跨越前缀:mov dl,es:count[si]

6,有效地址为一个基址寄存器和一个变址寄存器。
如:mov ax,[bx][ddi

7,相对基址变址寻址:
如:mov ax,count[bx][si]

8,比例变址寻址:
如:这里寄存器只能用变址寄存器。
mov ax,count[si*4]

其余的不常用。

与转移地址相关寻址方式

1,段内直接寻址:段内进行8位或者16位的转移
jmp near ptr progia:这里表示16位的转移
jmp short quest:这里表示八位的转移
这里的quest或者progia表示的是符号地址

2,段内间接寻址:除立即数外的任何寻址方式
jmp bx:bx保存符号地址偏移量
jmp word prt[bp+table]

注:条件转移指令只能用段内直接寻址的八位位移量

3,段间直接寻址:指令中直接提供段地址和偏移地址
jmp far ptr next
这里far ptr表示段间转移操作符。

4,段间间接寻址:用存储器中两个相继的内容取代cs和ip中原始内容。这里不能用立即数寻址和寄存器寻址,因为寄存器只能存16位,没办法既给cs又给ip。
如:jmp dword ptr [in]

指令系统

mem:内存,reg:寄存器,data:立即数,segreg:指定的段寄存器,ac:累加器。

1,mov:
mov mem/reg1,mem/reg2,这里不能两个都为mem,且reg不能为段寄存器。
mov reg,data
mov ac,mem
mov mem,ac
mov mov segreg,mem/reg:这里segreg不为cs寄存器,且这条指令不响应中断,要这条的下一条才有可能响应 。
注:mov指令不影响标志位。

2,push:
push src(reg,mem,segreg),且不能用立即数寻址方式
执行时:
( sp)←(sp)-2
( (sp)+1,(sp))←(src)
且我们应该知道push指令只能Push字数据,不能Push字节数据,而且这里必须是sp先减2,再将数据压入栈中,

3,pop:
pop dst(reg,mem,sergeg),这里跟push相差了一个data,因为不存在将一个数据弹出到立即数里面这种情况
( (sp)+1,(sp))←(dst)
( sp)←(sp)+2

而且这里我们应该知道sp是指向栈顶的,所有压栈的时候sp自然要减,这样子才能压入,反过来则一定要增,而且这里也符合高位高地址,低位低地址,并且push和pop也不影响标志位。
亚洲
压栈的过程
出栈同理,不多赘述

4,xchg:用来交换两个操作数之间的值,且必须有一个操作数在寄存器中
格式:xchg opr1,opr2
注意:
* 不影响标志位
* 不允许使用段寄存器
* 不允许两个字段都来自存储器

由此可得说明可以两个寄存器之间交换值或者在寄存器和存储器之间交换值
如:

XCHG BX, [ BP+SI ]
XCHG AL, BH

IN/OUT指令:(这里只能使用AL或AH),这两个指令用来让cpu和外界进行交换数据,且只有这两个指令可以实现
输入指令 IN (I/O → CPU)

输出指令 OUT (CPU → I/O)

注:8086用于寻址端口号的总线宽度为16,故其最多可以访问65536个端口号,而每个端口号最大可以对外读出或写入一个字,也就是十六位数据。而端口号一共64k个,所以不需要分段,而且这两个操作也不影响标志位。

其寻址方式有两种:
1,立即寻址:前256个端口可以直接用立即寻址给出
2,DX间接寻址:超过256个后,需要用DX来保存端口号来进行数据交换

CPU与外设进行数据交换时,读出或写入的数据存放的位置只能是:
AL(读取8位数据时)
AX(读取16位数据时)

5,输入指令 IN (I/O → CPU)

 长格式(直接):     IN   AL, PORT   (字节)
                   IN   AX, PORT   (字)
 执行操作:         (AL)  ←  ( PORT ) (字节)
                  (AX)  ←  ( PORT+1,  PORT )(字)

  短格式(DX间接):    IN   AL, DX   (字节)
                     IN   AX, DX   (字)
  执行操作:          (AL)  ←  ( (DX) ) (字节)
                     (AX)  ←  ( (DX)+1,  (DX) )(字)

输出指令 OUT (CPU → I/O)

长格式: OUT PORT, AL (字节)
OUT PORT, AX (字)
执行操作:( PORT ) 👈 (AL) (字节)
( PORT+1, PORT ) 👈 (AX)(字)

短格式: OUT DX, AL (字节)
OUT DX, AX (字)
执行操作:( (DX) ) 👈 (AL) (字节)
( (DX)+1, (DX) ) 👈 (AX)(字)

如:测试第27H号端口的第二位是否为1
IN AL,27H
TEST AL,00000010B
JNZ ERROR:不为0则跳到error

6,换码指令:xlat
XLAT 或 XLAT OPR
执行操作:(AL) ← ( (BX) + (AL) )

解释:xlat适用于快速查表,但在使用前要先用bx来指定表头的首地址,而al则可以当作需要查的表相对表头的偏移量,到时候就将查到的表中的值传送给al
举例:
MOV BX, OFFSET TABLE ; (BX)=0040H
MOV AL, 3
XLAT TABLE
这样会将这个以0040H为表头的表格的第四号字节元素传输给al。
而这样子就可以把原本al的值换成现在在表中的那个值,所以这个叫做换码指令。

注:

  • 不影响标志位
  • 字节表格(长度不超过256)
    首地址 👉 (BX)
  • 需转换的代码位移量 👉 (AL)

7,地址传送指令:
有效地址送寄存器指令: LEA REG, SRC
执行操作:   (REG) 👈 SRC

指针送寄存器和DS指令: LDS REG, SRC
执行操作: (REG) 👈(SRC)
(DS) 👈 (SRC+2)
相继二字 👉 寄存器、DS

指针送寄存器和ES指令: LES REG, SRC
执行操作: (REG) 👈 (SRC)
(ES) 👈 (SRC+2)
相继二字 👉 寄存器、ES

这里lea就是把src的偏移地址的值赋给reg,
lds则是将src的值赋给reg,并且将接下来的字数据赋值给ds。
les和lds有点相似,不过是将字数据赋值给es而不是ds。
例:LEA BX, [BX+SI+0F62H]
LDS SI, [10H]
LES DI, [BX]

8,接下来为一连串标志寄存器传送指令,了解下即可:
LAHF:标志送AH(load AH with flags),且这里是低八位送到AH

SAHF:AH送标志(save flags into AH),同理这里是送到低八位里面

PUSHF/PUSHFD: 标志进栈

POPF/POPFD :标志出栈

9,类型转换数据:
CBW AL 👉 AX
执行操作: 若(AL)的最高有效位为0,则(AH)= 00H
若(AL)的最高有效位为1,则(AH)= FFH

CWD AX 👉 (DX,AX)
执行操作:若(AX)的最高有效位为0,则(DX)= 0000H
若(AX)的最高有效位为1,则(DX)= FFFFH

注:这里一般用于扩充字长。因为负数在计算机中用补码来存储,所以其值不会改变,同理这里也不不会影响标志寄存器的值

10,加法指令:

加法指令: ADD DST, SRC
执行操作: (DST) 👈 (SRC) + (DST)

带进位加法指令: ADC DST, SRC
执行操作: (DST) 👈 (SRC) + (DST) + CF

加1指令: INC OPR
执行操作: (OPR) 👈 (OPR) + 1

注意:

  • 除INC指令不影响CF标志外,均对条件标志位有影响。

一些常见标志位:
SF:结果为负则为1,否则为0
ZF:结果为0则为1,否则为0
CF: 和的最高有效位 有 向高位的进位为1,否则为0
OF:两个操作数符号相同,而结果符号与之相反则为1,否则为0

在这里插入图片描述

在这里如果当作带符号数来看的话,这个数字则为补码,否则就是看其原码

注:指令执行后, CF和OF无论如何都会按照定义进行设置,

但它们的值是否有意义, 取决于把加法看作带符号数还是无符号数加法.

11,减法指令:
减法指令: SUB DST, SRC
执行操作: (DST) 👈 (DST) - (SRC)

带借位减法指令: SBB DST, SRC
执行操作: (DST) 👈 (DST) - (SRC) - CF

减1指令: DEC OPR
执行操作: (OPR) 👈 (OPR) - 1

求补指令: NEG OPR
执行操作: (OPR)👈 - (OPR)

比较指令: CMP OPR1, OPR2
执行操作: (OPR1) - (OPR2)

注:只有dec不影响标志位

减法指令对标志位的影响:
这里是其对标志位的影响请添加图片描述

12,乘法指令:
无符号:mul src
有符号: imul src ,这里src和另一个数是补码形式,使用时记得将其转换为原本的真值
在这里面隐藏的默认的另一个乘数保存在al或ax中,在这里src不能为立即数,在这里除了cf和of外,对其他的标志位没有定义(即其他的标志位没有任何意义,可以不用考虑)
注:
有符号乘法中将两个操作数看作原数的补码,计算完成后将结果存入相应寄存器中。

对标志位的影响:
请添加图片描述

13,除法指令:
无符号数除法指令: DIV SRC
带符号数除法指令: IDIV SRC
执行操作:
字节操作 (AL) 👈 (AX) / (SRC) 的商
(AH) 👈 (AX) / (SRC) 的余数

字操作 (AX) 👈 (DX, AX) / (SRC) 的商
(DX) 👈 (DX, AX) / (SRC) 的余数

注意: * AX (DX,AX) 为隐含的被除数寄存器。
* AL (AX) 为隐含的商寄存器。
* AH (DX) 为隐含的余数寄存器。
* SRC不能为立即数。
且除法指令对任何的标志位都没有定义,所以除法指令不用管标志位,需要自己注意是否溢出

14,十进制表示指令:

BCD码:用二进制编码的十进制数,又称二–十进制数
压缩的BCD码:用 4 位二进制数表示 1 位十进制数
例:( 59 )10 =( 0101 1001 )BCD
非压缩的BCD码:用 8 位二进制数表示 1 位十进制数
例:( 59 )10 =( 0000 0101 0000 1001 )BCD

(1)压缩的BCD码调整指令
● DAA 加法的十进制调整指令
● DAS 减法的十进制调整指令
(2)非压缩的BCD码调整指令
● AAA 加法的ASCII码调整指令
● AAS 减法的ASCII码调整指令
● AAM 乘法的ASCII码调整指令
● AAD 除法的ASCII码调整指令

例子:
压缩:
在这里插入图片描述

非压缩:
在这里插入图片描述

15,逻辑运算指令:
NOT,and,or,xor,test(都不影响标志位)

使用方法:
例:屏蔽AL的第0、1两位

        AND  AL, 0FCH

例:置AL的第5位为1

        OR  AL, 20H

例:使AL的第0、1位变反

        XOR  AL, 3

例:测试某些位是0是1

        TEST  AL, 1
        JZ       EVEN

16,移位指令:在这里移动位数可以用立即数寻址外的任何寻址方式,移动位数为1时可以用立即数寻址,其他不行
逻辑左/右移:将最高/低位移到CF里面。(SHL al,位数)
算术左移:和逻辑左移一样(SRL)
算数右移:最低位移入CF,最高位不变(SAR)
循环左移:将最高位移入cf并且移入最低位(rol)
循环右移:将最低位移入cf且移入最高位(ror)
带进位循环左移:把cf当作操作数的最高位一起进行循环左移(rcl)
带进位循环右移:把cf当做操作数最低位一起进行循环右移(rcr)

CNT=1,SHL OPR, 1
CNT>1,MOV CL, CNT
SHL OPR, CL ; 以SHL为例

  • 条件标志位:
    CF = 移入的数值
    1 CNT=1时,最高有效位的值发生变化
    0 CNT=1时,最高有效位的值不变
    移位指令:
    SF、ZF、PF 根据移位结果设置,AF无定义
    循环移位指令:
    不影响 SF、ZF、PF、AF

运算在乘除法里的作用总结:
SAL, SHL用于乘以2的n次方

SAR, SHR用于除以2的n次方(结果只保留商,不含余数)

17,串处理指令:这里只能用es段

     设置方向标志指令
     CLD、STD
     串处理指令                             串重复前缀
      MOVSB  /  MOVSW                         REP
      STOSB  /  STOSW                            REPE  /  REPZ
      LODSB  /  LODSW                           REPNE  /  REPNZ
      CMPSB  /  CMPSW
      SCASB  /  SCASW      

执行 REP MOVS 之前,应先做好:

(1) 源串首地址(末地址)→ SI
(2) 目的串首地址(末地址)→ DI
(3) 串长度 → CX
(4) 建立方向标志
( CLD 使 DF=0,STD 使 DF=1 ) ,DF=0表示正向传输, DF=-1表示反向传输

例子:
在这里插入图片描述
在这里cld表示将df置为0,然后cx表示要传送的字数,然后进行循环

STOS 存入串指令:
STOS DST
STOSB (字节)
STOSW (字)
执行操作:
字节操作:((DI))←(AL), (DI)←(DI)±1
字操作:((DI))←(AX), (DI)←(DI)±2

例:把 附加段 中的 10 个字节缓冲区置为 20H

lea di, mess2
mov al, 20H
mov cx, 10
cld
rep stosb
这里也可以一次性存入一个字,然后存五次也是可以的。

LODS 从串取指令:
LODS SRC
LODSB (字节)
LODSW (字)
执行操作:
字节操作:(AL)←((SI)), (SI)←(SI)±1
字操作:(AX)←((SI)), (SI)←(SI)±2

注意:

  • LODS 指令一般不与 REP 联用
  • 源串一般在数据段中(允许使用段跨越前缀来修改),
    目的串必须在附加段中
  • 不影响条件标志位

CMPS 串比较指令:
CMPS SRC, DST
CMPSB (字节)
CMPSW (字)

执行操作:
(1) ((SI)) - ((DI))
根据比较结果置条件标志位:相等 ZF=1
不等 ZF=0
(2) 字节操作:(SI)←(SI)±1, (DI)←(DI)±1
字操作: (SI)←(SI)±2, (DI)←(DI)±2

SCAS 串扫描指令:
SCAS DST
SCASB (字节)
SCASW (字)

执行操作:
字节操作:(AL) - ((DI)), (DI)←(DI)±1
字操作: (AX) - ((DI)), (DI)←(DI)±2

与 REPE / REPZ(REPNE / REPNZ)配合工作的
CMPS 和 SCAS

 REPE / REPZ 
 REPNE / REPNZ

执行操作:
(1) 如 (CX)=0 或 ZF=0 (ZF=1) 则退出串操作,
否则转(2)
(2) (CX)←(CX) -1
(3) 执行 CMPS / SCAS
(4) 重复 (1) ~ (3)

条件转移指令:

在这里插入图片描述

无条件转移指令:

段内直接短转移:JMP SHORT OPR
执行操作:(IP) ← (IP) + 8位位移量

段内直接近转移:JMP NEAR PTR OPR
执行操作:(IP) ← (IP) + 16位位移量

段内间接转移: JMP WORD PTR OPR
执行操作: (IP) ← (EA)

段间直接远转移:JMP FAR PTR OPR
执行操作:(IP) ← OPR 的段内偏移地址
(CS) ← OPR 所在段的段地址

段间间接转移: JMP DWORD PTR OPR
执行操作: (IP) ← (EA)
(CS) ← (EA+2)

条件转移指令:
格式 测试条件
JZ(JE) OPR ZF = 1
JNZ(JNE) OPR ZF = 0
JS OPR SF = 1
JNS OPR SF = 0
JO OPR OF = 1
JNO OPR OF = 0
JP OPR PF = 1
JNP OPR PF = 0
JC OPR CF = 1
JNC OPR CF = 0

) 比较两个无符号数,并根据比较结果转移*

                       格式           测试条件

<         JB (JNAE,JC)        OPR             CF = 1
≥         JNB (JAE,JNC)        OPR             CF = 0
≤         JBE (JNA)            OPR          CF∨ZF = 1
>        JNBE (JA)           OPR          CF∨ZF = 0

) 比较两个带符号数,并根据比较结果转移*

                  格式           测试条件

  <   JL (JNGE)   OPR           SFOF = 1
  ≥    JNL (JGE)   OPR           SFOF = 0
  ≤    JLE (JNG)   OPR         (SFOF)∨ZF = 1
  >   JNLE (JG)    OPR          (SFOF)∨ZF = 0

循环指令:

循环指令:LOOP OPR
测试条件:(CX) 不为 0

为零或相等时循环指令:LOOPZ(LOOPE) OPR
测试条件:ZF=1 且 (CX) 不为 0

不为零或不相等时循环指令:LOOPNZ(LOOPNE) OPR
测试条件:ZF=0 且 (CX) 不为 0
看着用就行,一般不常用,不过稍微留个印象

子程序自行看,大差不差。

中断:
中断向量:
中断例行程序的入口地址,存放于中断向量区,其中低位为ip,高位为cs。

  • 27
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
scau汇编综合性实验是一个非常有趣的项目,其中有一个实现在屏幕上移动的“蛇”的任务。我们可以使用汇编语言的指令来控制屏幕的输出和键盘输入。 首先,我们需要定义一个表示“蛇”的数据结构。可以使用一个数组来储存蛇的位置信息,每个元素表示一个身体部位的坐标。我们还需要定义一个变量来表示蛇的长度。 接下来,我们需要在屏幕上绘制“蛇”。我们可以使用汇编语言的命令来控制屏幕的像素,实现绘制功能。首先,我们需要清空屏幕上的内容,然后将“蛇”的每个身体部位的坐标对应的像素点设为特定颜色。 在屏幕上移动“蛇”的思路是,通过监听键盘输入来控制“蛇”的移动方向。当用户按下箭头键的时候,我们通过改变蛇头的坐标来实现移动。之后,我们还需要更新蛇身体的坐标信息,最后再次绘制“蛇”。 同时,要确保蛇的移动过程中不会碰到屏幕边界或者自身身体的其他部位。如果蛇头碰到屏幕边界或者自身身体的其他部位,游戏结束。 在游戏进行过程中,还可以加入一些额外的功能,比如蛇吃到食物后身体加长,每移动一步更新分数等。 这个“蛇”的移动实验可以让我们深入理解汇编语言的编程思想,锻炼我们的逻辑思维和创造力。同时,通过这个实验,我们可以将计算机相关知识与生活中的游戏联系起来,更加直观地感受到计算机的奇妙之处。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值