汇编入门

汇编入门

Posted by gxkyrftx on September 15, 2019

1 汇编语言与机器语言

人与计算机交流的语言,需要让计算机做事

人——》汇编语言——》编译器——》机器语言——》计算机

2 进制

逢几进几的运算,不同进制只是表示方法不同,对应同一个数字。意义相同。

3 存储器,CPU

存储器:存储数据,提供数据

  • 外部存储器:硬盘,光盘
  • 内部存储器:RAM(内存条),ROM(BIOS芯片)
  • 一个存储单元存储一个字节

CPU:中央处理器

  • 运算器:数据进行计算
  • 控制器:控制操作步骤

CPU对存储器的读写

  • 通过三根总线读写:地址总线,数据总线,控制总线
  • 地址总线——》寻址能力(80386为32根)
  • 数据总线——》一次数据传输量(80386为32根)
  • 控制总线——》对其他器件的控制能力

4 寄存器

寄存器是CPU内部的组成部分,可以用来暂存指令,数据,地址

  • 8086有14个寄存器,16位,一个字

    4个数据寄存器:AX,BX,CX,DX

    2个变址寄存器:SI,DI

    2个指针寄存器:SP,BP

    4个段寄存器:ES,CS,SS,DS

    1个指令指针寄存器:IP

    1个标志寄存器:Flags

  • 80386有16个寄存器,32位,两个字

    4个数据寄存器:EAX,EBX,ECX,EDX

    2个变址寄存器:ESI,EDI

    2个指针寄存器:ESP,EBP

    6个段寄存器:ES,CS,SS,DS,FS,GS

    1个指令指针寄存器:EIP

    1个标志寄存器:EFlags

32位的通用寄存器通用性更强一些,数据寄存器也可以为指令寄存器

5 简单的汇编指令

mov ax ,11F6H

add al , 0AH

最后ax的值为1100H

6 CS:IP

程序运行时,将代码段加载到内存中,然后CPU在内存中找到代码段,也就是代码的物理地址执行。

物理地址=基础地址+偏移地址

​ =段地址 x 10H + 偏移地址

修改CS:IP可以达到控制程序执行的目的,有两种方法:

  • 同时修改CS:IP的内容

    jmp 段地址:偏移地址

    jmp 2AE3:3 ——》从2AE33H处读取指令

    jmp 3:0B16——》从00B46H处读取指令

  • 修改IP 的内容

    jmp 寄存器

    jmp bx 含义上与 mov IP,bx 相同,因为执行前后的变化为

    bx cs ip  
    0x0B16H 0X2000H 0x0003H 执行前
    0x0B16H 0X2000H 0x0B16H 执行后

7 debug使用

7.1 环境配置

winxp可以直接使用debug,其他的环境需要使用DOSBox+debug.exe。

下载安装,然后在安装目录中找到DOSBox 0.74 Option.bat,打开之后,找到autoexec选项,添加如下字段:

MOUNT C D:\masmpro
set PATH=$PATH$;D:\xxxxx

并且在d盘下创建xxxxx目录,并且放入:debug.exe,edit.com,LINK.EXE,MASM.EXE

7.2 常用操作

  • R:查看更改CPU中,寄存器的值
  • D:查看内存中的内容
  • E:改写内存中的内容
  • U:将内存中的机器指令翻译为汇编指令
  • T:执行一条机器指令
  • A:以汇编的格式在内存中写入一条指令

8 分段管理

物理地址是内存单元的编号。

逻辑地址是用户编程时使用的,形式为(段基址:段内偏移地址),物理地址=段基址x10H+偏移地址

8086CPU有4个段寄存器,用来确定每个逻辑段的起始位置,各个段寄存器含义如下:

  • CS(代码段):指明代码的起始地址,使用方式(CS:IP)
  • SS (堆栈段):指明堆栈段的起始地址,使用方式(SS:SP)
  • DS(数据段):指明数据的起始地址,使用方式(DS:EA)
  • ES(附加段):指明附加段的起始地址,使用方式(ES:EA)

9 标志寄存器

8086的标志位寄存器如下

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1  
        OF DF IF TF SF ZF   AF   PF   CF
  • 状态标志:

    用于记录运行结果的状态信息:CF,ZF,SF,PF,OF,AF

  • 控制标志:

    用于控制处理器执行指令:DF,IF,TF

    寄存器 意义 举例
    CF 进位标志,有进位时flag=1 c2H+c7H=(1)89H,标志位为1
    ZF 零标志位,运算结果为0,flag=1 39H+c7H=(1)00H,标志位为1
    SF 符号标志位,最高位为1,flag=1 2CH+7CH=A8H,标志位为1
    PF 奇偶标志位,字节中1的个数为偶数,flag=1 39H+C7H=(1)00H,标志位为1
    OF 溢出标志,运算有溢出,OF=1 2CH+7CH=A8H,标志位为1
    AF 辅助进位标志,低半字节有进位或借位,flag=1 39H+78H=B1H,标志位为1
    DF 方向标志位,用于串操作中控制地址方向,存储器地址自动减少,flag=1 CLD执行后DF=0;STD执行后DF=1
    IF 中断标志位,中断是否可以被响应,flag=1,允许中断 CLI指令用于复位中断标志,IF=0。STL用于置位,IF=1
    TF 陷阱标志位,控制处理器单步操作的方式。flag=1,单步执行 单步执行指令,可以对程序进行调试

10 指令

指令一般由:操作码+操作数。构成

根据操作数的类型不同,指令的结构可以为:操作码+目的操作数+源操作数

11 寻址方式

指令中数据的存储位置有3种

  1. 存放在指令中(立即数)
  2. 存于寄存器中(寄存器操作数)
  3. 存于存储器中(存储器寻址)

寻址方式

寻址方式 例子 解释
立即数寻址 mov al,80H 源操作数是数据,目的操作数是寄存器
寄存器寻址 mov ax,cx 将寄存器中的值赋给另一个寄存器
直接寻址 mov al,[1064H] 操作数存在内存中,操作数的偏移地址直接在指令中,默认操作数在数据段
寄存器间接寻址 mov ax,[si]####mov [bx],al bx,si,di作为间接寻址寄存器,默认操作数存放于数据段,段寄存器使用DS。bp作为间接寻址寄存器,默认操作数存放于堆栈段,段寄存器使用ss
寄存器相对寻址 mov cl,[bx+1064H] 相对于寄存器间接寻址多了一个偏移量
基址加变址寻址方式 mov ah,[bp] [si] bx,bp是基址寄存器,把si和di变址寄存器,计算时,段寄存器+bp的值+si的值
相对基址加变址寻址方式 mov [bx+di+1234H],ah 比基址加变址寻址方式多了一个偏移量

12 汇编指令

12.1 数据传送指令

12.1.1 通用传送指令

指令 格式 其他
mov mov dst,src 1.存储器操作数之间不能直接传送:mov [1000H],[di]错误,应使用通用寄存器
    2.立即数不能直接送段寄存器: mov ds,1000H
    3.段寄存器之间不能直接传递: mov es,ds
    4.cs只可以作为源操作数: mov cs ,ax
    5.源操作数和目的操作数位数需要相同
push push src sp-2(因为按一个字两个字节为单位操作),然后按“高高低低原则”放入数据
pop pop dst 现弹出数据,然后sp-2
xchg xchg dst,src  

12.1.2 累加器专用传送指令

指令 格式 说明
IN (用于CPU从外设端口中接收数据) IN AL,data8 8位端口输入一字节
  IN AX,data8 8位端口输入一字
  IN AL,DX 16位端口输入一字节
  IN AX,DX 16位端口输入一字
OUT (用于CPU向外设端口中发送数据) OUT data8,AL 给8位端口输出一个字节
  OUT data8,AX 给8位端口输出一个字
  OUT DX,AL 给16位端口输出一个字节
  OUT DX,AX 给16位端口输出一个字
LEA(将源操作数的偏移地址传送到目的操作数) LEA reg16,mem 目的操作数必须是16位的寄存器,
LDS(将源操作数指定的4个相继字节的数据分别送指令到指定的寄存器及DS寄存器) LES reg16 ,mem 先给寄存器赋值,然后,从内存中读取两个字节

12.1.3 地址传送指令

指令 格式 说明
LEA(将源操作数的偏移地址传送到目的操作数) LEA reg16,mem 目的操作数必须是16位的寄存器,
LDS(将源操作数指定的4个相继字节的数据分别送指令到指定的寄存器及DS寄存器) LES reg16 ,mem 先给寄存器赋值,然后,从内存中读取两个字节

12.1.4 标志传送指令

指令 格式 说明
LAHF(标志寄存器的低八位赋值给AH) LAHF psw的低字节——》AH
SAHF(AH的值赋值给标志寄存器) SAHF AH——》psw的低字节
PUSHF PUSHF (SP)《——(SP)-2
    ((SP)+1,(SP))《——(PSW)
POPF POPF (PSW)《——((SP)+1,(SP))
    (SP)《——(SP)+2

12.2 算术运算类指令

加减乘除

12.2.1 加法指令

指令 格式 描述
add(加法指令) add dest,src (dest)《——(dest)+(src)
adc(带进位的加法) adc dest,src (dest)《——(dest)+(src)+C(进位标志)
inc(自增一) inc (dest)《——(dest)+1
aaa(加法ascii调整指令)    
daa(加法十进制调整指令)    

12.2.2 减法指令

指令 格式 描述
sub (减法指令) sub dest,src (dest)《——(dest)-(src)
sbb(带进位的减法指令) sub dest,src (dest)《——(dest)-(src)- C
dec(自减1指令) dec (dest)《——(dest)-1
neg(求补指令) neg dest (dest)《—— 0 -(dest)
cmp(比较指令) cmp dest,src 不影响结果,只改变标志位

12.2.3 乘法指令

指令 格式 描述
mul(无符号乘法) mul src 1.字节操作数:ax《——(al)*(src)
    2.字操作数:dx:ax《——(ax)*(src)
imul(带符号乘法) imul src  

12.2.4 除法指令

指令 格式 描述
div(除法) div src 1.字节除数:al《——(ax)/(src)之商
    ah《——(ax)/(src)之余数
    2.字除数:ax《——(dx:ax)/(src)之商
    dx《——(dx:ax)/src 之余数
idiv(带符号除法) idiv src  

12.2.5 字节扩展指令

指令 格式 描述
cbw cbw 将al扩展为字,符号位和高字节在ah中,对被除数进行扩充

12.2.6 字扩展指令

指令 格式 描述
cwd cwd 将ax扩展为双字,符号位和高字在dx中,对被除数进行扩充

12.3 位操作类

12.3.1 逻辑运算指令

指令 格式 描述
and and dest ,src (dest)《——(dest)^(src)
test test dest,src (dest)^(src)
or or dest ,src (dest)《——(dest)||(src)
xor xor dest ,src 不同为1,相同为0
not not dest 按位取反

12.3.2 移位指令

以下指令格式均为:操作码 寄存器/内存 ,数字

指令 描述
sal(算术左移) 相当于无符号数乘2,末尾补0
sar(算术右移) 最高位不变,最低位移入CF
shl(逻辑左移) 相当于无符号数乘2,末尾补0
shr(逻辑右移) 相当于无符号数除以2,高位补0,地位进入CF
rol(不含进位标志循环左移) 高位的数放到低位,同时放入CF中
ror(不含进位标志循环右移) 低位的数放到高位,同时放入CF中
rcl(带进位循环左移) 将原先的CF存入低位,左移后的高位放入CF
rcr(带进位循环右移) 将原先的CF存入高位,右移后的低位放入CF

12.4 串操作指令

串操作,也叫数据块操作。串是内存中一段相连的字节或字,可以实现存储器数据块之间的直接传送。

指令 格式 描述
movs(串传送指令) movsb (ES:DI)《——(DS:SI)
    (SI)《——(SI)+/- 1
    (DI)《——(DI)+/- 1
  movsw (ES:DI)《——(DS:SI)
    (SI)《——(SI)+/- 2
    (DI)《——(DI)+/- 2
	mov ax,1000H
	mov ds,ax;数据段地址赋值
	mov ax,1000H
	mov es,ax;附加段赋值
	mov si,0013H;源数据块首地址
	mov di,1004H;目的数据块首地址
	mov cx,4;数据块长度赋计数器
	std
lp:
	movsb;完成一个字节的数据传送
	dec cx;计数器减一
	jnz lp;结果不为0,重复传送
	hlt
lpwithoutmovsb:
	mov ax,[si]
	mov es:di,ax
	dec si
	dec di
	dec cx
	jnz lpwithoutmovsb
lpuserep:
	rep movsb
	hlt

指令 格式 描述
lods(串中取数指令) lodsb (AL)《——(DS:SI)
    (SI)《——(SI)+/- 1
  lodsw (AX)《——(DS:SI)
    (SI)《——(SI)+/- 2
stos(存入串指令) stosb (ES:DI)《——(AL)
    (DI)《——(DI)+/- 1
  stosw (ES:DI)《——(AX)
    (DI)《——(DI)+/- 2
cmp(比较指令) cmpsb (ES:DI)《——(DS:SI)
    (SI)《——(SI)+/- 1
    (DI)《——(DI)+/- 1
  smpsw (ES:DI)《——(DS:SI)
    (SI)《——(SI)+/- 2
    (DI)《——(DI)+/- 2
scas(串扫描指令) scasb (AL)-(ES:DI)
    (DI)《——(DI)+/-1
  scasw (AX)-(ES:DI)
    (DI)《——(DI)+/-2
;cmps和scas可与前缀repe/repz/repne/repnz联合工作
;repe 相等时重复操作
;repz 为0时重复操作
;repne 不相等时重复操作
;repnz 不为0时重复操作
mov edi,s1
mov esi,s2
mov ecx,0xFFFFFFFF
xor eax,eax;先清空eax
repne scasb;等到eax=0时,停止接收数据
not ecx;计算得到的字符串长度
mov edi,s1
mov esi,s2
xor edx,edx
repe cmpsb;不相等则退出

12.5 程序控制指令

12.5.1 转移指令

控制程序从一处转向另一处执行,目标地址赋值给CS:IP实现

12.5.1.1 根据标志位判断转移

指令 格式 描述
jmp(强制跳转) jmp xx 无条件跳转
jz/jnz(根据z标志位判断跳转)    
jc/jnc(根据c标志位判断跳转)    
jp(jpe)/ jnp(jpo)(根据p标志位判断跳转)    
js/jns(根据s标志位判断跳转)    
jo/jno(根据o标志位判断跳转)    

12.5.1.2 根据两个无符号数的大小判断转移

指令 格式 描述
jb(低于跳转)    
jbe(不高于跳转)    
ja(高于跳转)    

12.5.1.3 根据两个带符号数的大小判断

指令 格式 描述
jl(jnge)/jnl(jge)(小于跳转/不小于跳转)    
jle(jng)/jnle(jg)    

12.5.2 过程(子过程)调用指令

子程序——程序中具有独立功能的部分编写成独立程序模块

指令 格式 描述
call 子过程名    
ret   返回主程序

12.5.3 循环控制指令

指令 格式 描述
loop(无条件循环) loop Lable (CX)《——(CX)-1
    CX 不等于0,转向Lable;CX=0,执行loop后面的语句
loopz/loope(有条件跳转) loopz/loope Lable (CX)《——(CX)-1
    CX 不等于0,并且ZF=1,转向Lable;否则,执行loop后面的语句
loopnz/loopne(有条件跳转) loopnz/loopne Lable (CX)《——(CX)-1
    CX 不等于0,并且ZF=0,转向Lable;否则,执行loop后面的语句

12.5.4 中断指令

指令 格式 描述
中断调用 int n n的范围为0-255
中断返回 iret  

12.6 处理器控制指令

12.6.1 标志处理指令

指令 描述
clc 清c标志
stc 置c标志
cmc 对c求反
cld 清d标志
std 置d标志
cli 清i标志
sti 置i标志

12.6.2 其他处理机控制机制

指令 描述
nop 空操作
hlt cpu暂停状态
wait cpu等待状态
esc 交权
lock 总线锁定

本文访问量: