编程语言
首页 > 编程语言> > 汇编基础知识总结|基础知识|8086计算机组织|指令系统与寻址|汇编语言程序格式|循环与分支|子程序结构|输入输出程序|文件

汇编基础知识总结|基础知识|8086计算机组织|指令系统与寻址|汇编语言程序格式|循环与分支|子程序结构|输入输出程序|文件

作者:互联网

汇编基础知识总结

文章目录



前记:


一、基础知识

  1. 不同进制间的转换

    整数:除法或凑数法.小数:乘法 按权展开 每4位一组 一位变成4位二进制 十进制与十六进制之间的互转可以通过二进制作为媒介 十进制 二进制 十六进制
  2. 补码与原码转换

    • 方法一:原码 = 反码 + 1
    • 方法二:原码和反码快速转换。从尾数起不变,直到遇到第一个1(第一个1也不变)。然后其它全部相反。
  3. 溢出与进位

    • 进位不一定出错
    • 溢出一定是出错:溢出判断- -> 正 + 正 符号位变为1。负 + 负 符号位变为0。正 + 负 一定不会溢出。
  4. 补码符号位扩展

    • 正数前面添0
    • 负数前面添1
  5. N位比特位表示数的范围

    • 无符号数:0 ~ 2^(N) - 1
    • 有符号数:-2^(N - 1) ~ 2^(N - 1) - 1 (之所以负数的绝对值比正数大1,是因为-0代表最小负数-2^(N - 1) )
  6. ASCII码必记

    名字十进制十六进制
    数字04830
    大写字母A6541
    小写字母a9761
    LF(line feed换行)100A
    CR(carriage return回车)130D

二、80x86计算机组织

1、存器组
概述

在这里插入图片描述

通用寄存器

**注意:**所有都是针对80x86而言!

AX BX CX DX

  1. 可称为***数据寄存器***,它们全部都是通用寄存器,功能具有专用性。
  2. 主要功能是数据方面,又具有地址方面的功能。
  3. 可以以高低位的方式使用
  4. AX(accumulator)
    • 作为累加器,存放操作数,
    • 所有的IO指令都使用这一寄存器与外部设备传送信息
  5. BX(base)
    • 可作为通用寄存器
    • 在计算地址 时,作为基地址寄存器
  6. CX(count)
    • 可作为通用寄存器
    • 保存计数值
  7. DX(data)
    • 可作为通用寄存器
    • 双字长计算中,DX与AX表示一个双字长数,DX为高位
    • 某些IO操作,DX可存放IO端口地址

SP BP SI DI

  1. 称为指针寄存器,主要功能是寻址
  2. 也可以存放操作数,只能以16位为单位使用
  3. SP(stack pointer) 堆栈指针寄存器
    • 指示段顶的偏移地址
  4. BP(base pointer) 基址指针寄存器
    • 与堆栈段寄存器SS确定堆栈段中的某一存储单元的地址
专用寄存器

IP

FLAGS

段寄存器

段:segment(记英文单词是一个学计算机很好的习惯)

在这里插入图片描述

2、存储器
3、寻址

实模式:

保护模式:


三、指令系统与寻址

1、指令
2、寻址方式

基本概念

具体寻址

其中,34567称为存储器寻址。

  1. 立即寻址:数字本身就是操作数!且数据位于代码段中!!!(很特殊)

  2. 寄存器(直接)寻址:寄存器中的内容就是操作数本身

  3. 直接寻址:位移量

    • MOV AX , [2000H]
  4. 寄存器间接寻址:基址 / 变址

    • 如:MOV AX , [BX] MOV AX , [DI]
    • 使用BX,SI,DI,段寄存器默认为DS(包括直接寻址),BP默认为SS
    • 基址只能用BX和BP(只能是与SS搭配使用) , 变址只能用SI和DI
  5. 寄存器相对寻址:基址 / 变址 + 位移量 (相对的意思是,相对于位移量)

    • 表格。表头:位移量。基址或变址:表行。
  6. 基址变址寻址:基址 + 变址

  7. 相对基址变址寻址:基址 + 变址 + 位移量

    • 二维数组。位移量指a[ 0] [ 0 ], 而基址指 a[ n ] [0] , 变址再确定 a[ n ] [ m]。
  8. 比例变址寻址(对应5): 变址 * 因子 + 位移量

  9. 基址比例变址寻址(对应6): 基址 + 变址 * 因子

  10. 相对基址比例变址寻址(对应7):基址 + 变址 * 因子 + 位移量

3、指令系统

指令系统可分为6类:(每大类之中又有小类)

  1. 数据传送指令
  2. 算术指令
  3. 逻辑指令
  4. 串处理指令
  5. 控制转移指令
  6. 处理机控制指令

了解一个指令有如下几点

  1. 功能
  2. 格式
  3. 寻址方式(每个操作数的寻址方式都要说明)
  4. 对PSW的影响
  5. Byte / Word 操作要指明。(如两个操作数不能同时为存储器寻址)
4、数据传送指令
1通用数据传送指令
名称功能格式注意点
MOV:move传送MOV DST,SRC1.不能同时为段寄存器 2.立即数不能直接送段寄存器 3.不能同时为存储器寻址
PUSH进栈PUSH SRC1.必须是字或双字操作 2.进栈四个步骤:高位入栈–>SP减1–>低位入栈–>SP减1 3.每进一个数,SP减2
POP出栈POP DST和PUSH相反
XCHG:exchange交换XCHG OPR1 OPR21.在寄存器和存储器之间交换(也可以是两个寄存器操作数的交换) 2.起码有一个操作数是寄存器操作数 3.不能用段寄存器
2累加器专用传送指令
  1. IN:input 输入

    • 格式: IN 寄存器 端口号
    • 长格式:直接写端口号,端口号在指令中
    • 短格式:把端口放在DX中
    • 长和短是相对于指令来说的
    IN AL 80H     #这两组说明加不加[] 都代表80H是取端口中的内容
    IN AX [80H]
    -----------------------
    IN DX 1234H    #如果端口是16位的,不能直接送到AX,要借助DX来传送
    #传送的是字还是字节,取决于目的操作数。
    IN AX DX        #从端口中输入16位
    IN AL DX		#从端口中输入8位
    
  2. OUT:output 输出

    • 格式:OUT 端口号 寄存器
    • 注意点和IN一样
  3. XLAT:translate 换码

    • 格式:

      MOV  BX, OFFSET TABLE   ; (BX)=0040H
      MOV  AL, 3
      XLAT  TABLE  (或XLAT )
      首地址:BX
      需要转换的代码位移量:AL
      最后AL的结果:AL = BX + AL
      
3地址传送指令
  1. LEA:load effective address 有效地址送寄存器
    • 格式:LEA BX, BUF
    • 等价于:MOV BX, OFFSET BUF (回送有效地址)
4类型转换指令
  1. CBW: convert byte to wrod字节转换为字
    • 格式:CBW(即直接写就可以,后面不用跟任何东西)
    • 默认会把AL扩展成AX
  2. CWD: convert word to double word字转换为双字
    • 格式:CWD
    • 默认会把AX扩展成DX,AX
5、算术指令
1加法指令
  1. ADD:add 加法
    • 格式: ADD DST,SRC
    • 影响CF标志
  2. ADC:add with carry 带进位加法
    • 格式:ADC DST,SRC ( + CF进位)
    • 影响CF标志
  3. INC:increment 加1
    • 格式:INC OPR
    • INC [BX]是错的。不能确定B/W
    • 不影响CF标志
  4. 溢出:
    • CF 位表示 无符号数 相加的溢出
    • OF 位表示 带符号数 相加的溢出
2减法指令
  1. SUB:substract 减法
    • 格式:SUB DST,SRC
    • 影响CF标志
  2. SBB:substract with borrow带借位减法
    • 格式:SBB DST, SRC ( - CF)
    • 影响CF标志
  3. DEC:decrement 减1
    • 格式:DEC OPR
    • 不影响标志位
  4. NEG:negate 求相反数,即求补。(求补 和 求补码 是不一样的,自己搜资料)
    • NEG OPR
    • 对OPR的内容求补
    • 等价于:0FFFFH - (OPR) + 1 (求反加1)
    • 对0求被,CF为0;其它CF都为1
    • 单字节运算对-128 双字节对-32768 对补时,OF为1;其它为0
  5. CMP:compare 比较
    • 格式:CMP OPR1,OPR2
    • 将OPR1和OPR2相减,但不保存结果(对比sub)
    • 会影响CF位(借位)
  6. 溢出:
    • CF 位表示 无符号数 减法的溢出
    • OF 位表示 带符号数 减法的溢出(OF=1,两个操作数符号相反,而结果的符号与减数相同)
3乘法指令
  1. MUL:unsigned multiple无符号数乘法

    • 格式:MUL SRC

    • 目的操作数是默认的,必须是累加器如下:

      • 字节操作数:(AX) ← (AL) * (SRC)
      • 字操作数:(DX,AX) ← (AX) * (SRC)
    • 以下都是错的:
      SRC 1234H   不能是立即数,程序不能确定用al来不是用ax来
      SRC DS      不能是段寄存器
      SRC [BX]	不能确定B/W
      
    • CF=OF=0, 乘积的高一半为零

    • CF=OF=1,否则

  2. IMUL:signed multiple带符号数乘法

    • 与上面上样
    • CF=OF=0,乘积的高一半是低一半的扩展
    • CF=OF=1,否则
4除法指令
  1. DIV: unsigned divide 无符号数除法
    • 格式:DIV SRC
    • 目的操作数是默认的,必须是累加器如下:
      • 16位被除数:(AL) ← (AX) / (SRC),商保存在AL中;余数保存在AH中
      • 32位被除数:(AX) ← (DX,AX) * (SRC),商保存在AX中;余数保存在DX中
    • 溢出:
      • 当字节操作时,被除数的高4位的绝对值大于除数的绝对值,那么会溢出。字操作类似
  2. IDIV:signed divide 带符号数除法
    • 和上面一样
5十进制调整指令

(好像不太重要~~有些内容没看)

  1. DAA: decimal adjust for addition 加法的十进制调整指令
    • 把BCD码+6调整
    • 两种情况要调整:当出现A~F非法时;当有进位时。
6、逻辑指令
1逻辑运算指令

除了NOT指令不影响标志位,其他四个指令都会使CF=OF=0。

SF、ZF、PF根据具体运算结果而设置。

  1. AND:and 逻辑与

    • 格式: AND DST,SRC
    • 执行操作:DST ← DST 与 SRC
    • ZF可以判断结果是否为0
  2. OR: or 逻辑或

    • 格式:OR DST,SRC
    • 执行操作:DST ← DST 或 SRC
  3. NOT:not 逻辑非

    • 格式 :NOT OPR
    • 执行的操作:OPR ← OPR’
    • 不影响标志位
  4. XOR:异或指令

    • 格式:XOR DST,SRC
    • 执行操作:DST ← DST 异或 SRC
  5. TEST:test 测试指令

    • 格式:TEST DST,SRC
    • 操作:DST 与 SRC (即不保存结果)
    • 但会影响标志位,如ZF标志位
2移位指令
  1. SHL: shift logical left 逻辑左移
    • 格式:SHL OPR, CNT
    • CNT表示移位次数。CNT可以直接写数字1 和寄存器 CL
    • 如果移位次数大于1,必须使用CL寄存器来指定移位的位数
    • OPR除了用立即数,其它所有的寻址方式都可以用。
    • 对CNT和OPR的规定,下面的移位指令也适用。
  2. SHR: shift logical right 逻辑右移
    • 直接看图,不解释
  3. SAL:shift arithmetic left 算术左移
  4. SAR: shift arithmetic right 算术右移
  5. ROL:rotate left 循环左移
  6. ROR:rotate right 循环右移

移位图如下(很重要很形象):

在这里插入图片描述

7、串处理指令

5步走:

  1. SI ← 原串地址(DS)
  2. DI ← 目的串地址(ES)
  3. CX ← 长度
  4. 设置方向DF。CLD:DF=0,正向;STD:DF=1,反向
  5. 执行串指令(REP、REPZ)
1串传送
  1. MOVS(move string):串传送

  2. 四种格式:

    • MOVS DST,SRC (实际上不用指定)
    • MOVSB(字节)
    • MOVSW(字)
    • MOVSD(双字)
  3. REP(repeat):重复

    • 重复串操作,直到计数寄存器为0为止
  4. 例子

    把mess1内容复制到mess2中

    ;数据段中有:
    ; mess1 db 'personal computer$'
    ; 附加段中有:
    ; mess2 db 17 db(?)
    
    ;主程序
    lea si,mess1;源
    lea di,mess2;目的
    mov cx,17
    cld   ;正向
    rep movsb ;字节重复传送
    
2串比较
  1. REPE/REPZ(完全相同):repeat while equal 当相等/为零时重复串操作

    • 当计数器为0或者ZF=0(不相等)时退出
    • REPNE/REPNZ 当 相等/为零时重复串操作
  2. CMPS(compare string):串比较

    • 格式和MOVS一样,有CMPSB,CMPSW,CMPSD
    • 操作:((Source - index)) - ((Destination - index))
  3. SCAS(scan string):串扫描

    • 格式:SCASB(AL) 、SCASW(AX)
    • 操作 : (AL) - (Destination - index)
    • 指令把AL或AX的内容与由目的寄存器指向的在附加段中的一个字节或字进行比较,并不保存结果,会设置条件码
  4. 例子1:

    比较两个字符串,找出不相匹配的位置

    ;数据段中有:
    ; mess1 db 'personal computer$'
    ; 附加段中有:
    ; mess2 db 'personal computer2$'
    
    ;主程序
    lea si,mess1;源
    lea di,mess2;目的
    mov cx,17
    cld   ;正向
    repe cmpsb ;当相等时重复
    
    ;当结束时,CX是还剩下未比较的字符个数
    ;         DI是相匹配字符的下一个地址
    
  5. 例子2:

    从一个字符串的查找一个指定的字符

    ;数据段中有:
    ; mess1 db 'personal computer$'
    ; 附加段中有:
    ; mess2 db 'personal computer2$'
    
    ;主程序
    ;lea si,mess1;源
    mov al, 'a'; 查找’a‘这个字符
    lea di,mess2;目的
    mov cx,17
    cld   ;正向
    repne scasb ;当 不 相等时重复扫描
    
    ;当结束时,CX是还剩下未比较的字符个数
    ;         DI是相匹配字符的下一个地址
    
8、控制转移指令
1无条件转移指令

四种分类:

  1. 段内直接转(cs不变,ip变)
    • JMP short 标号 (-128~127) ,ip = 现行 + 8位偏移量(2B机器码的操作数)
    • JMP NEAR PRT 标号 (-32768~32767), ip = 现行 + 16位偏移量(3B机器码的操作数)
    • 指令格式:机器码(2B或3B) = 操作码(1B) + 操作数(1B或2B)
  2. 段内间接转(cs不变,ip变)
    • JMP WORD PTR可省略) BX(寄存器),IP = 操作数
  3. 段间直接转(cs和ip都变)
    • JMP FAR PTR 标号
    • 5B机器码:1B操作码 + 2B ip地址 + 2B cs地址
  4. 段间间接转(cs和ip都变)
    • JMP DWROD PTR [bx] (只能是存储器操作数)
    • 从存储器中取连续四个字节送入到ip,cs中
2条件转移指令

具体使用时,可以不用太在意标志位的情况,根据中文含义也是可以的。

字母缩写含义:

无符号数:

Above 大于

Below 小于

Equal 等于

有符号数:

Great 大于

Less 小于

Equal 等于

三个分类:

根据单个条件标志的设置情况转移

  1. JZ(JE) : jump if zero,or equal
  2. JNZ
  3. JS : jump if sign 负就转移
  4. JNS
  5. JO: jump if overflow
  6. JNO
  7. JP(JPE) : jump if parity,or paryty even 奇偶位为1,则转移
  8. JNP(JPO: jump if not parity,or parity odd
  9. JB(JNAE, JC): jump if below ,or not above or equal, or carry 低于,或者不高于或等于,或进位为1则转移
  10. JNB(JAE, JNC)
  11. jcxz : jump if cx is zero

比较两个无符号数

  1. JB(JNAE, JC) :低于,或者不高于或等于,或进位为1则转移
  2. JNB(JAE, JNC):
  3. JBE(JNA): jump if below or equal, or not above 低于或等于,或不高于则转移
  4. JNBE(JA)

比较两个带符号数

  1. JL(JNGE) : jump if less, or not greater or equal 小于,或者不大于或等于
  2. JNL(JGE)
  3. JLE(JNG):jump if less or equal, or not greater 小于或等于,或者不大于
  4. JNLE(JG)

循环

杂项控制

指令 全称 功能
CLC clear carry flag CF清零
STC set carry flag CF置位1
CMC complement carry flag CF取反
CLD clear direction flag DF清零
STD set direction flag DF置位1
CLI clear interrupt endable flag IF清零,关闭中断
STI set interrupt endable flag IF置位1,打开中断


四、汇编语言程序格式

1、常见dos调用

doc调用(功能号送入ah中):

  1. 输入单个字符:1#,AL=输入的字符
  2. 显示单个字符:2#,DL=输出的字符
  3. 显示字符串:9#,DX=字符串首
  4. 输入字符串:0A#,DX=字符串首
  5. 返回doc系统:4ch

10号调用实例

;数据段中:
;string db 10,?,10 dup('$')
;10代表最大长度为10
;?为实际输入的长度
;10 dup('$')占10个位

mov ah,10
lea dx,string
int 4ch
2、汇编过程
  1. 编辑程序:生成 .ASM文件
  2. 汇编程序(MASM):生成 .OBJ 文件
    • 检查语法
    • 宏展开
    • 生成.obj
  3. 连接程序(LINK):生成exe
  4. debug
3、常见伪操作
  1. 分段伪指令: segment 和 ends配合

    DATAS SEGMENT
        ;此处输入数据段代码  
    DATAS ENDS
    
  2. 起别名:ASSUME CS: 名字

    • 如:ASSUME CS:CODES,DS:DATAS,SS:STACKS

    • 人为赋值:mov AX,DATA

      ​ mov DS, AX

    • DS和ES要人为赋值,CS只能由系统赋值,SS可以人为也可以系统

    • 取消: ASSUME DS:NOTHING , 然后再重新定义

  3. 开始结束

    • END:程序最后一条指令
    • START:标号,mov之前(即段地址赋值前),即第一条指令之前
  4. 变量定义:DB,DW,DD (第一个D:define定义的意思)

    变量复制:dup: var db 100 dup(?)

    • B,W,D分别定义字节,字,和双字
    • 在定义字符串时,DB和DW在内存中有区别:
      • string1 db ‘ab’, 在内存中,存放的时候按顺序存,即a在低地址,b在高地址
      • string2 dw ‘ab’,在内存中,ab看成一个整体,遵守小端模式,即a在高地址,b在低地址
      • 字符串的大小大于两个时,只能用db来定义
  5. 表达式赋值(不分配内存单元):

    • A EQU 9 (不可重复定义)
    • A = 9 (可重复定义)
  6. 地址跟踪计数器

    string db ‘abcdefg’

    count db $ - string

  7. ORG:起始偏移地址设定

  8. EVEN:从偶地址开始

4、运算符
  1. +, - , * , / , mod
  2. 地址表达式:
  1. 逻辑表达式(注意和指令的区别)
    • 如 AND AX,A AND B
  2. 移位表达式
  3. 关系:
    • EQ(=)
    • NE(不等于)
    • LT(<)
    • LE(<=)
    • GT(>)
    • GE(>=)
    • 真:全1 FFFF,假 0
  4. 数值回头符
    • OFFSET:回送偏移地址
    • SEG:回送段地址
    • TYPE:回送类型大小,db为1,dw为2,dd为4
    • LENGTH:回送dup指定的数大小(如果不是dup定义的,那么默认为1)
    • SIZE:回送 TYPE * LENGTH(注意不是dup定义的情况)
  5. 属性操作
    • PTR:BYTE/WORD PTR,NEAR/FAR PTR
    • 段超越:ES:SP
    • SHORT
5、程序框架

在这里插入图片描述


五、循环与分支

这章节主要是实践章节,没什么重要知识点,靠的是自己的训练。

经典题型:

  1. 二、十、十六进制的转化与输入输出
    • 总结博客地址:https://blog.csdn.net/qq_47234534/article/details/117569401
  2. 数组中查找数,找到删除
  3. 数组中插入数
  4. 逻辑尺
  5. 2种起泡排序
  6. 折半查找

实现嵌套循环三种方法:

;---------------------------------------------
外层loop
mov di,cx    ;保护
.....内层代码
mov cx,di    ;还回来
外层loop

;---------------------------------------------
push cx    ;保护
.....内层代码
pop cx    ;还回来

;---------------------------------------------
;利用跳转命令
mov si, 次数
.....循环代码
dec si
jne 标号

清零四种方法:

1. XOR BX , BX ; 重点
2. MOV BX , 0
3. SUB BX , BX
4. AND BX , 0

六、子程序结构

基本结构

main PROC FAR/NEAR (段间与段内)

   call 程序名  ;调用
   
   ret  返回
main endp

参数传送方法

  1. 寄存器传送

  2. 变量传送

  3. 地址表传送参数地址

    mov table, offset num ;送数组首地址
    mov table + 2, offset count ; 送数组大小
    mov table + 4, offset sum    ;数组和
    mov bx, offset table     ;送入首地址
    然后子程序用[bx],[bx + 2],[bx +4] 来操作首地址,数组大小及 sum和地址
    
  4. 堆栈传送参数地址(注意堆栈画图,以2个字节为一个格子)

    • 在主程序中,把需要用到的变量入栈。注意,call的时候,cs和ip也自动会入栈
    • 在子程序中,先BP入栈,再用BP保存SP
    • 保存所有需要保存的值
    • 用BP操作自己需要的值 (注意,每次入栈都是占两个字节的,注意BP + 2的整数倍)
    • 还原现场
    • ret (主程序中,入栈的变量数 * 2)。清空主程序中无用变量入栈对原程序产生的影响

八、输入输出程序

1、基本知识

传送方式

  1. 无条件传送(程序控制):送取无条件,用定时方法,数据易丢失
  2. 查询方式(程序控制):cpu反复询问外设工作状态,直到可以进行数据的传送
  3. 中断方式(硬件)
  4. DMA(硬件)

IO指令

所有外设的IO数据都要通过al或者ax。

  1. IN:input 输入

    • 格式: IN 寄存器 端口号
    • 长格式:直接写端口号,端口号在指令中
    • 短格式:把端口放在DX中
    • 长和短是相对于指令来说的
    IN AL 80H     #这两组说明加不加[] 都代表80H是取端口中的内容
    IN AX [80H]
    -----------------------
    IN DX 1234H    #如果端口是16位的,不能直接送到AX,要借助DX来传送
    #传送的是字还是字节,取决于目的操作数。
    IN AX DX    #从端口中输入16位
    IN AL DX		#从端口中输入8位
    
  2. OUT:output 输出

    • 格式:OUT 端口号 寄存器
    • 注意点和IN一样
2、中断传送

中断的分类

中断 软件/内部 中断 int指令中断 cpu错误中断,如除法错误INTO debug中断,如单步中断 硬件/外部 中断 非屏蔽中断NMI 可屏蔽中断INTR

8259中断源

  1. 中断源图如下:

在这里插入图片描述

  1. 每一个8259有如下寄存器:

    8259可编程中断控制器PIC 中断请求寄存器 中断屏蔽寄存器 优先级比较寄存器 中断服务寄存器 IRR 有8个, 下面同理 IMR PR ISR
  2. 8259的级联:

    • 每一个8259有IR0~IR7 8个接口,优先级IR0 > IR7
    • 第一个IR接口,可外接另一片8259
    • 最多可级联两级,形成主从关系
  3. 在8259发送中断源后,会有两个负脉冲传送中断相关信息:

    • 第一个负脉冲:CPU通过 (INTA)’ 引脚,使8259 IRR = 0, ISR = 1 (注意,要对应着IR中的中断源)
    • 第二个负脉冲:8259给cpu送中断类型号

标志位/缩写总结

英文缩写含义
NMI非屏蔽中断请求
INTR可屏蔽中断请求
(INTA)’CPU响应外部的引脚位
IFIF=1,代表CPU响应外设中断请求
TFTF=1,代表CPU开启单步中断模式
INT n中断n指令,如 INT 21H
INTOCPU处理错误中断中的溢出处理中断指令
EOIend of interrupt, 中断结束命令
STI设置中断允许位,IF=1
CLI清除中断允许位,IF=0

中断优先级

优先级从高到低为 软件中断 非屏蔽中断 可屏蔽中断,从R0到R7又分为8级 单步中断

中断向量表的建立**(超级重点)**

一是绝对地址方法

push ds

mov ax,0
mov ds,ax     ;将ax和dx清零
mov bx, N * 4 ;中断类型号为N,计算初始向量地址
mov ax, offset subp   ;得ip
mov [bx], ax  ;先存ip
mov ax, seg subp    ;得cs
mov [bx + 2], ax  ;再存cs

pop ds
STI

二是dos调用方法

两种中断中常用的dos调用:

AH功能调用参数返回参数
25设置中断向量DS:DX = 中断向量,AL = 中断号
35取中断向量AL = 中断号ES:BX = 中断向量
;利用dos调用建立中断向量表,功能号25H
; DS = 中断服务子程序入口段地址
; DX = 中断服务子程序入口偏移地址
; AL = 中断类型号

push ds

mov ax, seg subp
mov ds,ax    ;放置cs
mov dx, offset subp  ;放置ip
mov ah,25h
mov al,08h    ;中断号为08H
int 21h

pop ds
STI

dos调用完整程序示例

AH功能调用参数返回参数
25设置中断向量DS:DX = 中断向量,AL = 中断号
35取中断向量AL = 中断号ES:BX = 中断向量

三步走:

MOV   AL, N
MOV   AH, 35H        ;35调用,取原N号中断向量
INT   21H            
PUSH  ES
PUSH  BX             ; 保存原中断向量

PUSH  DS
MOV   AX, SEG subp
MOV   DS, AX        
MOV   DX, OFFSET subp
MOV   AL, N
MOV   AH, 25H
INT   21H            ; 设置新的中断向量 
POP   DS
……
POP   DX     ;原来的BX
POP   DS     ;原来的ES
MOV   AL, N
MOV   AH, 25H      
INT   21H            ; 恢复原中断向量
……
subp:                    ; 中断处理程序
……
IRET


十一、文件

实现一个程序,把根目录下的test文件中的小写字母变成大写字母,并写写回原文件中。

;默认采用ML6.11汇编程序
DATAS SEGMENT
    ;此处输入数据段代码  
    file db 'test.txt',0  ;asciz 串,注意后面要加0
    charBuff db ?  ;放读出来的字符
    errorMsg db 'file error!!$'  ;提示信息
DATAS ENDS

STACKS SEGMENT
    ;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    ;此处输入代码段代码
	
	mov dx, offset file   ;要打开的文件asciz串
	mov al,2 ;。0读,1写,2读写
	mov ah,3DH  ;打开文件
	int 21h
	jc error
	mov bx,ax  ;打开文件的文件代号存放。
	          ;全局都使用BX文件代号。有多个可以设置变量handle1,hadndle2来存放
	readFile:
	lea dx,charBuff  ;存放的地址
	mov cx,1     ;每次读一个字符
	mov ah,3FH  ;读取文件
	int 21h
	jc error
	
	cmp ax,0    ;实际读取的字符数,如果为0,说明文件结束
	jz exit
	
	mov al,charBuff ;把读出来的字符拿出来比较
	cmp al,'a'
	jb writeFile
	cmp al,'z'
	ja writeFile
	sub al,20H
	mov charBuff,al   ;放回去,方便把charBuff写回文件中
	
	writeFile:
	mov ax,-1   ;把指针向上移动一个
	cwd         ;符号扩展
	mov cx,dx   ;CX是高位
	mov dx,ax   ;DX是低位
	mov al,01   ;移动指针方式。相对移动指针
	mov ah,42H  ;移动指针
	int 21h     
	jc error
	
	mov cx,1        ;写入一个
	lea dx,charBuff  ;从哪里写
	mov ah,40h       ;写文件
	int 21h
	jc error
	
	jmp readFile

error:
	lea dx, errorMsg
	mov ah,9
	int 21h

exit:
	mov ah,3EH  ;关闭文件。文件代号在BX中
	int 21h

    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

标签:指令系统,中断,程序,mov,基础知识,地址,指令,寄存器,AX
来源: https://blog.csdn.net/qq_47234534/article/details/118438617