关于寄存器的疑问
寄存器的名称为什么一个ax会出现rax,eax,ax,ah,al
1 2 3 4 5 回答:是为了确保能够被向下兼容,才有这些名称的。 x86基于原始的8086指令集,寄存器是16为宽 x86 ISA将寄存器扩展为32位 x86-64再将它们进一步扩展为64位。 为了保证向后兼容,新指令集中使用的寄存器是旧寄存器的超集
所以在64位寄存器中就会出现如下图:
寄存器
在介绍汇编指令之前,先要了解寄存器,这样才有利于汇编指令的学习
通用寄存器
数据寄存器
指针寄存器
变址寄存器
专用寄存器
控制寄存器
状态标志寄存器
CF标志(Carry Flag)–第0位 ——进位标志位
在进行无符号 运算时,记录最高有效位向更高位的进位值,或向更高位的借位值
例如:
1 2 3 4 5 6 7 8 mov al,98H add al,al 执行后: al=30H,会将溢出值丢弃,但是CF=1 mov al,97H sub al,98H ;执行后:al=FFH,CF=1,CF记录了借位 sub al,al ;执行后:al=0,CF=0 CF记录了借位
PF标志(Parity Flag)–第2位 ——奇偶标志位
判断计算结果bit位中1的个数是否为偶数,1为偶数个就置1,为奇数个就置0
PF标志位是看当前指令执行后的结果
1 2 3 4 例如: mov al,1 add al,10 执行后,结果为00001011B,1的个数为3(奇数),pf=0
AF标志–第4位 ——
ZF标志(Zero Flag)–第6位 ——零标志位
零标志位,对指令进行操作,计算结果为0,则ZF标志位为1;计算结果不为0,则ZF标志位为0。
ZF标志位是看当前指令执行后的结果
1 2 3 4 例如: mov ax,1 sub ax,1 执行后,结果为0,则zf=1
TF标志
IF标志
DF标志
OF标志(Overflow Flag)–第11位 ——溢出标志位
段寄存器
代码段寄存器(CS)
数据段寄存器(DS)
堆栈段寄存器(SS)
附加段寄存器(ES)
汇编指令语句
寻址方式
立即寻址
寄存器寻址
寄存器间接寻址
直接寻址
寄存器相对寻址
汇编指令
在学习汇编指令之前先了解一些缩写
OPD :表示目的操作数Operand Destination
OPS :表示源操作数
mem :表示内存单元Memory
reg :表示通用寄存器Register
seg :表示段寄存器Segment
imm :表示立即数Immediate
MOV指令
“MOV”是赋值指令,用于数据传送,可以将数据域从一个源位置转移到另一个目的的位置(源位置的数据会复制一份到目标位置,而不是单纯的移动)
1 2 3 4 MOV OPD,OPS # MOV AX,8; # 将8赋值给AX,AX=8; MOV BX,10; # 将10赋值给BX,BX=10; MOV AX,BX; # 将BX中的10赋值给AX,AX=BX;
1 2 3 4 MOV reg/mem,imm; 将立即数 赋值给 寄存器/内存单元 MOV seg/reg/mem,reg; 将寄存器 赋值给 段寄存器/寄存器/内存单元 MOV seg/reg,mem; 将内存单元 赋值给 段寄存器/寄存器 MOV reg/mem,seg; 将段寄存器 赋值给 寄存器/内存单元
1 2 两内存单元 不能直接MOV,需要通过寄存器 间接MOV
XCHG指令
1 2 3 4 格式: XCHG OPD,OPS XCHG reg,mem XCHG reg,reg XCHG mem,reg
XCHG指令不能使用立即数作为操作数,并且在段寄存器和累加器之间不能进行交换。
XLAT指令
查表指令
AL
寄存器中的值用作查找表的索引
查找表的基地址由BX
寄存器提供
XLAT
指令将AL
中的值替换为查找表中BX+AL
位置处的值
PUSH、POP指令
ADD指令
加法操作,将源操作数与目的操作数相加,把结果存储到目的操作数中
1 2 3 4 5 6 7 8 ADD 目的操作数,源操作数 ADD AX,BX AX = AX+BX ADD 寄存器,寄存器 ADD 寄存器,内存 ADD 寄存器,立即数 ADD 内存,立即数
ADC指令
SUB指令
CMP指令
1 2 3 4 5 寄存器、内存操作数、立即数 CMP 寄存器,寄存器; CMP 寄存器,内存; CMP 寄存器,立即数; CMp 内存,立即数;
INC指令
LEA指令
取地址指令
能作为地址指针的寄存器有BX、BP、SI、DI
LES指令
取内存地址的内容,准确的来说是将内存中的段偏移地址加载到指定的通用寄存器和ES段寄存器
所以LES目的操作数只能是BX、SI、DI、BP,能配合段寄存器使用取址的寄存器
1 2 3 4 LES BX,[1234H] 将取内存1234H处的4字节 低2字节存到BX寄存器中 高2字节存到ES寄存器中
LDS指令
取内存地址的内容,准确的来说是将内存中的段偏移地址加载到指定的通用寄存器和DS段寄存器
目的操作数的限制同LES指令
1 2 3 4 LDS SI,[1234H] 取内存1234H处的4字节 低2字节存到SI寄存器中 高2字节存到DS寄存器中
OUT指令
从CUP向IO端口写入数据,它将数据从一个寄存器或内存地址输出到指定的IO端口
OUT指令的目的操作数只能是DX,
1 2 3 MOV DX, 0x03F8 ; 将0x03F8端口地址加载到DX寄存器 MOV AL, 65 ; 将ASCII码为65的字符('A')加载到AL寄存器 OUT DX, AL ; 将AL寄存器中的数据输出到0x03F8端口
逻辑运算指令
XOR指令
对源操作数和目的操作数做异或操作,并将结果保存在目的操作数中
运算结果为0,ZF置1,反之置0
运算结果最高位为1,则SF置1,反之置0
CF、OF始终置0
结果为偶数PF置1,反之置0
OR指令
对源操作数和目的操作数进行或运算,并将结果保存在目的操作数中
AND指令
将源操作数和目的操作数进行与操作,并将结果保存在目的操作数中
NOT指令
NOT
指令不会影响任何标志位(如 CF, ZF, SF, OF 等)。
TEST指令
将源操作数和目的操作数进行与操作,并且不保存结果,只影响标志位
影响的标志位
ZF (零标志):如果结果为 0,则设置为 1,否则设置为 0。
SF (符号标志):如果结果的最高有效位为 1,则设置为 1,否则设置为 0。
PF (奇偶标志):如果结果的最低 8 位中有偶数个 1,则设置为 1,否则设置为 0。
CF (进位标志):被清除(设置为 0)。
OF (溢出标志):被清除(设置为 0)。
移位指令
算术位移指令
SAL/SAR指令
逻辑位移指令
SHL/SHR指令
循环位移指令
ROL/ROR指令
RCL/RCR指令
控制转移指令
跳转指令中
A:Above
B:Below
E:Equal
G:Greater
J :Jump
L:Less
N:Not
汇编指令
描述
JA
无符号大于则跳转
JNA
无符号不大于则跳转
JAE
无符号大于等于则跳转(同JNB)
JNAE
无符号不大于等于则跳转(同JB)
JB
无符号小于则跳转
JNB
无符号不小于则跳转
JBE
无符号小于等于则跳转(同JNA)
JNBE
无符号不小于等于则跳转(同JA)
有符号跳转
汇编指令
描述
-------
----
JG
有符号大于则跳转
JNG
有符号不大于则跳转
JGE
有符号大于等于则跳转(同JNL)
JNGE
有符号不大于等于则跳转(同JL)
JL
有符号小于则跳转
JNL
有符号不小于则跳转
JLE
有符号小于等于则跳转(同JNG)
JNLE
有符号不小于等于则跳转(同JG)
转移的方式
段内转移,范围在段内-128~+127范围内称为短转移
段间转移
JMP指令默认是近转移
JMP指令
1 2 3 4 5 6 7 8 9 格式: JMP LABLE JMP SHORT LABLE; JMP NEAR PTR LABLE; JMP WORD PTR [BX]; JMP FAR PTR LABLE; JMP FAR PTR MEM;
用指令中给出的段地址修改CS的值,给出的偏移地址修改IP的值
也可以仅修改IP的值
1 2 3 4 5 6 7 8 9 10 11 12 jmp指令修改CS、IP的值 jmp 数据:数据 例如: jmp 2AE3:3 执行后:CS=2AE3H IP = 0003H jmp 3:0B16 执行后:CS=0003H IP = 0B16H jmp指令仅修改IP的值 jmp 某一合法寄存器,将该合法寄存器里面的值赋值给IP 例如: 假设CS=2000H,IP0003H mov ax,1000H jmp ax 执行后:CS=2000H,IP=1000H
JCC指令
条件转移语句
该指令是段内短转移指令
条件转移中的条件可以分成三类:判断单个标志位状态、比较无符号数高低、比较有符号数大小
判断单个标志位转态
1 2 3 4 5 JZ/jE和JNZ/JNE JS和JNS JO和JNO JP/JPE和JNP/JPO JC/JB/JNAE和JNC/JNB/JAE
jz指令
1 2 3 4 5 6 7 8 9 用法: JZ destination 其中:destination是一个标记或者地址,表示程序在满足条件是要跳转到的目标位置。 例如: MOV AX,0; .... 关于AX的运算 .... JZ ZeroDetected; # 如果AX的值为零,则跳转到ZeroDetected标签处
比较无符号数高低
指令中的A表示高,B表示低,利用CF确定高低、ZF标志确定相等
1 2 3 4 JB/JNAE/JC JNB/JAE/JNC JBE/JNA JNBE/JA
比较有符号数大小
指令中的G(Greater)表示大,L表示小(Less)
1 2 3 4 JL/JNGE JNL/JGE ≥0 则跳转 JLE/JNG ≤0 则跳转 JNLE/JG
其他
循环指令
LOOP指令
循环控制指令
默认利用CX计数器,属于段内短转移。执行时:
CX=CX-1
判断CX是否为0,CX不为0,则跳转;CX为0则不跳转。
执行后续程序
1 2 3 4 格式: LOOP LABLE LOOPZ/LOOPE LABLE LOOPNZ/LOOPE LABLE
LOOPZ/E指令
LOOPZ指令
先判断CX是否为0,CX为0则退出循环,不等于0再接下去判断
再判断ZF是否等于0,ZF等于1进入循环,ZF为0退出循环
LOOPNZ /NE指令
子程序调用及返回指令
CALL指令
子程序调用指令CALL,CALL指令执行时会有以下操作
先push rip
再jmp LABLE
段内调用只要把ip压入栈即可,段间调用要把ip、cs压入栈中
段内直接调用、段内间接调用、段间直接调用、段间间接调用
1 2 3 4 5 6 格式: CALL NEAR PTR LABLE CALL R16/M16 (R16表示16位寄存器,M16表示) CALL FAR PTR LABLE CALL MEM # 不写伪指令默认段内
1 2 3 4 5 6 7 8 call kkk 相当于: push cs push ip 先将cs压入栈中,再将ip压入栈中,因为cs表示地址的高位 # call kkk 下一条指令的cs:ip=ABCDH:3416H # kkk函数的cs:ip=1234H:5678H
RET指令
1 2 3 4 5 6 7 ret pop ip pop cs ret n sp=sp+n
示例
1 2 3 4 5 6 7 8 9 10 11 MOV AL,20H CALL PROC1 PROC1: MOV AH,0 MOV CL,0 DIV CL OR AL,30H MOV BH,AL OR AH,30H MOV BL,AH RET
处理器控制指令
NOP指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 下面是51单片机的软件延时: DELAY100MS: ;@12.000MHz NOP NOP NOP PUSH 30H PUSH 31H PUSH 32H MOV 30H,#4 MOV 31H,#166 MOV 32H,#207 NEXT: DJNZ 32H,NEXT DJNZ 31H,NEXT DJNZ 30H,NEXT POP 32H POP 31H POP 30H RET
LOCK指令
HLT指令
ESC指令
交权指令,CPU控制计算机的总线,能够实现处理操作还有其他处理器,如:8087浮点数处理器等。
使用该指令可以将总线的控制权交给其他处理器
WAIT指令
等待指令,当需要引脚条件成立后才会执行,wait就是等待该条件满足
标志操作指令
对进位位操作
其他
CLD:DF位置零
STD:DF位置1
CLI:IF位置零
STI:IF位置1
端口操作指令
1 2 3 4 5 6 7 8 9 输入输出指令IN和OUT 指令格式: n代表端口号 端口号在0~255时可以使用立即数 端口号大于255,必须将端口先送给DX,再进行IN操作 IN AL,n OUT n,AL IN AX,n OUT n,AX IN AX,DX OUT DX,AL In AL,DX OUT DX,AX
中断指令和中断返回指令
中断向量表
中断向量表存储着中断程序起始位的cs、ip
中断源只允许有256个中断源
中断向量表就需要内存256*4=1024
中断向量表存储在内存的最低位 00000H~003FFH
INT指令
1 2 例如: INT 80H; # pwn常用32位中断
其他
中断指令执行过程
取中断类型号n,n*4作为中断向量表的指针
将标志寄存器内容压入堆栈
保护断点,将当前CS,IP压入堆栈
备份TF标志,并将IF和TF清0,以禁止外部中断
取中断处理器程序对待入口地址送IP、CS
字符串操作指令
串操作数的寻址
源操作数用寄存器SI寻址,默认在数据段DS中,但允许段超越:ES: [SI]。
目的操作数用寄存器DI寻址,默认在附加段ES中,不允许段超越:DS: [DI]。
每执行一次串操作指令,SI和DI都会自动修改:±1(字节串)或±2(字串)。
串传送指令
SI所对应的地址内容,送到DI所对应的地址内容,自动完成SI和DI的自增或自减
1 2 3 4 5 6 7 8 9 指令格式: MOVSB MOVSW 等价于: MOV AL,[SI] MOV [DI],AL INC SI INC DI
例如:将数据段DATA1指示的50个字节传送到本数据段指示的DATA2区域。
1 2 3 4 5 6 7 MOV SI,OFFSET DATA1 MOV DI,OFFSET DATA2 MOV CX,50 CLD AGN: MOVSB DEC CX JNZ AGN
串存储指令
例如:将附加段偏移地址为300H开始的100个存储单元全部清为0。
1 2 3 4 5 6 7 MOV AX,0 MOV DI,300H MOV CX,50; LCD LOP: STOSW DEC CX JNZ LOP
串读取指令
将SI所对应的地址内容给AL或AX,SI自增1或2
串比较指令
俩串数据比较,[SI]和[DI]比较,[DI]-[SI]结果不回送,影响标志位
例如:比较字符串STR1和STR2,字符串长度为20,如果相等AL置0,不相等AL置0FFH
1 2 3 4 5 6 7 8 9 10 11 12 MOV SI, OFFSET STR1 MOV DI, OFFSET STR2 MOV CX, 20 CLD AGN: CMPSB JNZ NLT DEC CX JNZ AGN MOOV AL,0 JMP EXIT NLT: MOV AL,0FFH EXIT:
串扫描指令
从字符串里面去找关键字,实现应把要搜索的关键字放在AL或者AX里面
1 2 3 4 5 SCASB SCASW 等价于: CMP AL,[DI]
例如:搜索STR字符串,查找是否有空格,如果有则转去FIN。
1 2 3 4 5 6 7 8 MOV DI,OFFSET STR MOV AL,20H MOV CX,COUNT CLD AGN: SCASB JZ FIN DEC CX JNZ AGN
重复前缀指令
重复前缀分2类,3条指令
第一类:与MOVS、STOS和LODS指令配合的前缀REP,不影响标志位。
第二类:与CMPS和SCAS指令配合的前缀REPZ和REPNZ,影响标志位
1 2 3 4 5 6 指令格式:REP MOVSB/REP STOSW REPZ CMPS/REPZ SCAS REPNZ CMPS/REPNZ SCAS 注意: REP指令使串操作重复CX规定的次数,REPZ、REPNZ使串操作的重复可能提前结束,根据ZF值的变化 重复前缀和循环控制指令的差别:LOOP先做CX减1,后判断;REP先判断,后做CX减1。
例如:比较字符串STR1和STR2,字符串长度为20,如果相等AL置0,不相等AL置0FFH.
1 2 3 4 5 6 7 8 9 10 MOV SI, OFFSET STR1 MOV DI, OFFSET STR2 MOV CX,20 CLD AGN: REPZ CMPSB JNZ NLT MOV AL,0 JMP EXIT NLT: MOV AL,0FFH EXIT:
例如:用SCASB指令,编程查找字符串STRING中是否包含$字符,若包含,FLAG单元置1;否则FLAG单元置0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 DATA SEGMENT STRING DB N DUP(?) N=$-STRING FLAG DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA START: MOV AX,DATA MOV DS,AX MOV ES,AX MOV AL,'$' MOV DI,OFFSET STRING MOV CX,N CLD REPNZ SCASB JNZ LAB1 MOV FLAG,1 JMP EXIT LAB1: MOV FLAG,0 EXIT: INT 21H CODE ENDS END START
汇编伪指令
1 2 3 4 [名字] 伪指令助记符 参数, 参数...[;注释] 名字:反映伪指令 参数 注释
关于结束的伪指令
END伪指令
END伪指令用于指示汇编器文件的结束。所有程序通常在代码段的结尾使用它。它还可以指定程序的入口点(起始地址)
注意:END是标识源程序的结束而不是程序终止运行
ENDP伪指令
ENDP伪指令用于指示过程(子程序)的结束。它通常与过程的开始伪指令 PROC
一起使用。
1 2 3 MyProcedure PROC ; Procedure code here MyProcedure ENDP
ENDS伪指令
ENDS
伪指令在 x86 汇编语言中用于标志段(segment)的结束。段是内存中的一个连续区域,用于存储代码、数据或堆栈。段的定义从 SEGMENT
或 SEG
伪指令开始,用 ENDS
结束。
ENDM伪指令
ENDM标志宏定义的结束。宏(Macro)。
宏定义从 MACRO
开始,用 ENDM
结束。
1 2 3 4 5 6 7 8 MyMacro MACRO param1, param2 ; 宏代码 mov ax, param1 mov bx, param2 ENDM ; 使用宏 MyMacro 1, 2
参数
数值表达式
算数运算符
逻辑运算符
关系运算符,注意(真为-1,假为0)
运算符的优先顺序
地址型参数
变量
ORG伪指令
1 2 3 格式:ORG N 例如:ORG 30 数据从001EH开始存储
EVEN伪指令
1 2 3 格式:EVEN 例如:EVEN WARY DW 20
ALING对齐伪指令
使下面的内容变量必须从下一个能被NUM整除的地址开始分配
1 2 格式:ALIGN NUM; #NUM必须是2的幂 例如:
特殊运算符
PTR运算符
强制类型运算符,用于给已分配的存储地址赋予另一种属性,仅在本语句有效,不影响原有属性。
THIS运算符
1 2 3 4 5 6 7 格式: 名字 EQU THIS 类型名 例如: BARRAY EQU THIS BYTE WARRAY DW 3344H ...... MOV AL,BARRAY MOV AX,WARRAY
SHORT运算符
数值返回操作符
这一类操作数不改变操作属性,只送操作数的某一属性值
OFFSET操作符
SEG操作符
TYPE操作符
1 2 3 4 5 6 7 DB = 1,DW = 2, DD = 4 NEAR = -1,FAR = -2 array DW 1, 2, 3, 4 ; 定义一个包含4个16位元素的数组 byte_var DB 'A' ; 定义一个单字节变量 mov ax, TYPE array ; AX 中将包含 2,因为每个 `DW`(double word) 是 2 个字节 mov bx, TYPE byte_var ; BX 中将包含 1,因为每个 `DB`(byte) 是 1 个字节
LENGTH操作符
汇编宏指令
1 2 3 LEA DX,STR1 MOV AH,9 INT 21H
宏指令
宏定义
1 2 3 格式:宏定义名 MACRO [形式参数表] 宏定义体 ENDM
1 2 3 4 5 PRINt MACRO STR LEA DX,STR MOV AH,9 INT 21H ENDM
宏调用
1 2 3 4 5 6 ...... PRINT STR1 ...... PRINT STR2 ...... PRINT STR3
宏展开
汇编语言格式
段和模块定义伪指令
段定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 DATA SEGMENT STRING DB N DUP(?) N=$-STRING FLAG DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA START: MOV AX,DATA MOV DS,AX MOV ES,AX MOV AL,'$' MOV DI,OFFSET STRING MOV CX,N CLD REPNZ SCASB JNZ LAB1 MOV FLAG,1 JMP EXIT LAB1: MOV FLAG,0 EXIT: INT 21H CODE ENDS END START
DEBUG
A命令
用于汇编语言输入
语法:a [address]
address是可选参数,指定从哪个内存地址开始汇编。如果不指定地址,将从当前的CS寄存器取址
1 2 3 4 5 a 100 0A23:0100 mov ax, 0002;输入a 100后,就可以再该位置键入汇编指令 0A23:0103 int 21 0A23:0105
D命令
1 2 3 4 5 6 可以直接查看地址 d 0040:0000 0040:0000 00 01 1F 10 也可以用寄存器查看所指地址 d DS:SI
E命令
用于修改内存内容
语法:e [address][data]
按下回车键结束输入
F命令
G命令
H命令
I命令
L命令
M命令
N命令
O命令
P命令
Q命令
R命令
S命令
T命令
U命令
W命令
系统功能调用
MS-DOS的调用过程
将系统调用号送AN寄存器
在指定的寄存器中设置有关入口参数
INT 21H;DOS的中断处理程序,对于不同的系统调用号,能够完成对不同设备的控制
返回DOS的系统调用
调用结束当前正在执行的程序,返回DOS系统。无入口参数。
常用DOS系统调用
字符输入-01H
AH=01,从键盘输入一个字符。机器会等待键盘输入,输入字符的ASCII码存于AL中。
单字符输出-02H
AH=02,要显示的字符存于DL中,即入口参数DL=字符的ASCII
1 2 3 MOV AH,2 MOV DL,'a' INT 21H ;输出字符
字符串输出-09H
AH=09,要输出的字符串的首地址存于DX寄存器中,即入口参数DS:DX=字符串首地址,字符串必须以$(24H)结尾。
1 2 3 MOV AH,09 LEA DX,BUF ;BUF为字符串首地址 INT 21H
字符串输入-0AH
1 2 3 4 5 BUFF DB 10H,?,10H(?) MOV DX,OFFSET BUFF MOV AH,0AH INT 21H 键入:0123456789
汇编程序
顺序程序设计
存储单元内容移位
将存储单元A中的内容左移4位,存储单元B中的内容右移2位(移位后的空位为0)
屏蔽与组合
将字类型变量A的高4位和低4位置0,其余各位保持不变。
拆字
将存储单元A中两个压缩BCD数拆成两个非压缩BCD数(高位BCD数放C单元中,低位BCD数放B单元中),然后分别转换为两个ASCII代码。
查表程序设计
加减运算
已知Z=(X+Y)-(W+Z),其中X,Y,Z,W均为字节存储单元,存放的数据均用压缩BCD码表示。编写完成上式的程序段。
乘法运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 MOV AL,10 MUL BL ;该程序需要70个时钟周期 MOV AL,BL MOV AH,0 SAL AX,1 MOV BX,AX SAL AX,1 SAL AX,1 ADD AX,BX ;只需15个时钟周期 MOV AL,BL MOV AH,0 ADD AX,AX MOV BX,AX ADD AX,AX ADD AX,AX ADD AX,BX ;只需18个时钟周期
混合运算
用顺序结构来编程实现求无符号数S=(x^2+Y^2)/Z的值,将最后结果放入RESULT单元保存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 DATA SEGMENT X DB 5 Y DB 7 Z DB 2 RESULT DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA; MOV AX,DATA MOV DS,AX MOV AL,X MUL X MOV BX,AX MOV AL,Y MUL Y ADD AX,BX DIV Z MOV RESULT,AL MOV AH,4CH INT 21H CODE ENDS END START
求数的补码与反码
将自变量A转换为补码和反码,分别存入自变量B和C中
1 2 3 4 5 6 7 8 9 10 11 MOV AX,A NOT AX MOV B,AX INC AX MOV C,AX 还可以 MOV AX,A NEg AX MOV C,AX DEC AX MOV B,AX
分支程序设计
条件转移指令和无条件转移指令JMP用于实现程序的分支。
输入小写——输出大写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 CODE SEGMENT ASSUME CS:CODE START: MOV AH,01H INT 21H JMP AL,'a' JB EXIT CMP AL,'z' JA EXIT SUBB AL,20H MOV DL,AL MOV AH,02H INT 21H EXIT: MOV Ah,4CH INT 21H CODE ENDS END START
多分支程序设计
多分支结构具有若干个条件,每个条件对应一个操作程序。程序必须判断
分段函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 DATA SEGMENT X DB -10 Y DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV AL,X CMP AL,0 JGE BIG MOV BL,-1 JMP EXIT BIG: JE MIN MOV BL,1 JMP EXIT MIN: MOV BL:0 EXIT: MOV Y,BL MOV AH,4CH INT 21H CODE ENDS END START
循环程序设计
统计正数和负数
已知有n个有符号二进制数,存放在以BUF为首地址的字节存储区,试统计其中正数和负数的个数。
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 DATA SEGMENT BUF DB -40,78,0,12,-19,41,-34 COUNT EQU $-BUF PLUS DW ? MINUS DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA BEGIN: MOV AX,DATA MOV DS,AX MOV BX,0 MOV DX,0 LEA SI,BUF MOV CX,0 LOP: MOV AL,[SI] CMP AL,0 JG P1 JE P2 INC DX JMP P2 P1: INC BX P2: INC SI INC CX CMP CX,COUNT JL LOP MOV PLUS,BX MOV MINIUS,DX MOV AH,4CH INT 21H CODE ENDS END BEGIN
程序2
编写程序段,求N1和N2两个数组对应的数据之和(数组中的数据个数为M),并将结果存入到新数组N3中。此计算一直进行到两数之和为0或数组结束,并将新数组的长度存放在N4单元中。
1 2 3 4 5 6 7 8 9 10 MOV CX,M MOV BX,-1 L1: INC BX MOV AL,N1[BX] ADD AL,N2[BX] MOV N3[BX],AL LOOPNZ L1 JZ L2 INC BX L2: MOV N4,BX
程序3
试编一个程序实现S=1+2×3+3×4+…+N×(N+1)+…直到N(N+1)项大于100为止
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CODE SEGMENT ASSUME CS:CODE STARTL: MOV DX,1 MOV AX,0 MOV BL,2 NEXT: ADD DX,AX MOV AL,BL INC BL MUL BL CMP AX,100 JBE NEXT MOV AH,4CH INT 21H CODE ENDS END START
子程序设计
子程序定义
1 2 3 4 子程序名 PROC [NEAR/FAR] ...... ;子程序体 RET 子程序名 ENDP
保护现场和恢复现场
示例
例题1:编写一个求两个正整数最大公约数的子程序
分析:求两个数的最大公约数可以用辗转相除法:用M除以N,得余数R,若R=0,则N就是所求的最大公约数;若R≠0,则N→M,R→N,继续求解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 GYS PROC PUSH AX PUSH BX PUSH DX G1: XOR DX,DX DIV BX AND DX,DX JZ EXIT MOV AX,BX MOV BX,DX JMP G1 EXIT: MOV CX,BX POP DX POP BX POP AX RET GYS ENDP
子程序参数调用
示例
例题1:两个6字节数相加。
1 2 DATA SEGMENT ADD1 DB 0FEH
应用程序设计
;