精华内容
下载资源
问答
  • 转移指令 一、无条件转移指令 (1)JMP指令概述 (2)JMP指令类型 1.段内转移、相对寻址 2.段内转移、间接寻址 3.段间转移、直接寻址 4.段间转移、间接寻址 (3)条件转移指令的使用 1.标号的地址属性 2.控制转移 二、条件...

    转移指令

    在这里插入图片描述

    一、无条件转移指令

    (1)JMP指令概述

    JMP 称为无条件转移 (Jump) ,就是无任何先决条件就能使程序改变执行顺序。

    • 执行无条件转移指 JMP, 就可以使程序转到指定的目标地址处,从目标地址处开始执行指令。
    • JMP 指令相当于高级语言的 GOTO 语句 结构化程序设计要求尽量避免使用GOTO 语句,但指令系统决不能缺少 JMP ,汇编语言编程也不可避免地要使用 JMP 指令。

    (2)JMP指令类型

    JMP 根据目标地址的转移范围和寻址方式,可以分成4种类型。

    • MASM 汇编程序会根据存储模型和目标地址等信息自动识别是段内转移还是段间转移,也能够根据位移 大小自动形成短转移或近转移指令。
    • 32 位保护方式使用平展存储模型,不允许应用程序进行段间转移

    1.段内转移、相对寻址

    JMP label 	;EIP=EIP+位移量
    

    段内相对转移 JMP指令 利用标号 (LABEL) 指明目标地址。

    • 当向地址增大方向转移时,位移量为正;向地址减小方向转移时,位移量为负(补码表示)。
    • EIP 指向的偏移地址改变,段寄存器 CS 的内容不变

    2.段内转移、间接寻址

    JMP r32/rl6		 	; EIP = r32/r16 , 寄存器间接寻址
    JMP m32/m16 		; EIP = m32/m16 , 存储器间接寻址
    

    段内间接转移 JMP 32 位通用寄存器或主存单元内容(线性地址空间)或者 16位通用寄存器或主存单元内容(实地址存储模型)送入 EIP 寄存器,作为新的指令指针(即偏移地址),但不修改 CS 寄存器的内容。

    3.段间转移、直接寻址

    JMP label 			; EIP = label 的偏移地址,CS= label 的段选择器
    

    段间直接转移 JMP 是将标号所在的段选择器作为新的 CS 值,标号在该段内的偏移地址作为新的 ElP 这样,程序跳转到新的代码段执行.

    4.段间转移、间接寻址

    JMP m48/m32 		;EIP=m48/m32 , CS =m48+4/m32+2
    
    • 在32位线性地址空间用一个字存储单元 (48 位,使用了符号m48) 表示要跳转的目标地址,将低双字送 EIP 寄存器 CS 寄存器(小端方式);
    • 在16位实地址存储模型中,用一个双字存储单元表示要跳转的目标地址,将低字送 EIP 寄存器、高字送入CS 寄存器(小端方式)。

    (3)条件转移指令的使用

    1.标号的地址属性

    使用offset + 标号 获取标号所在指令的地址

    • 指令寄存器间接寻址

      mov eax,offset label
      jmp eax
      
    • 指令存储器间接寻址

      mov eax,offset label
      mov nvar,eax
      jmp nvar
      

    2.控制转移

    汇编程序提供了短转移SHORT 、近转移 NEAR PTR 和远转移 FAR PTR 操作符,强制转换一个标号、段名或子程序名的类型,形成相应的控制转移。

    jmp near ptr label		;强制生成相对寻址的近转移
    

    二、条件转移指令

    (1)JCC指令概述

    条件转移指令 Jcc 根据指定的条件确定程序是否发生转移,条件满足,发生转移、跳转到 LABEL 位置,即 EIP=EIP+ 位移量。否则,顺序执行下条指令。

    • 语法格式:

      Jcc label
      

      label表示目标地址采用段内相对寻址

    • 流程图表示
      在这里插入图片描述

    (2)条件转移指令分类

    条件转移指令中的条件是由状态标志决定,共16条指令,分成两类。
    在这里插入图片描述

    ①单个标志状态作为条件

    5个状态标志ZF、CF、SF、OF和PF的10种状态

    1.利用零位标志ZF的条件转移指令
    • 判断条件:运算结果为0、两数相等(标志ZF=1)

      JZ label ;Jump if Zero
      
      JE label ;Jump if Equal
      
    • 判断条件:结果不为0、不相等(标志ZF=0)

      JNZ label ;Jump if Not Zero
      
      JNE label ;Jump if Not Equal
      
    2.利用进位标志CF的条件转移指令
    • 判断条件:运算结果有进位(借位)(标志CF=1)

      JC label ;Jump if Carry
      
    • 判断条件:结果没有进位(借位)(标志CF=0)

      JNC label ;Jump if Not Carry
      
    3.利用溢出标志OF的条件转移指令
    • 判断条件:运算结果有溢出(标志OF=1)

      JO label ;Jump if Overflow
      
    • 判断条件:结果没有溢出(标志OF=0)

      JNO label ;Jump if Not Overflow
      
    4.利用符号标志SF的条件转移指令
    • 判断条件:运算结果是负、最高位为1(标志SF=1)

      JS label ;Jump if Sign
      
    • 判断条件:结果是正、最高位为0(标志SF=0)

      JNS label ;Jump if Not Sign
      
    5.利用奇偶标志PF的条件转移指令
    • 判断条件:低8位结果中1的个数为偶或0(标志PF=1)

      JP label ;Jump if Parity
      
      JPE label ;Jump if Parity Even
      
    • 判断条件:低8位结果中1的个数为奇(标志PF=0)

      JNP label ;Jump if Not Parity
      
      JPO label ;Jump if Parity Odd
      

    ②两数大小关系作为条件

    1.比较无符号整数大小

    4种情况:低于、不低于、低于等于、高于
    无符号数大小用高(Above)、低(Below)助记符

    • 判断条件:低于、不高于等于(标志CF=1)

      JB ;Jump if Below
      
      JNAE ;Jump if Not Above or Equal
      
    • 判断条件:不低于、高于等于(标志CF=0)

      JNB ;Jump if Not Below
      
      JAE ;Jump if Above or Equal
      
    • 判断条件:低于等于、不高于(标志CF=1或ZF=1)

      JBE ;Jump if Below or Equal
      
      JNA ;Jump if Not Above
      
    • 判断条件:不低于等于、高于(标志CF=0且ZF=0)

      JNBE ;Jump if Not Below or Equal
      
      JA ;Jump if Above
      
    2.比较有符号整数大小

    4种情况:小于、不小于、小于等于、大于
    有符号数大小用大(Greater)、小(Less)助记符

    • 判断条件:小于、不大于等于(标志SF≠OF)

      JL ;Jump if Less
      
      JNGE ;Jump if Not Greater or Equal
      
    • 判断条件:不小于、大于等于(标志SF=OF)

      JNL ;Jump if Not Less
      
      JGE ;Jump if Greater or Equal
      
    • 判断条件:小于等于、不大于(标志SF≠OF或ZF=1)

      JLE ;Jump if Less or Equal
      
      JNG ;Jump if Not Greater
      
    • 判断条件:不小于等于、大于(标志SF=OF且ZF=0)

      JNLE ;Jump if Not Less or Equal
      
      JG ;Jump if Greater
      

    (3)产生条件的指令

    1.比较指令CMP

    进行减法运算,用于判断两个数据大小、是否相等

    将目的操作数减去源操作数,差值不回送目的操作数,按照减法结果影响状态标志

    CMP reg,imm/reg/mem ;reg-imm/reg/mem
    
    CMP mem,imm/reg ;mem-imm/reg
    
    • 根据标志状态获知两个操作数的大小关系
    • 给条件转移等指令使用其形成的状态标志

    2.测试指令TEST

    进行逻辑与运算,用于判断某位为0或为1等

    按位进行逻辑与运算,不返回逻辑与结果

    TEST reg,imm/reg/mem ;reg ^ imm/reg/mem
    
    TEST mem,imm/reg ;mem ^ imm/reg
    
    • TEST指令像AND指令一样来设置状态标志
    • 常用于检测一些条件是否满足,一般后跟条件转移指令,目的是利用测试条件转向不同的分支

    3.其他指令(能够影响状态标志的指令)

    加减运算指令、逻辑运算指令、移位指令等

    循环指令

    循环条件判断可以使用条件转移指 ,同时 IA-32 处理器针对个数控制的循环设计有若干条指令, 要是 LOOP 指令和 JECX 指令。

    一、LOOP指令

    IA-32 处理器 的循环指令是 LOOP,使用 ECX 寄存器作为计数器(在实地址存储模型 使用 CX), 每执行 LOOP, ECX-1。然后判断 ECX 是否为 0: 如果不为 0, 表示循环没有结束,则转移到指定的标号处;如果为 0, 表示循环结束,则顺序执行下一条指令。

    (1)LOOP指令格式

    循环指 LOOP 的格式如下:

    LOOP label
    
    • 功能1:ECX←ECX-1(相当于 DEC ECX
    • 功能2:若ECX≠0,转移到LABEL, 否则,顺序执行(相当于 JNZ label

    相当于

    DEC ECX 
    JNZ label 
    

    寄存器ECX是默认的计数器,目标地址采用相对短转移

    (2)LOOP指令的应用

    LOOP是循环指令,用于实现减量计数的循环控制

    • 典型应用形式:
    		mov ecx,num 	;设置循环的计数初值num
    label: 	… 				;循环体
    		loop label 		;ECX减1,未到0继续循环
    						;到0循环结束,顺序执行
    
    • LOOP指令的循环次数
      循环初值12 2 32 − 1 2^{32}-1 23210
      循环次数12 2 32 − 1 2^{32}-1 2321 2 32 2^{32} 232

    LOOP指令先减1后判断

     		mov ecx,0 		;设置循环的计数初值 
     label: 	loop label 	;ECX减1,未到0继续循环
    

    在这里插入图片描述

    二、JECXZ指令

    LOOP 指令先进行 ECX 操作,然后判断 如果 ECX 等于0 时执行 LOOP 指令,则将循环 2 32 2^{32} 232次。所以,如果数组元素的个数为 0, 本程序将出错,为此,我们可以使用另一条循环指令JECXZ (实地址存储模型是 JCXZ 指令)排除 ECX 等于0 的情况。

    • JECXZ指令格式:

      JECXZ label
      

      ECX=0,转移到label,否则,顺序执行

      • 相当于:
        CMP ECX,0 
        JZ label 
        

    在这里插入图片描述

    展开全文
  • 目录控制转移类指令无条件转移指令JMP段内转移、直接寻址段内转移、间接寻址条件转移指令判断单个标志位状态比较无符号数高低比较有符号数大小循环指令(loop)子程序指令中断指令系统功能调用字符输出的功能调用字符...

    作为汇编语言的课程笔记,方便之后的复习与查阅

    本篇为课程第八次课内容

    控制转移类指令

    重点掌握:

    • JMP/Jcc/LOOP
    • CALL/RET
    • INT n 常用系统功能调用

    一般了解:

    • LOOPZ/LOOPNZ

    无条件转移指令JMP

    JMP label			;程序转向label标号指定的地址
    

    操作数label是要转移到的目标地址

    JMP指令分成4种类型:

    • 段内转移、直接寻址
    • 段内转移、间接寻址
    • 段间转移、直接寻址
    • 段间转移、间接寻址

    因为现在的硬件条件比较好,所以主要了解段内转移的两种即可

    段内转移、直接寻址

    转移地址和立即数一样,直接在指令的机器代码中,就是直接寻址方式(用标号表达,标号在编译的时候,会转换成直接的地址)

    JMP label			;IP←IP+位移量 实际上是相对寻址
    

    位移量是紧接着JMP指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移。当向地址增大方向转移时,位移量为正;向地址减小方向转移时,位移量为负

    jmp again				;转移到again处继续执行
    	……
    again:	dec cx			;标号again的指令
    	……
    	jmp output			;转向output
    	……
    output:	mov result,al	;标号output的指令
    

    段内转移、间接寻址

    转移地址在寄存器或主存单元中,就是通过寄存器或存储器的间接寻址方式

    JMP r16/m16 			;IP←r16/m16
    

    将一个16位寄存器或主存字单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容

    jmp ax						;IP←AX
    jmp word ptr [2000h]		;IP←[2000h]
    

    条件转移指令

    Jcc label		;条件满足,发生转移:IP←IP+8位位移量
      				;条件不满足,顺序执行
    

    指定的条件cc如果成立,程序转移到由标号label指定的目标地址去执行指令;条件不成立,则程序将顺序执行下一条指令

    操作数label是采用短转移,称为相对寻址方式

    Jcc指令不影响标志,但要利用标志。根据利用的标志位不同,16条指令分成3种情况:

    • 判断单个标志位状态
    • 比较无符号数高低
    • 比较有符号数大小

    判断单个标志位状态

    • JZ/JEJNZ/JNE:利用零标志ZF,判断结果是否为零(或相等)
    • JSJNS:利用符号标志SF,判断结果是正是负
    • JOJNO:利用溢出标志OF,判断结果是否产生溢出
    • JP/JPEJNP/JPO:利用奇偶标志PF,判断结果中“1”的个数是偶是奇
    • JC/JB/JNAEJNC/JNB/JAE:利用进位标志CF,判断结果是否进位或借位

    :如果al最高位为1,ah值设置为0ffh,否则ah值为0

    test al,80h				;测试最高位
    jz next0				;D7=0(ZF=1),转移
    mov ah,0ffh				;D7=1,顺序执行
    jmp done				;无条件转向
    
    next0:	mov ah,0
    done:	...
    

    :计算|X-Y|。X和Y为存放于X单元和Y单元的16位操作数,结果存入result

    mov ax,X
    sub ax,Y
    jns nonneg
    neg ax
    	
    nonneg:	mov result,ax
    

    :计算X-Y,X和Y为存放于X单元和Y单元的16位操作数。若溢出,则转移到overflow处理

    mov ax,X
    sub ax,Y
    jo overflow
    
    ...	;无溢出,结果正确
    overflow:	...	;有溢出处理
    

    :设字符的ASCII码在AL寄存器中,将字符加上奇校验位,在字符ASCII码中为“1”的个数已为奇数时,令其最高位为“0”;否则令最高位为“1”

    and al,7fh			;最高位置“0”,同时判断“1”的个数
    jnp next			;个数已为奇数,则转向next
    or al,80h			;否则,最高位置“1”
    next:
    

    :记录BX中1的个数

    xor al,al					;AL=0,CF=0
    again:	test bx,ffffh 		;等价于 cmp bx,0 		判断bx中是否有1
    		je next				;如果没1,则跳转到next
    		shl bx,1
    		jnc again
    		inc al
    		jmp again
    next:	...					;AL保存1的个数
    
    xor al,al					;AL=0,CF=0
    again:	cmp bx,0
    		jz next
    		shl bx,1			;也可使用 shr bx,1
    		adc al,0			;adc:带CF的加法
    		jmp again
    next:	...					;AL保存1的个数
    

    比较无符号数高低

    • 无符号数的大小用(Above)(Below)表示
    • 利用CF确定高低、利用ZF标志确定相等(Equal)

    两数的高低分成4种关系:

    • <:JBJNAE):CF=1
    • >=:JNBJAE): CF=0
    • <=:JBEJNA): CF=1或ZF=1
    • >:JNBEJA ):CF=0且 ZF=0

    AX,BX中为无符号数,编程将较大者存于AX中,较小者存于BX

    cmp ax,bx			;比较ax和bx
    jnb next			;若ax≥bx,转移
    xchg ax,bx			;若ax<bx,交换
    next:	...
    

    比较有符号数大小

    • 有符号数的(Greater)(Less)
    • 需要组合OFSF标志,并利用ZF标志确定相等(Equal)

    两数的大小分成4种关系:

    • <:JLJNGE):(SFOF)
    • >=:JNLJGE):(SF=OF)
    • <=:JLEJNG):(SFOFZF=1)
    • >:JNLEJG ):(SF=OFZF=0)

    :设AX,BX中为有符号数,编程将较大者存于AX中,较小者存于BX

    	cmp ax,bx					;比较ax和bx
    	jnl next	          		;若ax≥bx,转移
    	xchg ax,bx					;若ax<bx,交换
    next:	...
    

    循环指令(loop)

    LOOP label			;CX←CX-1,
        				;CX≠0,循环到标号label
    LOOPZ label			;CX←CX-1,
        				;CX≠0且ZF=1,循环到标号label
    LOOPNZ label		;CX←CX-1,
        				;CX≠0且ZF=0,循环到标号label
    

    循环指令默认利用CX计数器,方便实现计数循环的程序结构

    :记录空格个数

    	mov cx,count			;设置循环次数
    	mov si,offset string
    	xor bx,bx				;bx=0,记录空格数
    	mov al,20h				;20h为空格的ascii码,用来和每个字符进行比较
    again:	cmp al,es:[si]
    	jnz next				;ZF=0非空格,转移
    	inc bx					;ZF=1是空格,个数加1
    next:	inc si
    		loop again 			;等价于dec cx , jnz again
    							;字符个数减1,不为0继续循环
    

    子程序指令

    子程序是完成特定功能的一段程序。当主程序(调用程序)需要执行这个功能时,采用CALL调用指令转移到该子程序的起始处执行。当运行完子程序功能后,采用RET返回指令回到主程序继续执行

    CALL指令分成4种类型(类似JMP

    CALL label		;段内调用、直接寻址
    CALL r16/m16	;段内调用、间接寻址
    

    CALL指令需要保存返回地址:

    • 段内调用——入栈偏移地址IP
      SPSP-2,SS:[SP]←IP

    RET指令需要弹出CALL指令压入堆栈的返回地址:

    • 段内返回——出栈偏移地址IP
      IPSS:[SP], SPSP+2

    ;主程序
    	mov al,0fh			;提供参数AL
    	call htoasc			;调用子程序
    	...
    ;子程序:将AL低4位的一位16进制数转换成ASCII码
    Htoasc  proc			;Htosac为子程序名称,可以随意命名		proc代表一个子程序
    	and al,0fh			;只取al的低4位
    	or al,30h			;al高4位变成3		0~9转成ascii码只要加上30h
    	cmp al,39h			;是0~9,还是0Ah~0Fh
    	jbe htoend
    	add al,7			;是0Ah~0Fh,加上7		如果是字母的话则再加上7
    htoend:    ret			;子程序最后要用ret返回
    Htoasc endp				;endp代表子程序结束
    

    中断指令

    INT i8  
    

    DOS系统调用表

    系统功能调用

    • 21H号中断是DOS提供给用户的用于调用系统功能的中断,它有近百个功能供用户选择使用,主要包括设备管理、目录管理和文件管理三个方面的功能
    • ROM-BIOS也以中断服务程序的形式,向程序员提供系统的基本输入输出程序

    功能调用的步骤:

    • AH寄存器中设置系统功能调用号
    • 在指定寄存器中设置入口参数
    • 执行指令INT 21H(或ROM-BIOS的中断向量号)实现中断服务程序的功能调用
    • 根据出口参数分析功能调用执行情况

    字符输出的功能调用

    DOS功能调用INT 21H

    • 功能号:AH02H
    • 入口参数:DL=字符的ASCII码
    • 功能:在显示器当前光标位置显示给定的字符,光标右移一个字符位置。如按Ctrl-Break或Ctrl-C则退出

    :在当前显示器光标位置显示一个问号

    mov ah,02h	
    mov dl,'?'	
    int 21h	
    

    进行字符输出时,当输出响铃字符(07H)以及退格(08H)、回车(0DH)和换行(0AH)字符时,该功能调用可以自动识别并能进行相应处理

    字符串输出的功能调用

    DOS功能调用INT 21H

    • 功能号:AH09H
    • 入口参数:
      DX=欲显示字符串在主存中的首地址
      字符串应以$(24H)结束
    • 功能:在显示器输出指定的字符串
      可以输出回车(0DH)和换行(0AH)字符产生回车和换行的作用

    字符输入的功能调用

    DOS功能调用INT 21H

    • 功能号:AH01H
    • 出口参数:AL=字符的ASCII码
    • 功能:获得按键的ASCII代码值
      调用此功能时,若无键按下,则会一直等待,直到按键后才读取该键值

    :判断按键

    getkey:	mov ah,01h		;功能号:ah←01h
    		int 21h			;功能调用
    		cmp al,’Y’		;处理出口参数al
    		je yeskey		;是“Y”
    		cmp al,’N’
    		je nokey		;是“N”
    		jne getkey
    	...
    yeskey:	...
    nokey:	...
    

    字符串输入的功能调用

    DOS功能调用INT 21H

    • 功能号:AH0AH
    • 入口参数:DS:DX=缓冲区首地址(关键就是要定义好缓冲区)
    • 执行该功能调用时,用户按键,最后用回车确认
      本调用可执行全部标准键盘编辑命令;用户按回车键结束输入,如按Ctrl+Break或Ctrl+C则中止

    缓冲区的定义

    • 第1字节事先填入最多欲接收的字符个数(包括回车字符,可以是1~255)
    • 第2字节将存放实际输入的字符个数(不包括回车符)
    • 第3字节开始将存放输入的字符串(回车符也会放入缓冲区)
    • 实际输入的字符数多于定义数时,多出的字符丢掉,且响铃
    • 扩展ASCII码(如功能键等)占两个字节,第1个为0

    :输入字符串

    buffer	db 81 			;定义缓冲区
    						;第1个字节填入可能输入的最大字符数
    		db 0			;存放实际输入的字符数
    		db 81 dup(0)	;存放输入的字符串
    		...
    	
    mov dx,offset buffer
    mov ah,0ah
    int 21h
    

    DOS 文件操作

    建立文件

    • 调用号: 3CH
    • 参数: DX=文件要存放的路径的字符串的地址,该字符串结束用0表示
      CX=文件属性 0 :一般 1:只读 2:隐蔽 4:系统
    • 返回: 成功:AX=文件代号,错误:AX=错误码

    打开文件

    打开文件了之后一定要关闭

    • 调用号: 3DH
    • 参数: DX=文件路径的字符串的地址,该字符串结束用0表示
      AL:为打开方式 =0 读 =1 写 =3 读/写
    • 返回: 成功:AX=文件代号
      错误:AX=错误码

    关闭文件

    • 调用号: 3EH
    • 参数: BX=文件代号
    • 返回: 错误:AX=错误码

    读取文件

    • 调用号: 3FH
    • 参数: BX=文件代号
      DX=数据缓冲区地址
      CX=读取的字节数
    • 返回:读成功: AX=实际读入的字节数
      AX=0 已到文件尾
      读出错:AX=错误码

    写文件

    • 调用号: 40H
    • 参数: BX=文件代号
      DX=数据缓冲区地址
      CX=写入的字节数
    • 返回:读成功: AX=实际写入的字节数
      读出错:AX=错误码

    练习:文件写入 + 字符串加密解密

    这个练习部分主要是记录两个作业题

    1. 要求是将用户输入的内容写入文本文件data.txt中
    .model tiny
    .code
    .startup
        mov dx, offset hello_str
        call print_str
    
        mov ah, 0ah ; 读取输入
        mov dx, offset buffer
        int 21h
    
        mov ah, 41h ; 删除文件
        mov dx, offset file_path
        int 21h
    
        mov ah, 3ch ; 创建文件
        mov dx, offset file_path
        mov cx, 00h
        int 21h
    
        mov bx, ax ; 写入文件
        mov ah, 40h 
        mov cx, 00h
        mov cl, byte ptr [buffer+1] ; 注意这里前后位数要一致
        mov dx, offset buffer+2
        int 21h
     
        mov ah, 3eh ; 关闭文件
        int 21h
    
        mov dx, offset end_str
        call print_str
    
        .exit 0
    
        print_str proc
            mov ah, 09h  
            int 21h
            ret
        print_str endp
    
        buffer_size equ 101 ; 最多支持输入100个字符
        buffer  db buffer_size ;定义缓冲区
                db 0 ; 存放实际输入的字符数
                db buffer_size dup(?) ; 存放输入的字符串
    
        file_path db 'data.txt', 0
        hello_str db 'Please input message(no more than 100 characters):', 0dh, 0ah, '$'
        end_str db 'message saved successfully!', 0dh, 0ah, '$'
    end
    
    1. 进行字符串的加密和解密

    我采用的加密方法是先将输入的字符串进行倒序,然后奇数字节和偶数字节分别于不同的8位密钥进行异或操作,最后再将每个字节的前4位和后4位交换位置

    最后程序的效果如下:
    在这里插入图片描述
    首先会输出一行菜单,之后输入1表示进行加密,输入2表示进行解密,输入3表示退出程序。
    如果选择加密模式,则要在之后输入不超过100个字符的字符串进行加密,输入完毕之后程序会输出加密完的字符串,同时在当前目录下生成一个encrypt.txt文件
    如果选择解密模式,则要先确保当前目录下有encrypt.txt文件,之后输入需要解密的字节数,比如上例中要解密的字节数就为14,之后程序会根据encrypt.txt文件和字节数,将解密结果输出到屏幕上

    总的来说思路挺简单,但是刚开始写汇编,各种错误还是不少,真正完成这个程序还是花了点时间的

    .model tiny
    .code
    .startup
    again:
        mov dx, offset hello_str
        call print_str
    
        call read_input
        
        mov al, byte ptr [buffer+2]
        cmp al, 31h
        jz encryption ; 加密
        cmp al, 32h
        jz decryption ; 解密
        cmp al, 33h
        jz over ; 结束程序
    
        mov dx, offset err_str ; 输入错误
        call print_str
        jmp again
    
        encryption:
            mov dx, offset encryption_str 
            call print_str
            call read_input
    
            xor ax, ax
            mov al, byte ptr [buffer+1] ; 保存字符串长度
            mov word ptr [str_len], ax
    
            ; 将字符串逆序存放到output中
            call reverse_str
    
            ; 异或 奇数byte与偶数byte分别与不同的key进行异或
            ; 每个字节异或之后,前后半个字节交换位置
            mov cx, word ptr [str_len]
            xor_encryption:
                mov bx, offset output-1 ; bx中保存要处理的字节地址
                add bx, cx
                mov ax, cx
                mov dl, 02h
                div dl
                cmp ah, 0 
                jnz odd_xor ; 奇数字节跳转
                mov dl, byte ptr [even_key]
                xor dl, byte ptr [bx]
                mov byte ptr [bx], dl
                jmp exchange
                odd_xor:
                    mov dl, byte ptr [odd_key]
                    xor dl, byte ptr [bx]
                    mov byte ptr [bx], dl
                exchange:
                    ; 将前后半字节交换位置
                    mov dl, cl
                    mov cl, 4
                    ror byte ptr [bx], cl
                    mov cl, dl ; 注意这里cx还要用做循环,值一定要还原回来
                loop xor_encryption
    
            jmp create_encryption_file
    
        decryption:
            mov dx, offset decryption_str 
            call print_str
            call read_input ; 读入需要解密几个字节
    
            cmp byte ptr [buffer+3], 0dh 
            jnz two_bits    ; 输入2位数则跳转
            xor cx, cx
            mov cl, byte ptr [buffer+2] ; cl中存需要解密几个字节
            sub cl, 30h
            jmp save_str_len
    
            two_bits:
                xor cx, cx
                mov cl, byte ptr [buffer+2] ; 十位
                sub cl, 30h
                mov al, cl
                mov dh, 10
                mul dh
                mov cl, byte ptr [buffer+3] ; 个位
                sub cl, 30h
                add cl, al
            save_str_len:
                mov word ptr str_len, cx ; 保存字符串长度
    
            mov ah, 3dh ; 打开文件
            mov dx, offset encryption_file
            mov al, 00h
            int 21h
    
            ; 读取文件
            mov bx, ax
            mov ah, 3fh 
            mov dx, offset buffer+2
            int 21h
    
            mov byte ptr [buffer+1], al 
        
            mov ah, 3eh ; 关闭文件
            int 21h
    
            ; 前后半个字节交换位置
            ; 然后 异或 奇数byte与偶数byte分别与不同的key进行异或
            mov cx, word ptr [str_len]
            xor_decryption:
                mov bx, offset buffer+1 ; bx中保存要处理的字节地址
                add bx, cx
    
                ; 将前后半字节交换位置
                mov dl, cl
                mov cl, 4
                ror byte ptr [bx], cl
                mov cl, dl ; 注意这里cx还要用做循环,值一定要还原回来
    
                ; 异或
                mov ax, cx
                mov dl, 02h
                div dl
                cmp ah, 0 
                jnz odd_dexor ; 奇数字节跳转
                mov dl, byte ptr [even_key]
                xor dl, byte ptr [bx]
                mov byte ptr [bx], dl
                loop xor_decryption
                odd_dexor:
                    mov dl, byte ptr [odd_key]
                    xor dl, byte ptr [bx]
                    mov byte ptr [bx], dl
                    loop xor_decryption
            
            ; 将字符串逆序存放到output中
            call reverse_str
    
            ; 显示解密后的字符串
            mov dx, offset over_str
            call print_str
            mov dx, offset output
            call print_str
    
            jmp again
    
        create_encryption_file:
            mov ah, 41h ; 删除文件
            mov dx, offset encryption_file
            int 21h
    
            mov ah, 3ch ; 创建文件
            mov dx, offset encryption_file
            mov cx, 00h
            int 21h
    
            mov bx, ax ; 写入文件
            mov ah, 40h 
            mov cx, word ptr [str_len] ; 注意这里前后位数要一致
            mov dx, offset output
            int 21h
        
            mov ah, 3eh ; 关闭文件
            int 21h
    
            ; 显示加密后的字符串
            mov dx, offset over_str
            call print_str
            mov si, offset output
            add si, word ptr [str_len]
            mov byte ptr [si], 24h ; 注意: 如果要显示的话,最后还要加上美元符
            mov dx, offset output
            call print_str
    
            jmp again
    
        over:
            .exit 0
    
        read_input proc
            mov ah, 0ah ; 读取输入
            mov dx, offset buffer
            int 21h
            ret
        read_input endp
    
        print_str proc
            mov ah, 09h  
            int 21h
            ret
        print_str endp
    
        reverse_str proc
            mov cx, word ptr [str_len]
            mov si, offset buffer+1
            add si, word ptr [str_len] ; si保存buffer中最后一个字符的地址
            mov di, offset output ; di保存output的首地址
            reverse:
                mov al, byte ptr [si]
                mov byte ptr [di], al
                dec si
                inc di
                loop reverse
            ret
        reverse_str endp
    
        buffer_size equ 101 ; 最多支持输入100个字符
        buffer  db buffer_size ;定义缓冲区
                db 0 ; 存放实际输入的字符数
                db buffer_size dup(?) ; 存放输入的字符串
        output  db buffer_size dup(?)
    
        str_len     dw ?
        odd_key     db 2ch
        even_key    db 44h
    
        encryption_file db 'encrypt.txt', 0
        decryption_file db 'decrypt.txt', 0
        hello_str   db  0dh, 0ah, 0dh, 0ah, 'Input 1--encryption 2--decryption 3--exit', 0dh, 0ah, '$'
        encryption_str db 0dh, 0ah, 'Please input data to encrypt(no more than 100 characters):', 0dh, 0ah, '$'
        decryption_str db 0dh, 0ah, 'Please input string length(no more than 100 characters):', 0dh, 0ah, '$'
        end_str db 0dh, 0ah, 'message saved successfully!', 0dh, 0ah, '$'
        err_str db 0dh, 0ah, 'Input err!', 0dh, 0ah, '$'
        over_str db 0dh, 0ah, 'Encrypted / Decrepted string:', 0dh, 0ah, '$'
    end
    
    展开全文
  • 一 、转移指令 1.无条件转移指令 JMP 格式: 转移地址可用:寄存器寻址和存储器寻址 2.条件转移指令 Jcc https://blog.csdn.net/qq_36215315/article/details/79879391 这篇文章里写的也挺清楚 注: 只能完成...

    一 、转移指令

    1.无条件转移指令 JMP

    格式:
    在这里插入图片描述

    转移地址可用:寄存器寻址和存储器寻址
    在这里插入图片描述

    2.条件转移指令 Jcc

    https://blog.csdn.net/qq_36215315/article/details/79879391
    这篇文章里写的也挺清楚
    在这里插入图片描述

    注: 只能完成段内短转移,即偏移量为8位的

    在这里插入图片描述

    (1)有符号数

    在这里插入图片描述

    (2)无符号数

    在这里插入图片描述

    e=equal b=below n=not a=above g=greater l=less

    (3)单个标志位测试

    在这里插入图片描述

    二、循环控制指令

    1.LOOP

    在这里插入图片描述

    2.LOOPZ/LOOPE

    在这里插入图片描述

    3.LOOPNZ/LOOPNE

    在这里插入图片描述

    展开全文
  • 转移指令

    2017-05-03 18:09:12
    几种常见转移指令及原理,offset指令

    概述:

    一般情况下指令是顺序地逐条执行的,而在实际中,常需要改变程序的执行流程,这个时候,就用到了转移指令。可以修改IP或者同时修改CS和IP的指令,叫做转移指令。
    按转移行为可分为:
    段内转移:只修改IP,如jmp ax
    段间转移:同时修改CS和IP,如jmp 1000:0
    按指令对IP修改的范围不同可分为:
    段内短转移:IP修改范围为-128~127
    段内近转移:IP修改范围为-32768~32767
    按功能特点可分为:
    无条件转移指令 (如:jmp)
    条件转移指令(如:jcxz)
    循环指令(如:loop)
    过程
    中断

    jmp指令:

    转移的目标地址在指令中:
    1. jmp short 标号 段内短转移
    IP的修改范围为 -128~127,8位的位移
    2. jmp near ptr 标号 段内近转移
    IP的修改范围为 -32768~32767,16位的位移
    实现原理:
    对于段内短转移,jmp short 标号对应的机器码,存的不是要转移的目的地址,而是偏移地址,jmp的下面一条指令的地址 加上其偏移地址,才是修改后偏移地址。8位位移的范围为-128~127,用补码表示,8位位移由编译程序在编译时算出。
    同理,jmp near ptr 标号实现的功能则是(IP)=(IP)+16位位移
    3. 段间转移(远转移): jmp far ptr 标号
    该指令指明了跳转到的目的地址,即包含了标号的段地址CS和偏移地址IP,在其机器码中也会有所体现。
    转移的目标地址在内存中:
    1, 段内转移
    格式:jmp word ptr 内存单元地址
    从内存单元地址处开始存放着一个字,是转移的目的偏移地址。
    如:

    mov ax,0123H
    mov [bx],ax
    jmp word ptr [bx]
    ;执行后,(IP)=0123H

    2, 段间转移
    格式:jmp dword ptr 内存单元地址
    从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址
    这里写图片描述

    mov ax,0123H
    mov [bx],ax
    mov word ptr [bx+2],0
    jmp dword ptr [bx]
    ;执行后,
    ;(CS)=0
    ;(IP)=0123H
    ;CS:IP指向0000:0123

    转移的目标地址在寄存器中:
    格式:jmp 16位寄存器
    功能: IP =(16位寄存器)

    其他常用指令:

    jcxz指令
    格式:jcxz 标号
    功能:当(cx)≠0时,什么也不做(程序向下执行)
    如果(cx)=0,则转移到标号处执行
    (IP)=(IP)+8位位移,原理同jmp short
    loop指令
    格式:loop 标号
    功能:(cx)=(cx)-1;
    当(cx)=0时,程序向下执行
    当(cx)≠0时,则转移到标号处执行
    (IP)=(IP)+8位位移,原理同jmp short
    ja jna jb jnb指令
    格式: jxxx 标号
    功能:配合cmp指令使用
    如:
    cmp bx,50
    ja fin
    表示如果bx<=50,程序向下执行
    如果bx>50,跳到标号处执行
    (IP)=(IP)+8位位移,原理同jmp short

    offset操作符:

    操作符offset在汇编语言中时由编译器处理的符号,他的功能是取得标号的偏移地址。
    eg:

    assume cs:codeseg
    codeseg segment
    start: mov ax,offset start ; 相当于 mov ax,0
    ;这里也可以写做 lea ax,start
    s: mov ax,offset s ; 相当于mov ax,3
    codeseg ends
    end start
    展开全文
  • 汇编指令——转移指令

    千次阅读 2014-11-09 13:14:52
    可以修改IP或同时修改IP和CS的指令统称为转移指令 1 只修改IP 段内跳转 2 同时修改 CS和IP 段间跳转 段内转移:1短转移(-128——127) 2近转移 (-32768——32767) 8086cpu转移指令分为一下几种...
  • 条件转移指令详解

    千次阅读 2020-03-08 20:01:09
    程序控制指令又称为控制转移指令,包括:转移指令循环控制指令、过程调用指令和 中断指令 4 类。转移指令又分为无条件转移指令和条件转移指令。 1.无条件转移指令 JMP 计算机程序的执行完全按照 CS:IP 的指向执行...
  • 控制转移指令

    2020-07-10 23:04:43
    控制转移指令 一、 实验目的 a) 熟悉、掌握各种控制转移指令格式及其功能 b) 学会使用控制转移指令来控制程序的执行流程 二、 实验重难点 a) 重点:实验中要用到不少控制转移指令,因此要熟悉、掌握 各类控制转移指令...
  • loop转移指令

    2020-11-14 22:13:36
    loop指令为循环指令,所有的循环指令都是短转移指令 所有条件转移指令都是短转移指令,对于的机器码中包含了位移的范围(-128~127) 这个位移范围是编译器在编译的时候计算出来的 指令格式:loop 标号(cx=cx-1,...
  • 一些转移指令

    千次阅读 2017-05-08 13:24:00
    转移指令 # 8086cpu的转移指令分为以下几类: * 无条件转移指令(如:jmp) * 条件转移指令 * 循环指令(如:loop) * 过程(相当于函数) * 中断 # 操作符offset在汇编语言中是由编译器处理的符号,它的...
  • 转移指令的原理

    2018-01-05 17:30:19
    可以修改IP,或同时修改CS和IP对的指令统称为转移指令。概括的来讲,转移指令就是可以控制CPU执行内存中的某处代码的指令 8086CPU的转移行为有以下=几类。 只修改IP的段内转移,比如:jmp ax 同时修改CS和IP时,...
  • 8086CPU指令系统——控制转移指令

    千次阅读 2019-10-01 19:00:47
    控制转移(Control Jump)类指令用于改变程序的执行...调用与返回指令、无条件转移指令、条件转移指令循环控制指令、中断指令。 一、无条件转移指令 二、条件转移指令 三、循环控制指令 四、中断指令 ...
  • 汇编编程笔记--转移循环指令

    千次阅读 2016-07-28 13:12:27
     (2指令意义: 无条件转移指令,类似c语言goto指令,执行此指令时,先将标记名称所在的地址入到指令寄存器(ip)内,程序就执行ip所指之处的指令.  (3)指令执行后,根据结果可能变动的标记: jmp指令并不影响任何标记. >>...
  • 常用汇编程序转移指令

    千次阅读 2017-03-11 23:13:21
    1,无条件转移指令(长转移) JMP无条件转移指令 CALL 过程调用 RET/RETF 过程返回 2,条件转移指令(短转移,-128到+127的距离内)(当且仅当(SF XOR OF)=1时,OP1 JA/JNBE 不小于或不等于时转移.(意思...
  • 汇编语言--常见转移指令

    万次阅读 2020-09-12 23:24:38
    转移指令 可以修改IP,或同时修改CS和IP的指令统称为转移指令转移指令分为以下几类。 (1)无条件转移指令,比如,jmp; (2)条件转移指令,比如,jcxz、je、jb、ja、jnb、jna等; (3)循环指令,比如,loop; ...
  • [汇编]8086指令系统---控制转移指令

    千次阅读 2013-11-18 22:32:50
    这类指令包括无条件转移指令、条件转移指令循环指令、子程序调用和返回指令以及中断和中断返回指令。    ⑴ 无条件转移  JMP 跳转  ⑵ 条件转移  JZ/JNZ 结果为零/不为零则转移  JS/JNS 结果为负/为...
  • 循环控制指令是一组增强型的条件转义指令,用来控制一个程序段的重复执行,重复次数由CX...如果减1后CX≠0,则转移指令中所给定的标号处继续循环;若自动减1后CX=0,则结束循环,转去执行LOOP指令之后的那条指令
  • 汇编学习-转移指令和mul,div指令

    千次阅读 2013-09-12 20:48:26
    汇编中的转移指令有很多种,比如jmp,jcxz,call,ret,retf,loop等,能够分的种类细讲起来也很多,比如转移指令在内存中,转移指令在寄存器中,转移指令大小为16位,转移指令大小为32位等,这样看起来比较凌乱,也很难...
  • 常用转移指令总结

    2020-11-03 21:35:51
    常用转移指令总结 一,jmp指令(无条件转移指令) 1,指令格式 ①段间转移(远转移): jmp far ptr+标号 ②段内短转移: jmp short +标号(8位的位移) ③段内近转移 jmp near ptr+标号(16位位移) 2,jmp...
  • 8086汇编转移指令

    2018-05-05 14:07:59
    转移指令 我们把可以修改IP,或者同时修改CS和IP的指令统称为转移指令 如果只修改IP的称为段内转移,比如说jmp ax 同时修改CS和IP的称为段间指令,比如说jmp 1000:0 由于转移指令对IP的修改范围的不同,软...
  • 循环指令

    2014-04-16 17:20:58
    为了方便构成循环结构,汇编语言提供了多种循环指令,这些循环指令循环次数都是保存在计数器CX或ECX中。除了CX或ECX可以决定循环是否结束外,有的循环指令还可由标志位ZF来决定是否结束循环。 在高级语言中,循环...
  • 汇编语言--转移指令

    万次阅读 2020-09-08 22:00:07
    由于转移指令对IP的修改范围不同,段内转移又分为:短转移和近转移。 短转移IP的修改范围为-128 ~ 127。 近转移IP的修改范围为-32768 ~ 32767。 8086CPU的转移指令分为以下几类。 无条件转移指令(如:jmp) ...
  • 汇编语言之转移指令和原理

    千次阅读 2016-10-31 20:13:47
    可以修改IP,或同时修改CS和IP的指令统称为转移指令。概括地讲,转移指令就是可以控制CPU执行内存 中某处代码的指令。 8086CPU的转移行为有以下几类: 1. 同时修改CS和IP时,称为段间转移,比如:jmp 100:2a7。 2. ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,283
精华内容 13,713
关键字:

循环转移指令