第1章 基础知识·
IBM-PC输入输出时采用ASCII码进行编码
第2章 IBM-PC计算机组织·
2.3 Intel 8086/8088 CPU的寄存器架构·
通用寄存器·
AX BX CX DX 常用于存放数据,称为数据寄存器,这四个寄存器可以拆分为AH,AL,BH,BL,CH,CL,DH,DL 8个8位寄存器,分别是相应寄存器的高8位和低8位
SP BP SI DI 常用于存放指针,称为指针或地址寄存器
数据寄存器·
AX是累加器(accumulator)常用来存放操作数和运算结果,乘除法强制使用 ,输入输出也需要使用
BX一般用来存放基地址(base address)
CX常在循环指令及串循环指令中用作计数器,移位指令则用CL作为计数器
DX用于32位乘除法时AX的扩展,输入输出指令中用来存放I/O端口的地址,实现间接寻址
指针与变址寄存器·
SP 堆栈 寄存器,堆栈的操作(压入,弹出)会自动修改SP值
BP 基址指针,是一种基地址寄存器(类似于BX),不同的是相对于堆栈段而不是数据段
SI 源变址寄存器
DI 目的变址寄存器
段寄存器·
CS:代码段寄存器
DS:数据段寄存器
SS:堆栈段寄存器
ES:附加段寄存器
指令指针·
IP 指令指针寄存器
当前执行的指令在代码段的偏移地址
不能直接改动
标志寄存器·
9个一位的标志寄存器(或标志位)
组合在一起放入一个16位的程序状态字寄存器PSW 中
2.4 PC机内存组织·
20根地址线 总内存大小是 $2^{20}=1MB$
范围表示从 $00000H-FFFFFH$
同时x86是小端存储 即低地址存低位
采用16位寄存器记录分段信息,一共分为64K个段,每个段最多有64KB的段长
用逻辑地址,即段地址:偏移地址 的格式映射某个物理地址
具体映射方式:物理地址=段地址*16D(或10H)+偏移地址
2.5 堆栈·
堆栈位置和大小由SS和SP寄存器确定
栈底由SP初始值确定,栈顶由SP值确定,一直压栈,SP值越来越小,栈顶距离栈底就越来越远
等价于
等价于
第3章 寻址方式与指令系统·
3.1 指令格式·
指令汇编语言格式·
1 2 3 OP DST,SRC ;类似ADD AX,b OP SRC ;类似POP OP ;类似DIV
3.2 寻址方式·
与数据相关的寻址方式·
各个指令所需的操作数来自:
寄存器。包括通用寄存器,段寄存器和标志寄存器(PSW)
指令本身给出的立即数(常量)
内存单元
立即寻址·
只能出现在源操作数 ,不能出现 在目的操作数 位置
目的操作数可以是寄存器或内存操作数
常用来给寄存器赋初值
常数可以直接写到指令,常量则需要线用EQU伪指令定义
1 2 3 MOV AX,512 VALUE EQU 51 MOV AX,VALUE
寄存器寻址·
操作数是CPU的某个寄存器
8位操作数,可以是AH,AL,BH,BL,CH,CL,DH,DL
16位操作数,可以是AX,BX,CX,DX,SP,BP,SI,DI,CS,DS,SS,ES
1 2 3 4 5 MOV AX,BX ADD AX,DX PUSH DS STD ;设置DF=1 PUSHF ;PSW作为源操作数
直接寻址·
操作数的偏移地址直接在指令中指出的寻址方式
默认是相对于DS数据段的偏移量
也可以先定义字/字节变量的方式
1 2 3 4 x DW ? c DB 'A' MOV AX,x MOV AL,c
汇编程序被汇编器汇编后,会计算出x,c的偏移值替换原来的x或c
寄存器间接寻址·
1 2 3 4 5 6 7 8 9 10 11 MOV AX,[BX] MOV BH,[BP] MOV CX,[SI] MOV DL,[DI] #等价于 即缺省时是相应的段 也可以修改 MOV AX,DS:[BX] MOV BH,SS:[BP] MOV CX,DS:[SI] MOV DL,DS:[DI]
注意不能用DX 做间接寻址寄存器
寄存器相对寻址·
操作数有效地址EA是一个基址寄存器或变址寄存器的内容 和指令中指定的8位或16位位移量 之和
EA=间接寄存器的值+8位/16位常量
1 2 3 4 MOV AX,[SI+10H] MOV AX,10H[SI] MOV AX,ARRAY[SI] MOV TABLE[DI+1],AL
基址变址寻址方式·
操作数有效地址EA=基址寄存器+变址寄存器内容
1 2 MOV AX,[BX][SI] MOV AX,[BX+SI]
注意,基址变址寻址方式的基址寄存器 只能是BX或BP ,变址寄存器 只能是SI或DI
与转移地址有关的寻址方式·
主要运用于转移指令(JMP)和过程调用指令(CALL)
通过标号和过程名 来确定同一代码段或另一代码段的偏移地址
段内直接寻址·
转向的指令实际有效地址是当前IP寄存器的内容和指令中指定的8位或16位位移量之和
条件转移指令必须是8位,所以省略了SHORT操作符
可以指定位移量
1 2 JMP SHORT L1 ;8位 短跳转 JMP NEAR PTR L1 ;16位
段内间接寻址·
1 2 3 4 5 6 MOV AX,OFFSET P1 MOV ADD1,AX CALL ADD1 MOV BX,OFFSET ADD1 CALL [BX] JMP BX
段间直接寻址·
要转移的标号或过程名必须具备FAR属性
段间间接寻址·
1 JMP DWORD PTR [BX+INTERS] ;寄存器相对寻址方式
转移地址是一个双字,高位字在后,低位字在前
3.3 指令系统·
数据传送指令·
数据通路与类型匹配·
MOV和XCHG指令·
1 2 MOV DST,SRC XCHG OPR1,OPR2
大部分指令需要遵守的规则:
源和目的必须类型匹配(8位对8位,16位对16位)
目的操作数不能为立即数
源和目的操作数不能同时为内存操作数 (串指令除外)
源和目的操作数不能同时为段寄存器
PUSH,POP,PUSHF,POPF指令·
地址传送指令 LEA,LDS,LES·
将地址送到指定寄存器
1 2 3 LEA REG,SRC ;源操作数src的偏移地址送入reg LDS REG,SRC ;src中的双字内容依次送入reg和DS中 LES REG,SRC ;src中的双字内容依次送入reg和ES中
获得地址也可以使用OFFSET和SEG
比如
1 2 MOV BX,OFFSET X MOV AX,SEG X
算术运算指令·
查看45-49页
加减指令
CMP与NEG
乘法指令MUL IMUL和CBW
除法指令DIV IDIV和CWD
逻辑指令·
查看49-52页
逻辑运算指令
测试指令
移位指令
控制转移指令·
查看52-59页
无条件转移指令
条件转移指令
循环指令
过程调用和返回指令
处理器控制指令
第4章 汇编语言程序格式·
4.1 分段式程序结构·
SEGMENT ENDS DW EQU ASSUME ENDP END都是常见伪指令
标号命名必须以@/-/?
或者字母开头,指令与伪指令的常数以字母开头 A/B/C/D/E/F
开头需要在前面加0,避免混淆,不区分大小写!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 STACK1 SEGMENT PARA STACK ;PARA STACK定义了堆栈 STACK_AREA DW 100H DUP(?) STACK_BTM EQU $-STACK_AREA STACK1 ENDS ;1-4行定义堆栈段 SEGMENTS和ENDS是一对 DATA SEGMENT TABLE_LEN DW 16 TABLE DW 19,06,19,73,11,22,33,44 DW 20,06,20,74,55,66,77,88 DATA ENDS ;5-9行定义数据段 CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK1 ;为了阅读方便和整齐,需要字段对齐 指令语句和伪指令语句不能换行 这里其实没有真正的设置CS DS SS MAIN PROC FAR ;PROC和ENDP是一对 如果只有一个过程则可以直接在代码段写指令 MOV AX,STACK1 MOV SS,AX MOV SP,STACK_BTM ;栈底交给SP MOV AX,DATA MOV DS,AX LP1: MOV BX,1 MOV CX,TABLE_LEN DEC CX MOV SI,OFFSET TABLE ;把TABLE的偏移地址送给SI LP2: MOV AX,[SI] ;利用SI进行间接寻址 CMP AX,[SI+2] ;比较TABLE[i]与TABLE[i+1]的大小 JBE CONTINUE ;小于等于则跳转到CONTINUE 无符号数比较是JB/JA/JE 有符号数是 JG/JL/JE XCHG AX,[SI+2] ;大于则交换,用AX当TEMP MOV [SI],AX MOV BX,0 ;清零标志变量 CONTINUE: ADD SI,2 LOOP LP2 ;<==> 先CX-- CX不为0就跳转到 LP2 CX为0则继续往下执行 CMP BX,1 JZ EXIT ;ZF为0则跳转到EXIT JMP SHORT LP1 ;SHORT是相距较近的代码时用的 EXIT: MOV AX,4C00H ;AH-功能号 AL-返回码 相当于exit(0),返回MS-DOS命令提示符 INT 21H ;调用MS-DOS例程 MAIN ENDP CODE1 ENDS ;10-36行定义代码段 END MAIN ;告诉编译器程序入口在MAIN
4.2 定义程序结构的伪指令·
4.3 数据定义与内存分配·
常数与常量·
二进制数:0-1序列,B结尾,比如:010B
八进制数:0-7组成序列,Q结尾,比如:127Q
十进制数:0-9组成序列,D结尾,D也可以省略。比如:129/129D
十六进制数:0-9,A-F组成序列,H结尾
字符或字符串:单引号或双引号括起来的字符:‘A’,“ABC”
实数:整数,小数,指数三部分,比如1.234E-5
EQU指令指定常量 比如:A EQU 12H
当前位置计数器 $
,常用来计算长度,比如 SRACK_BTM EQU-TABLE
变量与变量定义·
x86中所有的地址+1,都是+1个BYTE对应的地址
String1 DB 'ABCD',0DH,0AH,'$'
这里其实定义了7个字,即A B C D 0DH 0AH $
ARRAY1 DB 10 DUP(?)
ARRAY2D DB 5 DUP(1,2,3,4,?)
二维数组定义
汇编,链接,运行·
1 2 3 masm code.asm link code.asm code.asm
调试与DEBUG·
第5章 分支与循环程序设计·
5.1 顺序程序设计·
例题5.1 将一个25行,80列的数组的第y行,第x列元素的第i位置1·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 STACK1 SEGMENT PARA STACK_AREA DW 100H DUP(?) STACK_BOTTOM EQU $-STACK_AREA STACK1 ENDS DATA SEGMENT PARA ARRAY DB 25*80 DUP(?) X DB ? ;字节变量 Y DB ? I DB ? END SEGMENT CODE SEGMENT PARA ASSUME CS:CODE,SS:STACK1,DS:DATA MAIN PROC FAR MOV AX,STACK1 MOV SS,AX MOV SP,STACK_BOTTOM MOV AX,DATA MOV DS,AX MOV AL,80 MUL Y ;相当于AL*Y 结果送到AX MOV DL,X XOR DH,DH ;将DH清零 从而DX=X ADD AX,DX ;AX=Y*80+X MOV SI,OFFSET ARRAY ;SI=ARRAY首地址 ADD SI,AX;SI=需要的元素地址 MOV AL,80H;AL=10000000B MOV CL,I;CL=I SHR AL,CL ;AL=AL>>I 移位的数字不是1,必须使用CL寄存器!! OR [SI],AL ;第I位置1 SI寄存器间接寻址 EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE END END MAIN
例题5.2 用查表方式将一位十六进制数转换成相应ascii码·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 STACK1 SEGMENT PARA STACK STACK_AREA DB 100H DUP(?) ;定义PARA STACK就会自动初始化SP和SS STACK1 ENDS DATA SEGMENT PARA ASCII_TABLE DB 30H,31H,32H,33H,34H,35H,36H,37H DB 38H,39H,41H,42H,43H,44H,45H,46H HEX DB ? ASC DB ? DATA ENDS CODE SEGMENT PARA ASSUME CS:CODE,SS:STACK,DS:DATA MAIN PROC FAR MOV AX,DATA MOV DS,AX MOV SI,OFFSET ASCII_TABLE MOV AL,HEX XOR AH,AH;AX=HEX ADD SI,AX;SI=HEX对应的ascii码元素的地址 MOV AL,[SI] MOV ASC,AL ;打印ASCII码 MOV AH,2 ;二号中断 MOV DL,AL INT 21H EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN
也可以用以下寄存器相对寻址方式
1 2 3 4 5 XOR AH,AH MOV AL,HEX MOV SI,AX MOV AL,ASCII_TABLE[SI] MOV ASC,AL
也可以用基址加变址方式寻址
1 2 3 4 5 6 MOV BX,OFFSET ASCII_TABLE MOV AL,HEX XOR AH,AH MOV SI,AX MOV AL,[BX+SI] MOV ASC,AL
5.2 分支程序设计·
例5.3 删除数组中目标元素·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 STACK1 SEGMENT PARA STACK STACK_AREA DB 100H DUP(?) STACK1 ENDS DATA SEGMENT TABLE_LEN EQU 20 TABLE DW TABLE_LEN DUP(?) TABLE_END LABEL WORD ;表最后的下一个元素 VALUE DW ?;要查找的目标值 DATA ENDS CODE SEGMENT ASSUME CS:CODE,SS:STACK1,DS:DATA MAIN PROC FAR MOV AX,DATA MOV DS,AX SEARCH: MOV BX,OFFSET TABLE MOV AX,VALUE CMP AX,[BX] JE FOUND INC BX INC BX ;BX+=2 CMP TABLE_END JB SEARCH MOV SI,0FFFFH ;没找到 JMP SHORT EXIT FOUND: MOV SI,BX DELETE: CMP BX,TABLE_END JAE EXIT ;大于等于跳转 MOV AX,[BX+2] MOV [BX],AX ADD BX,2 JMP SHORT DELETE EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN
例5.4:跳转表·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 STACK0 SEGMENT PARA STACK STACK_AREA DW 100H DUP(?) STACK0 ENDS DATA SEGMENT PARA N EQU 5 JMP_TABLE DW ROAD1,ROAD2,ROAD3,ROAD4,ROAD5 I DW 3 DATA ENDS CODE SEGMENT PARA ASSUME CS:CODE,DS:DATA,SS:STACK0 MAIN PROC FAR MOV AX,DATA MOV DS,AX MOV BX,I DEC BX SHL BX,1 JMP JMP_TABLE[BX] ROAD1: MOV AH,2 MOV DL,31H INT 21H JMP EXIT ROAD2: MOV AH,2 MOV DL,32H INT 21H JMP EXIT ROAD3: MOV AH,2 MOV DL,33H INT 21H JMP EXIT ROAD4: MOV AH,2 MOV DL,34H INT 21H JMP EXIT ROAD5: MOV AH,2 MOV DL,35H INT 21H JMP EXIT EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN
5.3 循环程序设计·
与CX搭配使用的循环用法·
LOOP:先将CX设置为需要循环的次数,循环一次后,LOOP指令先将CX减1,并判断是否为0,不为0则继续循环,反之结束循环
LOOPE/LOOPZ:在LOOP基础上增加条件ZF==1 ,只有当ZF==1才继续循环
LOOPNE/LOOPNZ:在LOOP基础上增加条件ZF==0只有当ZF==0才继续循环
JCXZ:只判断,不递减CX。当CX==0时跳转
例5.5:内存中的一个字(二进制数)转换为十六进制数,并在屏幕上显示出来·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 STACK1 SEGMENT PARA STACK STACK_AREA DB 100H DUP(?) STACK1 ENDS DATA SEGMENT PARA VALUE DW 0011101000101111B ;3A2F DATA ENDS CODE SEGMENT PARA ASSUME CS:CODE,SS:STACK1,DS:DATA MAIN PROC FAR MOV AX,DATA MOV DS,AX MOV BX,VALUE MOV CX,4 ;循环次数 SHIFT: PUSH CX MOV CL,4 ROL BX,CL ;BX循环左移4位 MOV AL,BL ;取出低8位 AND AL,0FH;清除高四位,只留最低四位 ADD AL,30H CMP AL,39H JBE PRINT ADD AL,'A'-'9'-1 PRINT: MOV DL,AL MOV AH,2 INT 21H POP CX LOOP SHIFT EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN
将内存中一个字(二进制或十六进制数)转换成十进制数的ASCII码,并显示出来·
方法1 例5.6 依次除以10000,1000,100,10,1 得到商·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 STACK1 SEGMENT PARA STACK STACK_AREA DB 100H DUP(?) STACK1 ENDS DATA SEGMENT VALUE DW 0FFFEH DIVISOR DW 10000,1000,100,10,1 DATA ENDS CODE SEGMENT ASSUME CS:CODE,SS:STACK1,DS:DATA ;description MAIN PROC MOV AX,DATA MOV DS,AX MOV SI,OFFSET DIVISOR MOV AX,VALUE MOV CX,5 LP: XOR DX,DX ;清空被除数高16位 DIV WORD PTR [SI] ;AX=AX/DIVISOR PUSH DX OR AX,30H ;变成ASCII码 PRINT: MOV DL,AL MOV AH,2 INT 21H POP AX ADD SI,2 LOOP LP EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN
方法2 例5.7 不断除以10,按顺序所得的余数倒排即为所求·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 STACK1 SEGMENT PARA STACK STACK_AREA DB 100H DUP(?) STACK1 ENDS DATA SEGMENT VALUE DW 0FFFEH DATA ENDS CODE SEGMENT ASSUME CS:CODE,SS:STACK1,DS:DATA ;description MAIN PROC MOV AX,DATA MOV DS,AX MOV CX,5 MOV AX,VALUE MOV BX,10 LOOP1: XOR DX,DX DIV BX PUSH DX LOOP LOOP1 MOV CX,5 LOOP2: POP AX OR AX,30H MOV DL,AL MOV AH,2 INT 21H LOOP LOOP2 EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN
堆栈的出入栈都必须以字为单位!
内存中组织好一个ASCII字符串,串的有效内容后加一个’$'结束字符,就可以利用DOS的9号功能打印字符串。
使用如下方式:
1 2 3 MOV DX,串的首地址 MOV AH,9 INT 21H
方法3 例5.8 不断除以10得到商和余数,利用字符串进行输出·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 STACK1 SEGMENT PARA STACK STACK_AREA DB 100H DUP(?) STACK1 ENDS DATA SEGMENT VALUE DW 0FFFEH RES DB 5 DUP(?),'$' DATA ENDS CODE SEGMENT ASSUME CS:CODE,SS:STACK1,DS:DATA ;description MAIN PROC MOV AX,DATA MOV DS,AX MOV CX,5 MOV AX,VALUE MOV BX,10 MOV DI,OFFSET RES + 4 LOOP1: XOR DX,DX DIV BX OR DX,30H MOV [DI],DL DEC DI LOOP LOOP1 LOOP2: MOV DX,OFFSET RES MOV AH,9 INT 21H EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN
多重循环设计 冒泡排序为例·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 STACK1 SEGMENT PARA STACK STACK_AREA DW 100H DUP(?) STACK1 ENDS DATA SEGMENT PARA TABLEDATA_LEN DW 16 TABLEDATA DW 19,37,35,73,20,06,30,07 DW 20H,17H,0FFFFH,2001,2022,4,29,56 RES DB 5 DUP(?),20H,'$' ;十进制最多5位,20H表示空格 STR1 DB 'INIT_ARRAY:','$' STR2 DB 'SORTED_ARRAY:','$' NEWLINE DB 0DH,0AH,'$' ;回车换行 DATA ENDS CODE SEGMENT PARA ASSUME CS:CODE,SS:STACK1,DS:DATA MAIN PROC FAR MOV AX,DATA MOV DS,AX PRINT_INIT_ARRAY: ;先打印初始的数组 MOV DX,OFFSET STR1 MOV AH,9 INT 21H MOV DX,OFFSET NEWLINE MOV AH,9 INT 21H MOV CX,TABLEDATA_LEN MOV SI,OFFSET TABLEDATA WHILE1: PUSH CX MOV CX,5 MOV DI,OFFSET RES+4 MOV BX,10 MOV AX,[SI] WHILE2: XOR DX,DX DIV BX OR DL,30H MOV [DI],DL DEC DI LOOP WHILE2 ;打印字符串 MOV AH,9 MOV DX,OFFSET RES INT 21H INC SI INC SI POP CX LOOP WHILE1 MOV AH,9 MOV DX,OFFSET NEWLINE INT 21H BUBBLE_SORT: ;冒泡排序 MOV CX,TABLEDATA_LEN SORT_LOOP1: ;外层循环 PUSH CX MOV SI,OFFSET TABLEDATA MOV BX,0 ;BX作为一个标志变量,如果一次内层循环后仍然为0,说明已经是按照顺序排列了 SORT_LOOP2: ;内层循环 MOV AX,[SI] CMP AX,[SI+2] JNA CONTINUE SWAP: MOV BX,1 XCHG AX,[SI+2] MOV [SI],AX CONTINUE: ADD SI,2 LOOP SORT_LOOP2 POP CX CMP BX,0 JZ PRINT_SORTED_ARRAY LOOP SORT_LOOP1 PRINT_SORTED_ARRAY: ;打印排序后的数组 MOV DX,OFFSET STR2 MOV AH,9 INT 21H MOV DX,OFFSET NEWLINE MOV AH,9 INT 21H MOV CX,TABLEDATA_LEN MOV SI,OFFSET TABLEDATA WHILE3: PUSH CX MOV CX,5 MOV DI,OFFSET RES+4 MOV BX,10 MOV AX,[SI] WHILE4: XOR DX,DX DIV BX OR DL,30H MOV [DI],DL DEC DI LOOP WHILE4 ;打印字符串 MOV AH,9 MOV DX,OFFSET RES INT 21H INC SI INC SI POP CX LOOP WHILE3 MOV AH,9 MOV DX,OFFSET NEWLINE INT 21H EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN
5.4 串处理·
串处理指令·
典型的寻址过程是:DS:[SI]==>ES:[DI]
目的串——ES[DI] 即从这里取出
源串——DS[SI] 即写入这里
取串指令LODSB/LODSW·
LODSB将源串DS:[SI]的一个字节或一个字取到AL或AX中。
操作完后,按照DF的值自动修改SI的值。
DF=0则对SI+1或+2(根据字节或字)
DF=1则对SI-1或-2(根据字节或字)
存串指令STOSB/STOSW·
将AL或AX中的一个字节或字存入ES:[DI]中
操作完后,根据DF的值修改DI
DF=0则对DI +1或+2(根据字节或字)
DF=1则对DI -1或-2(根据字节或字)
串传送指令MOVSB/MOVSW·
将DS:[SI]中的字节或字传送到ES:[DI]中
操作完后,根据DF的值同时修改SI与DI
DF=0则SI与DI都+1或+2
DF=1则SI与DI都-1或-2
串比较指令CMPSB/CMPSW·
比较源串DS:[SI]与目的串ES:[DI]中的一个字节或一个字,与CMP类似
比较时,用源串中一个字节(字)减去目的串中一个字节(字)
不保留结果但影响标志寄存器,如CF,SF,ZF
执行完后根据DF值修改SI/DI
串扫描指令SCASB/SCASW·
在ES:[DI]中指定的目的串中扫描是否含有AL或AX中指定的字节或字,用AL或AX的内容减去ES:[DI]中的字节或字,比较结果影响标志寄存器。
执行完后根据DF值修改SI/DI
重复前缀指令REP·
格式:REP 串操作指令
比如:REP MOVSB
类似LOOP
每执行一次串操作指令就CX-1,直到CX为0时停止
条件重复前缀指令REPE/REPZ REPNE/REPNZ·
REPE/REPZ·
当CX==0或ZF==0时退出串操作指令,即运算结果不为0时退出
CX-=1
REPNE/REPNZ·
CX==0或ZF==1时退出串操作指令,即运算结果为0时退出
CX-=1
修改DF方向标志命令CLD,STD·
CLD清除DF标志寄存器,使得DF=0
STD设置DF标志寄存器,是的DF=1
串处理指令应用·
使用串处理的步骤
根据需要设置DS,SI,ES,DI
设置DF标志
设置CX值
选用REP,REPZ/REPE、REPNZ/REPNE
例5.10-5.14·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 STACK1 SEGMENT PARA STACK STACK_AREA DW 100H DUP(?) STACK1 ENDS DATA SEGMENT PARA LEN DW 8 BUFF DB '19373573','$' BUFF1 DB '20131839','$' BUFF2 DB '33839230','$' BUFF3 DB 'abcdEFZc','$' BUFF4 DB 'AKSHBASB','$' BUFF5 DB 'ASNSODOJ','$' STR1 DB 'P_5_10:','$' STR2 DB 'P_5_11:','$' STR3 DB 'P_5_12:','$' STR4 DB 'P_5_13:','$' STR5 DB 'P_5_14:','$' BIG_STR DB 'BUFF4>BUFF5','$' SMALL_STR DB 'BUFF4<BUFF5','$' NEW_LINE DB 0DH,0AH,'$' FIND_STR DB 'BUFF5 CONTAINS A','$' DATA ENDS CODE SEGMENT PARA ASSUME CS:CODE,DS:DATA,SS:STACK1 MAIN PROC FAR ;INIT MOV AX,DATA MOV DS,AX P_5_10: ;PRINT MOV AH,9 MOV DX,OFFSET STR1 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H MOV AH,9 MOV DX,OFFSET BUFF INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H ;SAVE ES AND SET ES TO DS PUSH ES PUSH DS POP ES ;STOSB CLD MOV CX,LEN MOV DI,OFFSET BUFF MOV AL,0 REP STOSB POP ES ;PRINT MOV AH,9 MOV DX,OFFSET BUFF INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H P_5_11: ;PRINT MOV AH,9 MOV DX,OFFSET STR2 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H MOV AH,9 MOV DX,OFFSET BUFF1 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H MOV AH,9 MOV DX,OFFSET BUFF2 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H ;SAVE ES AND SET ES TO DS PUSH ES PUSH DS POP ES ;MOVSB CLD MOV CX,LEN MOV DI,OFFSET BUFF2 MOV SI,OFFSET BUFF1 REP MOVSB POP ES ;PRINT MOV AH,9 MOV DX,OFFSET BUFF1 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H MOV AH,9 MOV DX,OFFSET BUFF2 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H P_5_12: ;PRINT MOV AH,9 MOV DX,OFFSET STR3 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H MOV AH,9 MOV DX,OFFSET BUFF3 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H ;SAVE ES AND SET ES TO DS PUSH ES PUSH DS POP ES ;STOSB,LODSB CLD MOV CX,LEN MOV DI,OFFSET BUFF3 MOV SI,OFFSET BUFF3 WHILE1: LODSB CMP AL,'a' JB NEXT CMP AL,'z' JG NEXT SUB AL,20H STOSB JMP NEXT1 NEXT: INC DI NEXT1: LOOP WHILE1 POP ES ;PRINT MOV AH,9 MOV DX,OFFSET BUFF3 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H P_5_13: ;PRINT MOV AH,9 MOV DX,OFFSET STR4 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H MOV AH,9 MOV DX,OFFSET BUFF4 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H MOV AH,9 MOV DX,OFFSET BUFF5 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H ;SAVE ES AND SET ES TO DS PUSH ES PUSH DS POP ES ;CMPSB CLD MOV CX,LEN MOV DI,OFFSET BUFF5 MOV SI,OFFSET BUFF4 JMP WHILE3 WHILE2: ;WAY1 CMPSB JB SMALLER JG BIGGER LOOP WHILE2 WHILE3: ;WAY2 REPZ CMPSB JB SMALLER JA BIGGER BIGGER: ;SRC>DST MOV AH,9 MOV DX,OFFSET BIG_STR INT 21H JMP END_P_5_13 SMALLER: ;SRC<DST MOV AH,9 MOV DX,OFFSET SMALL_STR INT 21H END_P_5_13: MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H P_5_14: ;跑不通,原因不详 PUSH ES PUSH DS POP ES MOV AH,9 MOV DX,OFFSET STR5 INT 21H MOV AH,9 MOV DX,OFFSET NEW_LINE INT 21H MOV AL,'A' CLD MOV CX,LEN MOV DI,OFFSET BUFF5 REPNZ SCASB POP ES JNZ EXIT MOV AH,9 MOV AX,OFFSET BUFF5 INT 21H EXIT: MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN
第6章 子程序结构·
6.1 子程序设计方法·
过程定义·
1 2 3 PROC_NAME PROC FAR ;默认为NEAR ... PROC_NAME ENDP
过程调用与返回·
使用CALL进行调用,RET返回调用者程序
CALL和RET都有FAR和NEAR属性
段内调用和返回使用NEAR,段间调用与返回使用FAR
段间返回的RET指令经汇编后会变成RETF
如果调用指令和所定义过程在同一代码段 ,则定义为NEAR 属性,可省略NEAR
调用指令与所定义过程不在一个代码段 ,则定义为FAR 属性。
6.2 编写子程序注意事项·
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 DISPLAY_STRING PROC FAR PUSH AX MOV AH,2 INT 21H POP AX RET DISPLAY_STRING ENDP DISPLAY_CHAR PROC FAR PUSH AX MOV AH,9 INT 21H PUSH DX MOV DX,OFFSET NEW_LINE ;打印换行符 MOV AH,9 INT 21H POP DX POP AX RET DISPLAY_CHAR ENDP
确定接口参数与传参·
第7章 高级汇编语言技术·
7.1 宏·
宏定义·
1 2 3 宏名 MACRO [形参表] ... ENDM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 PRINTCHAR MACRO OR DL,30H MOV AH,2 INT 21H ENDM PRINTCHAR1 MACRO REG MOV DL,REG OR DL,30H MOV AH,2 INT 21H ENDM PRINCHARS MACRO REG1,REG2 MOV DL,REG1 MOV AH,2 INT 21H MOV DL,REG2 MOV AH,2 INT 21H ENDM PRINCHARS AL,BL
7.2 结构·
1 2 3 4 5 6 7 8 9 10 结构名 STRUC ... 结构名 ENDS ;如,描述学生 STUDENT STRUC CLASS DB 8 DUP(?) ;班号 NUM DW ? ;学号 NAME1 DB 20 DUP(? ) ;名字 STEDENT ENDS
结构的预置与内存分配·
结构预置定义·
1 2 3 结构变量名 结构名 <字段值表> STUDENT1 STUDENT <'19373000',01,'SHARP'> STUDENTS STUDENT 28 DUP(<'19373000',01,'SHARP'>)
访问结构变量及其字段·
1 2 3 4 5 6 7 8 9 10 MOV CX,TYPE STUDENT1 ;CX=30 是结构体的长度 MOV BX,OFFSET STUDENT1 ;BX=STUDENT1的偏移值 MOV CX,LENGTH STUDENT1 ;CX=1 MOV CX,LENGTH STUDENTS ;CX=28 MOV CX,SIZE STUDENTS ;CX=28*30 MOV SI,OFFSET STUDENT1.NUM ;获得结构体中NUM变量的首地址 MOV AX,[SI].NUM[1] MOV AX,STUDENT1.NUM[1] MOV AX,STUDENT1.NUM+1
第8章 输入/输出程序设计·
8.1 输入/输出指令·
Intel 8086/8088内存寻址空间为1MB,而I/O空间为64KB
IN/OUT指令·
1 2 IN OP1,OP2 ;OP1为AL/AX OP2为输入端口地址或DX(用来存放端口地址) OUT OP1,OP2 ;OP1为输出端口地址或DX,OP2为AL/AX
8.2 输入/输出控制方式·
程序控制的I/O方式·
立即传送方式·
程序查询方法·
中断控制方式·
直接内存访问方式 DMA·
8.3 中断控制方式·
中断源·
内中断·
外中断·
中断优先级·
中断向量表·
中断过程·
8.4 编写中断处理程序·