16位汇编语言程序设计笔记[钱晓捷版][自用]

文章目录

  • 第一章 汇编语言基础知识
      • (1)熟悉寄存器组和存储器组织
      • (2)物理地址和逻辑地址
      • (3)7种寻址方式
        • 立即数寻址方式
        • 寄存器寻址方式
        • 存储器寻址方式
      • (4)(补充)计算机系统
  • 第二章 8086的指令系统
      • (1)常用传送指令:
      • (2)加减法指令
        • 加法指令
        • 减法指令
        • 乘法指令
        • 除法指令
        • 符号扩展指令
      • (3)逻辑运算和移位指令
        • 逻辑运算指令
        • 移位操作
      • (4)控制转移指令
        • 无条件转移指令
        • 条件转移指令
        • 循环指令
        • 子程序指令
  • 第三章 汇编语言程序格式
      • (1)硬指令和伪指令的区别
      • (2)标号、名字和标识符
      • (3)简化段定义格式
      • (4)汇编语言程序的开发过程
      • (5)常数的表达
      • (6)变量定义伪指令DB/DW/DD
      • (7)地址操作符和类型操作符(EQU、ORG、$、OFFSET、SEG、PTR、THIS、SHORT、TYPE、SIZEOF、LENGTHOF)
      • (8)了解几种程序段的属性
  • 第四章
      • (1)分支结构程序设计
      • (2)循环结构程序设计
        • 串操作类指令
          • 串传送指令
          • 串检测指令
          • 串扫描指令
      • (3)子程序结构程序设计
  • 第六章
      • (1)实地址工作方式
      • (2)32位保护方式
      • (3)虚拟8086方式
      • (4)32位寄存器组合寻址方式
  • 第七章
      • (1)嵌入式汇编
      • (2)模块连接

第一章 汇编语言基础知识

(1)熟悉寄存器组和存储器组织

  • 通用寄存器
    • 数据寄存器
      • AX累加器
      • BX基址寄存器
      • CX计数器
      • DX数据寄存器
    • 变址寄存器
      • SI源地址寄存器
      • DI目的地址寄存器
    • 指针寄存器
      • BP基址指针
      • SP堆栈指针
  • 标志寄存器 FLAGS
  • 指令指针 IP
  • 段寄存器 CS SS DS ES

(2)物理地址和逻辑地址

8086的地址线是20位的,最大可寻址空间为1MB,8086将1MB存储器空间分为许多逻辑段,每个段最大限制为64KB。段地址必须是模16地址❗,即xxxx0H形式,省略低四位的0,段地址可以用16位数据表示。
段内偏移地址:说明主存单元距离段起始位置的偏移量,限定每段不超过64KB,因此偏移地址也可以用16位数据表示。

(3)7种寻址方式

立即数寻址方式

mov al,05h

寄存器寻址方式

mov ax,bx

存储器寻址方式

  • 直接寻址方式 可以段超越,以下均可以的意思
mov ax,[2000h]
  • 寄存器间接寻址方式
mov ax,[bx/si/di]
  • 寄存器相对寻址方式
mov ax,[bx/bp/si/di + 06h] ;bp默认ss,其他默认ds
  • 基址变址寻址方式
mov ax,[bx/bp+si/di];bx和bp分别对应ds和ss
  • 相对基址变址寻址方式
mov ax,[bx/bp+si/di+06h]

(4)(补充)计算机系统

  • 冯诺依曼计算机有五大部件:控制器、运算器、存储器、输入设备和输出设备
  • 现代计算机由五大部件演变为三个硬件子系统:处理器(微型计算机里叫微处理器)、存储系统和输入/输出系统。
  • 8086的功能结构:内部结构分为执行单元EU和总线接口单元BIU。

第二章 8086的指令系统

(1)常用传送指令:

  • MOV
mov reg/mem,imm
mov reg/mem/seg,reg
mov reg/seg,mem

也就是说 不允许imm–>seg,mem–>mem,imm不能作为目的操作数

  • XCHG
xchg	reg,reg/mem		;reg<-->reg/mem
  • PUSH
    入栈会使SP减2,也就是进行16位数的操作。低地址存放于低地址,高地址存放于高地址。
    先进行sp-2!
push r16/m16/seg	;r16:16位的寄存器,m16:16位的存储器单元。
					;sp<-sp-2, ss:[sp]<-r16/m16/seg
  • POP
    出栈会使SP加2,也就是进行16位数的操作。低地址送低地址,高地址送高地址。
    先送出数据!
pop r16/m16/seg		;r16:16位的寄存器,m16:16位的存储器单元。
					;sp<-sp-2, ss:[sp]<-r16/m16/seg
  • LEA
    将存储器操作数的有效地址传送至指定的寄存器。
lea r16, mem
mov bx, 0400h
mov si, 3ch
lea bx, [bx+si+0f62h]	;bx<-bx+si+0f62h=0400h+3ch+0f62h=139eh

BX将会得到主存单元的有效地址,而不是物理地址,也不是该单元的内容。

(2)加减法指令

加法指令

  • ADD:按照状态标志的定义设置标志的0和1状态,不能mem+mem
add reg,imm/reg/mem
add mem,imm/reg

也就是说,不能进行mem+mem,(减法其实也是一样的

  • ADC:加进位CF,主要用于与ADD指令结合实现多精度相加
mov ax,1111h
add ax,1111h
mov dx,1111h
adc dx,1111h  ;结束后,DX.AX为所需值 假装有进位吧
  • INC:增量,单操作数指令,操作数可以是reg/mem,不影响CF,那么问题来了 你还记得CF是进位标志吗❓

减法指令

  • SUB:支持类型同ADD指令
  • SBB:带借位减法指令,还要减去借位CF,主要用于实现多精度相减
mov ax,1111h
sub ax,1111h
mov dx,1111h
sbb dx,1111h ;完成后DX.AX即为目标值,假装这里有借位
  • DEC:减量,同INC
  • NEG:求补,将操作数按位取反再加1,对标志的影响同用0做减法的SUB一样
  • CMP:比较指令,与SUB支持类型相同,影响标志但不改变目的操作数

乘法指令

乘法指令隐含使用操作数AX和DX,AL与r8/m8相乘,存入AX,AX与r16/m16相乘,存入DX.AX。

OF,CF有定义,对其他无。如果高一半没有有效数值(对MUL指令来说高一半为0,对IMUL指令来说高一半是低一半的符号扩展),则OF=CF=0,否则OF=CF=1。

  • MUL:无符号乘法
  • IMUL:有符号乘法,结果不同

除法指令

除法指令隐含使用DX,AX作为一个操作数,被除数哦,AX除以r8/m8,8位商和余数分别存存AL、AH。DX.AX除以r16/m16,16位商和余数分别存AX,DX

  • DIV:无符号数除法
  • IDIV:有符号数除法

符号扩展指令

对于无符号数据:零位扩展,8086没有设计指令,需要时可以直接对高位赋0
对于有符号数据:符号扩展

  • CBW:将al的最高有效位D7扩展至ah,如果al的最高有效位为0,则ah=00,al的最高有效位为1,则ah=ffh,al不变。(bw可以想成byte to word
  • CWD:将ax的内容符号扩展形成dx,同上(wd可以想成word to double

(3)逻辑运算和移位指令

逻辑运算指令

  • AND:逻辑与运算,所有双操作数的指令均设置CF=OF=0,根据结果设置SF、ZF、PF,对AF未定义
    no mem–mem!!
and reg,imm/reg/mem
and mem,imm/reg
  • OR:同上
  • XOR:同上,常用于求反某些位/清零寄存器
  • NOT:not reg/mem
  • TEST:对两个操作数进行and操作,但只设置标志位

移位操作

  • 逻辑左移 shl reg/mem,1/c1
  • 逻辑右移 shr 补0
  • 算数左移 sal 同逻辑左移
  • 算数右移 sar 补最高位
    算数的sa shift+arithmetic,逻辑sh只是单纯的shift
  • rol 不带进位循环左移
  • ror 不带进位循环右移
  • rcl 带进位循环左移
  • rcr 带进位循环右移

(4)控制转移指令

无条件转移指令

  • 段内转移,相对寻址:jmp label
  • 段内转移,间接寻址:jmp r16/m16 只改变IP值
  • 段间转移,直接寻址:jmp far ptr label
  • 段间转移,间接寻址:jmp far ptr mem 用一个双字存储单元表示要跳转到的目的地址,低位字送IP寄存器,高位送CS

条件转移指令

jcc label

助记符 标志位 含义
JZ/JE ZF=1 等于0(and)/相等(cmp)跳转
JNZ/JNE ZF=0 不等于0/不相等跳转
JS SF=1 符号为负跳转
JNS SF=0 符号为正跳转
JP/JPE(even) PF=1 "1"的个数为偶数跳转
JNP/JPO(odd) PF=0 "1"的个数为奇数跳转
JO OF=1 溢出跳转
JNO OF=0 无溢出跳转
JC/JB/JNAE CF=1 进位/低于/不高于等于跳转
JNC/JNB/JAE CF=0 无进位/不低于/高于等于跳转
JBE/JNA CF=1 或则 ZF=1 低于等于/不高于跳转
JNBE/JA CF=0 并且 ZF=0 不低于等于/高于跳转
JL/JNGE SF≠OF 小于/不大于等于跳转
JNL/JGE SF=OF 不小于/大于等于跳转
JLE/JNG SF≠OF 或则 ZF=1 小于等于/不大于跳转
JNLE/JG SF=OF 或则 ZF=0 不小于等于/大于跳转

循环指令

  • jcxz label:cx=0则转移
  • loop label:先cx=cx-1,若cx!=0则循环
  • loopz/loope label:cx!=0 && zf=1则循环
  • loopnz/loopne label:cx!=0 && zf=0则循环

子程序指令

  • CALL指令:可以分为段内调用和段间调用,4种格式类似于jmp指令
  • RET指令:
    • RET:无参数段内返回

    • RET i16:有参数段内返回,ip<–ss:[sp],sp<–sp+2,sp<–sp+i16

第三章 汇编语言程序格式

(1)硬指令和伪指令的区别

  • 硬指令:使CPU产生动作,并在程序执行时才处理的语句
  • s伪指令:存储模型、主存变量、子程序、宏、段定义等不产生CPU动作的说明性工作,并在程序执行前由汇编程序完成处理,这些工作由说明性语句完成。

(2)标号、名字和标识符

  • 标号表示处理器指令在主存地址中的逻辑地址,一般出现形式为“标号:处理器指令助记符”,标号主要用于指示分支、循环等程序的目的地址,可有可无。
  • 名字可以是变量名、段名、子程序名等,一般出现形式为“名字 伪指令助记符 参数,参数…”
  • 标识符与高级语言里一样

(3)简化段定义格式

.model small
.stack
.data
...
.code		
.startup	;程序起始点,并设置DS和SS内容
...			;主程序代码
.exit 0		;程序终止点,返回dos
...			;子程序代码
end			;汇编结束
.model small
.stack
.data
...
.code		
START:mov ax,@data	;程序起始点,并设置DS和SS内容
mov ds,ax
...			;主程序代码
mov ax,4c00h		;程序终止点,返回dos
int 21h
...			;子程序代码
end	start		;汇编结束

(4)汇编语言程序的开发过程

编辑、编译、连接
其他细节的好像没必要知道

(5)常数的表达

  • 数值型参数
    • equ 数值表达式或者<字符串>
    • = 和equ相同,但允许重复定义符号名
  • 字符型常数的数值是每个字符对应的ASCII码值

(6)变量定义伪指令DB/DW/DD

  • 为变量申请固定长度的存储空间,设置变量名是为了方便存取所指示的存储单元
  • db、dw、dd没什么好说的,注意高对高低对低,'AB’是4142h
  • 变量实际表达的是mem

(7)地址操作符和类型操作符(EQU、ORG、$、OFFSET、SEG、PTR、THIS、SHORT、TYPE、SIZEOF、LENGTHOF)

  • equ:等价机制 符号名 equ 数值表达式/<字符串>
  • org:将当前偏移地址指针指向参数表达的偏移地址
org 100h ;从100h开始安排数据或程序
org $+10 ;使偏移地址加10,即跳过10字节空间
  • $:表示当前偏移地址值,可以用来看上一个变量所占的字节数
  • offset/seg 名字/标号:在汇编过程中计算偏移地址,因此不能offset myword[si]这种
  • 数值表达式计算结果是在程序运行之前,因此不能算出变量的加减乘除之类
  • ptr:类型名 ptr 名字/标号(使名字/标号具有指定的类型)其中类型名可以是BYTE,WORD…也可以是NEAR,FAR
  • this:this 类型名(创建采用当前地址,但为指定类型的操作数)类型名同ptr
  • type:type 名字/标号 对于字节、字和双字变量依次返回1,2,4,对短,近,远转移依次返回FF01H,FF02H,FF05H
  • sizeof=lengthof x type

(8)了解几种程序段的属性

第四章

(1)分支结构程序设计

判断的条件是各种指令,如CMP、TEST等执行后形成的状态标志;双分支体中第1个分支体后一定要有一个JMP指令跳到第2个分支体后;如何实现多分支体

(2)循环结构程序设计

循环指令LOOP;串操作指令中的串寻址方式

串操作类指令

  • 源操作数用寄存器SI间接寻址,默认在数据段DS中,即DS:[SI],允许段超越
  • 目的操作数,ES:[DI],不允许段超越
  • 每执行一次串操作,SI和DI将自动修改,DF为0时,地址+,DF为1时,地址-
  • STD指令将DF置为1,CLD指令将DF清零
串传送指令
movsb  ;字节传送  es:[di]<-ds:[si] di++
movsw  ;字传送     di+=2

stosb  ;字节 存储 es:[di]<-al di++
stosw 

lodsb  ;字节 读取 al<-ds:[si] di++
lodsw
8
rep ;每执行一次串指令,cs--,直到cx=0,重复执行结束
  • 需要事前设置ds es si di和方向标志df,df=0时di++,df=1时di–
串检测指令
cmpsb ;字节串比较 ds:[si]-es:[di] 
cmpsw ;同
;源操作数减去目的操作数 
串扫描指令
scasb ;al-es:[di]
scasw ;ax-es:[di]
  • 重复前缀指令REPE/REPZ,CX!=0且ZF=1(串相等)则继续比较
  • 重复前缀指令REPNE/REPNZ,CX!=0且ZF=0
  • ❗**注意 **操作顺序,先判断cx是否为0,再进行减一操作,执行串操作指令,最后判断zf标志

(3)子程序结构程序设计

子程序的常见格式;子程序调用的三种参数传递方式;子程序如何保护寄存器的值;栈平衡的含义

第六章

(1)实地址工作方式

实方式下,32位80x86cpu只能寻址1MB物理存储器空间,分段最大是64KB,32位80x86CPU可以使用32位寄存器和32位操作数,也可以采用32位的寻址方式。

(2)32位保护方式

不但具有段式存储管理功能,还提供页式存储管理功能,可以更好的支持虚拟存储器,在保护方式下,32位CPU才能发挥其全部功能,可以使用全部32条地址,使微处理器可寻址的物理存储器达到4GB。

(3)虚拟8086方式

在虚拟8086方式下,段寄存器的使用与实方式一样,左移4位加16位偏移量得到20位地址。如果采用分页存储管理,则在8086方式下,任务的1MB地址空间可以转移到4GB物理地址的任何位置。

(4)32位寄存器组合寻址方式

  • 立即数寻址
mov eax,44332211h
  • 寄存器寻址
mov eax,ebx
  • 直接寻址
mov eax,[1234h]
  • 寄存器间接寻址
mov eax,[ebx]
  • 寄存器相对寻址
mov eax,[ebx+80h]
  • 基址变址寻址
mov eax,[ebx+esi]
  • 相对基址变址寻址
mov eax,[ebx+esi+80h]
  • 带比例的变址寻址
mov eax,[esi*2]
  • 基址的带比例的变址寻址
mov eax,[ebx+esi*4]
  • 基址的带位移量的带比例的变址寻址
mov eax,[ebx+esi*8+80h]

第七章

(1)嵌入式汇编

在C/C++语言中直接使用汇编语言语句

asm 操作码 操作数;

(2)模块连接

①两种语言分别编写独立的程序模块,分别产生目标代码OBJ文件,然后进行连接,形成一个完整的程序;
②模块连接的约定规则
③参数传递是关键

你可能感兴趣的:(学习笔记,asm)