您的位置:首页 > 财经 > 金融 > 莱西做网站公司_晋城疫情防控最新消息今天封城了_今天最新的新闻头条新闻_天津网站推广

莱西做网站公司_晋城疫情防控最新消息今天封城了_今天最新的新闻头条新闻_天津网站推广

2024/12/23 12:29:38 来源:https://blog.csdn.net/qq_45524532/article/details/142771322  浏览:    关键词:莱西做网站公司_晋城疫情防控最新消息今天封城了_今天最新的新闻头条新闻_天津网站推广
莱西做网站公司_晋城疫情防控最新消息今天封城了_今天最新的新闻头条新闻_天津网站推广

转移概念

一般情况下指令是顺序逐条执行,然而在实际情况中常常需要改变程序的执行流程。

转移指令:

  • 可以控制CPU执行内存中某处代码的指令
  • 可以修改IP,或者同时修改CS和IP的指令

转移指令按行为分为:

  • 段内转移:只修改IP,如jmp ax
  • 段间转移:同时修改CS和IP,如jmp 1000:0

根据指令对IP修改的范围不同分为:

  • 段内短转移: IP修改范围为-128~127
  • 段内近转移: IP修改范围为-32768~32767

按转移指令分为:

  • 无条件转移指令:jmp
  • 条件转移指令:jcxz
  • 循环指令:loop
  • 过程
  • 中断

offset偏移地址

格式

offset 标号
assume cs:codeseg
codeseg segment
start:  mov ax, offset start	; 相当于mov ax,0s:mov ax, offset s		; 相当于mov ax,3
codeseg ends
end start

jmp指令,无条件转移

不仅可以修改IP,也可以同时修改CS和IP。

短转移

“jmp short 标号” 的机器指令中,包含的是跳转到指令的相对位置,而不是转移的目标地址,(IP) = (IP) + 8位位移

  • 8位位移 = '标号’处的地址减去jmp指令后的第一个字节的地址;
  • short指明此处的位移为8位位移;
  • 8位位移的范围为-128~127,用补码表示;
  • 8位位移由编译程序在编译时算出
近转移

指令: “jmp near ptr 标号”,功能:(IP) = (IP) + 16位位移

  • 16位位移="标号"处的地址减去jmp指令后的第一个字节的地址;
  • near ptr指明此处的位移为16位位移,进行的段内近转移;
  • 16位位移的范围为-32768~32767,采用补码表示;
  • 16位位移由编译程序在编译时算出;
远转移

指令: “jmp far ptr 标号”

远转移jmp far ptr 标号近转移jmp near ptr 标号
段间转移段内转移
far ptr指明跳转到的目的地址,即包含了标号的段地址CS和偏移地址IPnear ptr指明了相对于当前IP的转移位移,而不是转移的目的地址
assume cs:codesg
codesg segment
start:  mov ax,0mov bx,0jmp far ptr sdb 256 dup(0)s:add ax,1inc ax
codesg ends
end start
转移地址在寄存器中的jmp指令

指令格式:jmp 16位寄存器

assume cs:codesg
codesg segment
start: 	mov ax,0mov bx,axjmp bxmov ax,0123H
codesg ends
end start
转移地址在内存中的jmp指令
jmp word ptr内存单元地址jmp dword ptr内存单元地址
段内转移段间转移
功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址。功能:从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址。
00 — (IP)
02 — (CS)

段内偏移

mov ax,0123H
mov ds:[0],ax
jmp word ptr ds:[0]	; (IP)=0123H

段间转移

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

jcxz指令

指令格式:jcxz 标号 (cx为cx寄存器,z为zero)

功能: 如果cx等于0,则转移到标号处执行,当cx不等于0时,则什么也不做,向下执行。

  • 当cx = 0时,(IP) = (IP) + 8位位移
    • 8位位移="标号"处的地址减去jcxz指令后的第一个字节的地址;
    • 8位位移的范围为-128~127,用补码表示;
    • 8位位移由编译程序在编译时算出;
  • jcxz是有条件转移指令
    • 所有的有条件转移指令都是短转移;
    • 对IP的修改范围都为-128~127;
    • 在对应的机器码中包含转移的位移,而不是目的地址;
assume cs:codesg
codesg segment
start:mov ax,2000Hmov ds,axmov bx,0s:mov cx,[bx]jcxz okinc bxinc bxjmp short sok:mov dx,bxmov ax,4c00Hint 21Hcodesg endsend start

loop指令

指令格式: loop标号

指令操作:

  • (cx) = (cx) - 1;

  • 当(cx) != 0时,转移到标号处执行;

    当(cx) = 0时,程序向下执行;

assume cs:codesg
codesg segment
start:mov cx,6hmov ax,10hs:add ax,axloop smov ax,4c00hint 21h
codesg ends
end start

模块化设计

call指令

调用子程序,call指令实现转移的方式与jmp指令的原理相似。

格式:call 标号

CPU执行call指令:

  • 将当前IP或CS和IP压入栈中
  • 转移到标号处执行指令

call 标号:

  • 16位位移="标号"处的地址减去call指令后的第一个字节的地址;
  • 16位位移的范围为-32768~32767,用补码表示;
  • 16位位移由编译程序在编译时算出;
mov ax,0
call s
mov ax,4c00h
int 21hs: add ax,1ret
指令"call for ptr 标号"-不同段间转移
  • (sp) = (sp) - 2

    ((ss) * 16 + (sp)) = (cs)

    (sp) = (sp) - 2

    ((ss) * 16 + (sp)) = (ip)

  • (cs) = 标号所在的段地址

    (IP) = 标号所在的偏移地址

该指令相当于

push cs
push ip
jmp far ptr 标号
mov ax,0
call far ptr s
; ...
mov ax,4c00h
int 21hs:add ax,1ret
转移地址在内存中的call指令

call word ptr 内存单元地址

相当于:

  • push IP
  • jmp word ptr 内存单元地址
mov sp,10h
mov ax,0123h
mov ds:[0],ax
call word ptr ds:[0]
; 执行之后,(IP)=0123H,(SP)=OEH

call dword ptr 内存单元地址

相当于:

  • push CS
  • push IP
  • jmp dword ptr 内存单元地址
mov sp,10h
mov ax,0123h
mov ds:[0],ax			; 低地址放置偏移地址
mov word ptr ds:[2],0	; 高地址放置段地址
call word ptr ds:[0]
; 执行结果为:(CS) = 0,(IP) = 0123H,(sp) = 0CH

返回指令ret和retf

ret指令采用栈中的数据,修改IP的内容,从而实现近转移。相当于pop IP。

assume cs:codesg,ss:stack
stack segmentdb 16 dup(0)
stack ends
codesg segmentmov ax,4c00hint 21h
start: mov ax,stackmov ss,axmov sp,16mov,ax,0push ax		; 返回的ax值(IP)mov bx,0ret
codesg ends
end start

retf采用栈中的数据,修改CS和IP的内容,从而实现远转移。相当于:

  • pop IP
  • pop CS
assume cs:codesg,ss:stack
stack segmentdb 16 dup(0)
stack ends
codesg segmentmov ax,4c00hint 21h
start: mov ax,stackmov ss,axmov sp,16mov,ax,0push cs		; 返回的cs值(CS)push ax		; 返回的ax值(IP)mov bx,0ret
codesg ends
end start

call 和 ret的配合使用

assume cs:code,ss:stack
stack segmentdb 8 dup(0)db 8 dup(0)
stack ends
code segment
start : mov ax,stackmov ss,axmov sp,16mov ax,1000call smov ax,4c00hint 21hs:  add ax,axret
code ends
end start

mul乘法指令

  • mul寄存器
  • mul内存单元
8位乘法16位乘法
被乘数ALAX
乘数8位寄存器或内存字节单位16位寄存器或内存字单元
结果AXDX(高位)和AX(低位)
mul bl
mul byte ptr ds:[0]
mul word ptr [bx+si+8]
;ax存放结果的低16位
dx存放结果的高16位

示例

; 100 * 10
mov al,100
mov bl,10
mul bl
; 结果: (ax) = 1000 (03E8H)
; 100 * 10000
mov ax,100
mov bx,10000
mul bx
; 结果(bx) = 000FH (ax) = 4240H
; F4240H = 1000000

模块化程序设计

采用寄存器存储参数和结果
  • 参数放置在bx中,即(bx) = N
  • 子程序中采用多个指令进行运算
  • 将结果放置在dx和ax中
; 计算data段中第一组数据的3次方,结果保存在后一组dword单元中
assume cs:code, ds:data
data segmentdw 1,2,3,4,5,6,7,8dd 0,0,0,0,0,0,0,0
data endscode segment
start:  mov ax,datamov ds,axmov si,0mov di,16mov cx,8s:mov bx,[si]call cubemov [di], axmov [di].2, dx	; 作用同上一行一致add si,2add di,4loop smov ax,4c00hint 21hcube:	mov ax,bxmul bxmul bxret
code ends
end start
采用内存单元批量传递数据
  • 将批量数据存放在内存中,随后将它们所在内存空间的首地址放置在寄存器中,传递给需要的子程序。

  • 对于具有批量数据的返回结果,可用同样的方式。

示例如下:

; 将data段中的字符串转换为大写
assume cs:codedata segmentdb 'conversation'
data endscode segment
start:	mov ax,datamov ds,axmov si,0mov cx,12call capitalmov ax,4c00hint 21h
capital:and byte ptr [si], 11011111binc siloop capitalret
code ends
end start
采用栈传递参数

将需要传递给子程序的参数压入栈中,子程序从栈中取得参数。

需要特别注意指令"ret n"的作用

其它数据
返回点IP
a参数
b参数
pop ip
add sp,n	; 舍弃n个参数直接偏移到栈首

示例描述: 计算(a-b)^3,a,b为word型数据。

  • 进入子程序前,参数a,b入栈
  • 调用子程序,使栈顶存放IP
  • 结果: (dx:ax) = (a - b) ^ 3
assume cs:code
code segment
start: 	mov ax,1push axmov ax,3push axcall difcubemov ax,4c00hint 21h
difcube:push bp			; 将bp之前的数值保留mov bp,spmov ax,[bp + 4]		; 获取栈中第一个参数sub ax,[bp + 6]		; 获取栈中第二个参数mov bp,axmul bpmul bppop bp			; 恢复进入段之前的数据ret 4			; 由于压入的两个参数,跳过两个参数直接偏移到栈首
code ends

子程序编写标准框架

  • 子程序开始: 子程序中使用的寄存器入栈

    ​ 子程序内容

    ​ 子程序使用的寄存器出栈

    ​ 返回(ret,retf)

在子模块开始时,将要用到的寄存器内容全都保存,在子程序返回前在恢复。

assume cs:code
data segmentdb 'word',0db 'unix',0db 'wind',0db 'good',0
data endscode segment
start:  mov ax,datamov bx,0mov cx,4s:mov si,bxcall capitaladd bx,5loop smov ax,4c00hint 21hcapital:push cxpush sichange: mov cl,[si]mov ch,0jcxz okand byte ptr [si], 11011111binc sijmp short changeok: pop sipop cxret
code ends
end start

标志寄存器

flag寄存器是按位标记,每一个都有不同的含义,记录特定的信息。

  • 存储相关指令的某些执行结果
  • 为CPU执行相关指令提供行为依据
  • 控制CPU的相关工作方式
标志值为1值为0意义
OverflowOFOVNV溢出
DirectionDFDNUP方向
SignSFNGPL符号
ZeroZFZRNZ零值
ParityPFPEPO奇偶
CarryCFCYNC进位
ZF-零标志(Zero Flag)

标记相关指令的计算结果是否为0

  • ZF = 1,表示"结果为0",1表示逻辑真
  • ZF = 0,表示"结果不为0",0表示"逻辑假"

示例

指令执行结果
mov ax,1
and ax,0
ZF =1,表示"结果为0"
mov ax,1
or ax,0
ZF = 0,表示"结果非0"
PF-奇偶标志(Parity Flag)

记录指令执行之后,结果当中所有二进制位中1的个数

  • 1的个数为偶数,PF = 1
  • 1的个数为奇数,PF = 0
SF-符号标志(Sign Flag)

SF记录指令执行后,将结果视为有符号数

  • 结果为负数,SF = 1
  • 结果为非负,SF = 0

示例

指令执行结果
mov al,10000001
add al,1
结果al为10000010
为负数,则SF = 1
sub ax,ax结果ax为0,为非负数,SF = 0

SF标志是CPU对有符号数运算结果的一种记录,将数据当作有符号数运算时,通过SF可知结果的正负,将数据当作无符号数运算时,SF没有意义。

CF-进位标志(Carry Flag)

进行无符号数运算时,CF记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位。

CF指令执行之后

  • 有进位或借位,CF = 1
  • 无进位或借位,CF = 0

示例

指令执行结果
mov al,98h
add al al
(al) = 30h,CF=1,CF记录了最高有效位向更高位的进位值
add al,al(al) = 60h,CF=0,CF记录了最高有效位向更高位的进位值
sub al,98h(al) = C8h,CF=1,CF记录了最高有效位向更高位的借位值
OF-溢出标志(Overflow Flag)

进行有符号数运算时,如结果超过了机器所能表示的范围称为溢出

OF记录有符号数操作指令执行之后的状态

  • 有溢出,OF = 1
  • 无溢出,OF = 0
指令执行结果
mov al,98
add al,99
(al) = 197,超出了8位有符号数的范围(-128~127),OF = 1
mov al,0F0H
add al,88H
(al) = (-16) + (-120) = -136,有溢出,OF = 1
CF和OF的区别
  • CF是对无符号数运算有意义的进/借位标志位
  • OF是对有符号数运算有意义的溢出标志位
指令执行结果
mov al,0F0H
add al,88H
CF = 1, OF = 1,当无符号数运算有进位,当有符号数运算有溢出。

adc带进位加法指令

adc带进位加法指令,利用CF位上记录的进位值

  • 格式: adc 操作对象1,操作对象2
  • 功能: 操作对象1 = 操作对象1 + 操作对象2 + CF
指令mov al,98h
add al,al
adc al,3
mov ax,1
add ax,ax
adc ax,3
结果(ax) = 34H(ax) = 5
adc执行时,相当于计算
(ax)+3+CF=30H+3+1 = 34H
adc执行时,相当于计算
(ax)+3+CF=2+3+0=5

sbb带借位减法指令

  • 格式:sbb 操作对象1, 操作对象2
  • 功能: 操作对象1 = 操作对象1 - 操作对象2 - CF
  • 利用CF位上记录的借位值
  • (ax) = (ax) - (bx) - CF
; 计算003E1000H - 00202000H结果放在ax,bx中
; 对任意大的数据进行减法运算
mov bx,1000H
mov ax,003EH
sub bx,2000H
sbb ax,0020H

cmp指令

cmp是比较指令,功能相当于减法指令,不保存结果,但指令执行后,将对标志寄存器产生影响。

  • 格式: cmp 操作对象1, 操作对象2
  • 功能: 计算操作对象1减去操作对象2
指令cmp ax,axmov ax,8
mov bx,3
com ax,bx
功能做(ax) - (ax)的运算,结果为0,但并不在ax中保存,仅影响flag的标志位(ax) = 8, (bx) = 3
标志寄存器ZF = 1,PF = 1,SF = 0,CF = 0,OF = 0ZF = 0, PF = 1,SF = 0, CF = 0, OF = 0
无符号数比较与标志位取值

通过cmp指令执行后查看相关标志位的值,

比较关系(ax) ? (bx)(ax) - (bx)特点标志寄存器
等于(ax) = (bx)(ax) - (bx) = 0ZF = 1
不等于(ax) != (bx)(ax) - (bx) != 0ZF = 0
小于(ax) < (bx)(ax) - (bx) 将产生借位CF = 1
大于等于(ax) >= (bx)(ax) -(bx) 不必借位CF = 0
大于(ax) > (bx)(ax) - (bx)既不借位,结果也不为0CF = 0 且 ZF = 0
小于等于(ax) <= (bx)(ax) - (bx)或借位,或结果为0CF = 1 或 ZF = 1
有符号数比较与标志位取值

通过cmp进行有符号数比较(cmp ah bh)。

结果需要(SF)配合是否溢出(OF)得出结论。

比较关系(ax) ? (bx)(ax) - (bx)特点标志寄存器
等于(ah) = (bh)(ah) - (bh) = 0ZF = 1
不等于(ah) != (bh)(ah) - (bh) != 0ZF = 0
小于(ax) < (bx)(ax) - (bx)为负,且不溢出SF = 1且OF = 0
大于(ax) > (bx)(ax) - (bx)为负,且溢出SF = 1且OF = 1
大于等于(ax) >= (bx)(ax) - (bx)为非负,且无溢出SF = 0且OF = 0
小于等于(ax) <= (bx)(ax) - (bx)为非负,且有溢出SF = 0或OF = 1
条件转移指令

根据单个标志位转移的指令

指令含义测试条件
je/jz相等/结果为0ZF = 1
jne/jnz不等/结果不为0ZF = 0
js结果为负数SF = 1
jns结果非负SF = 0
jo结果溢出OF = 1
jno结果不溢出OF = 0
jp奇偶位为1PF = 1
jnp奇偶位不为1PF = 0
jb/jnae/jc低于/不高于等于/有借位CF = 1
jnb/jae/jnc不低于/高于等于/无借位CF = 0

根据无符号数比较结果进行转移的指令

指令含义测试条件
jb/jnae/jc低于则转移CF = 1
jnb/jae/jnc低于则转移CF = 0
jna/jbe不高于则转移CF = 1或ZF = 1
ja/jnbe高于则转移CF = 0且ZF = 0

根据有符号数比较结果进行转移的指令

指令含义测试条件
jl/jnge小于则转移SF = 1且OF = 0
jnl/jge不小于转移SF = 0且OF = 0
jle/jng小于等于则转移SF = 0或OF = 1
jnle/jg不小于等于则转移SF = 1且OF = 1

j = Jump e = Equal n = Not b = Below a = Above l = Less g = Greater s = Sign c = Carry

p = Parity o = Overflow z = Zero

条件转移指令的使用
  • 条件转移指令和cmp指令配合使用,构造条件转移指令
    • 不必考虑cmp指令对相关标志位的影响和条件转移指令对相关标志位的检测

示例

; 如果ah = bh,则ah = ah + ah,否则ah = ah + bhcmp ah,bhje sadd ah,bhjmp short oks:add ah,ah
ok:ret
应用示例

统计数值为8的字节个数。

code segment
start:mov ax,datamov ds,axmov bx,0mov ax,0mov cx,8s:cmp byte ptr [bx],8je okjmp short nextok:inc axnext:inc bxloop smov ax,4c00hint 21h
code ends

统计数值大于8的字节个数

; 找到大于8的数就将ax的值加1
code segment
start:mov ax,datamov ds,axmov bx,0mov ax,0mov cx,8s:cmp byte ptr [bx],8jna nextinc axnext:inc bxloop smov ax,4c00hint 21h
code ends
end start

统计数值小于8的字节个数

; 找到小于8的数将ax的值加1
code segment
start:mov ax,datamov ds,axmov bx,0mov ax,0mov cx,8s:cmp byte ptr [bx],8jnb nextinc axnext:inc bxloop smov ax,4c00hint 21h
code ends
end start

DF标志和串传送指令

DF方向标志位

  • 在串处理指令当中,控制每次操作后si,di的增减。
  • DF = 0,每次操作后si,di递增
  • DF = 1,每次操作后si,di递减

对DF位进行设置的指令

  • cld指令: 将标志寄存器的DF位设置为0(clear)
  • std指令: 将标志寄存器的DF位设置为1(setup)

串传送指令movsb

  • ((es) * 16 + (di)) = ((ds) * 16 + (si))

  • 如果DF = 0,则

    • (si) = (si) + 1
    • (di) = (di) + 1

    如果DF = 1,则

    • (si) = (si) - 1
    • (di) = (di) - 1

串传送指令movsw

  • ((es) * 16 + (di)) = ((ds) * 16 + (si))

  • 如果DF = 0,则

    • (si) = (si) + 2
    • (di) = (di) + 2

    如果DF = 1,则

    • (si) = (si) - 2
    • (di) = (di) - 2

示例

assume cs:codesg,ds:data
data segmentdb 'Welcome to masm!'db 16 dup(0)
data endscodesg segmentstart:mov ax,datamov si,0mov es,axmov di,16cldmov cx,16s:movsbloop smov ax,4c00hint 21h
codesg ends
end start

rep指令

该指令常常与串传送指令搭配使用。

  • 根据cx的值,重复执行后面的指令

    rep movsb 相当于

    s: movsb

    loop s

  • rep movsw 相当于

    s: movsw

    loop s

示例

assume cs:code,ds,data
data segmentdb 'Welcome to masm!'db 16 dup(0)
data endscode segment
start:mov ax,datamov ds,axmov si,0mov es,axmov di,16cldmov cx,8rep movswmov ax,4c00hint 21h
code ends
end start

将F000H段中的最后16个字符复制到data段中(F000FFFFH)。

assume cs:code,ds:data
data segmentdb 16 dup(0)
data ends
code segment
start:mov ax,F000Hmov ds,axmov si,FFFFHmov ax,datamov es,axmov di,15mov cx,16stdrep movsbmov ax,4c00Hint 21h
code ends
start end

注意事项

  • 在编写调用子程序的程序时,注意看下子程序中有没有用到会产生冲突的寄存器,如果有,则使用其它寄存器。
  • 在编写子程序时,不要使用会产生冲突的寄存器。

示例

将data段中的字符串转换为大写。(通过将数据段尾加上0来做判断语句结束)

assume cs:code ds:data
data segmentdb 'conversation',0
data endscode segment
start:	mov ax,datamov ds,axmov si,0call capitalmov ax,4c00hint 21h
capital:mov cl,[si]mov ch,0jcxz okand byte ptr [si], 11011111binc sijmp short capitalok:ret
code ends
end start; 以上子程序依次读取每个字符进行检测,如果不是0,进行大写的转换,如果是0,结束处理。不再需要字符串的长度作为参数。

在运行中将s处的一条指令复制到s0处。

assume cs:codesg
codesg segment
s:  mov ax,bxmov si,offset smov di,offset s0mov ax,cs:[si]mov cs:[di],ax
s0: nopnop
codesg ends
ends
; nop机器码占一个字节,起占位作用

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com