做网站每一步的是什么/百度手机助手app下载
《汇编语言》- 读书笔记 - 第11章-标志寄存器
- 标志寄存器
- 指令与标志位关系
- 11.1 ZF(Zero Flag,零标志位)
- 11.2 PF(Parity Flag,奇偶标志位)
- 11.3 SF(Sign Flag,符号标志位)
- 处理无符号数
- 检测点 11.1
- 11.4 CF(Carry Flag,进位标志位)
- 加法进位
- 减法借位
- 11.5 OF(Overflow Flag,溢出标志位)
- 检测点 11.2
- 11.6 adc 指令(Add with Carry)
- 11.7 sbb 指令(SuBtraction with Borrow)
- 11.8 cmp 指令(Compare)
- 无符号数比较
- 有符号数比较
- 11.9 检测比较结果的条件转移指令
- 根据无符号数比较结果进行转移
- 根据有符号数比较结果进行转移
- 1. 编程
- 2. 编程
- 3. 编程
- 检测点 11.3
- 11.10 DF 标志和串传送指令(Direction Flag)
- movsb、movsw、rep
- cld、std
- 1. 编程
- 2. 编程
- 11.11 pushf 和 popf
- 检测点 11.4
- 11.12 标志寄存器在 Debug 中的表示
- 实验 11 编写子程序
- 参考资料
标志寄存器
寄存器 | 全称 | 含义 | 举例 |
---|---|---|---|
CF | Carry Flag | 进位标志位 | 若算术运算 有进位/借位 ,则CF=1 ,否则CF=0 。例如: ADD AX, BX 后,如果结果导致了进位或借位,CF 会被设置。 |
PF | Parity Flag | (奇)偶标志位 | 根据运算结果中所有 bit 位1 的个数是否为偶数 来设置。若 1 的个数为偶数 ,则 PF=1 ,否则 PF=0 。例如: 0000 0011 则 PF=1 ,0000 0111 则 PF=0 |
AF | Auxiliary Carry Flag | 辅助进位标志位 | 在BCD调整或某些算术运算(如加法和减法)中,当低4位 发生进位 或借位 时 AF=1 ;否则 AF=0 。 |
ZF | Zero Flag | 零标志位 | 结果为零 时,ZF=1 ;否则 ZF=0 。例如: CMP AX, BX ,如果AX 与BX 相等,则 ZF=1 。 |
SF | Sign Flag | 符号标志位 | 结果为负 ,则 SF=1 ,结果为正数或零 ,则 SF=0 CPU 在执行 add 等 指令时,必然影响 SF 标志位。用不用看我们需要。如果我们声明的是 有符号数 ,编译器自动会判断 SF |
TF | Trap Flag | 陷阱标志位 | 当TF=1 时,CPU每执行一条指令后会引发一个单步中断 ,常用于调试 。 |
IF | Interrupt Flag | 中断允许标志位 | IF=1 表示CPU可以响应 可屏蔽中断;IF=0 则禁止响应 可屏蔽中断。 |
DF | Direction Flag | 方向标志位 | 控制串操作指令的自动递增还是递减地址指针。DF=0 表示递增 ,DF=1 表示递减 。 |
OF | Overflow Flag | 溢出标志位 | 当算术运算的结果超出了寄存器所能表示的范围而产生溢出时,OF=1 ;否则 OF=0 。 |
注意:在编程中,通常无需关心标志位的使用,因为编译器会自动处理。但在特殊情况下,可能需要显式使用标志位,此时需深入了解底层硬件和编译器特性。
指令与标志位关系
许多指令在执行时会根据操作结果影响标志位。以下是一些常见的情况:
会影响标志位的指令(包括但不限于):
算术运算指令 | add 、adc 、sub 、sbb 、mul 、imul 、div 、idiv 等 影响标志位:CF(进位/借位标志)、ZF(零标志)、SF(符号标志)、OF(溢出标志) |
---|---|
逻辑运算指令 | and 、or 、xor 、not 、test 影响标志位: CF(某些情况下)、ZF(零标志)、PF(奇偶标志) |
移位指令 | shl 、shr 、sal 、sar 、rol 、ror 等 影响标志位: CF(进位/借位标志)、ZF(零标志)、OF(溢出标志) |
比较指令 | cmp 、test 影响标志位: CF、ZF、SF、OF |
字符串处理指令 | scas 、cmps 等 影响标志位: ZF、SF、OF、AF、PF、CF(根据具体操作) |
不会直接影响标志位的指令(仅列举部分):
数据传送指令 | mov (单纯的数据复制不会改变标志位)push 和pop (虽然它们间接影响栈指针,但并不会改变算术或逻辑运算相关的标志位) |
---|---|
控制转移指令 | jmp 、call 、ret 、loop 等 这类指令不影响标志位,它们主要控制程序流程。 |
处理器控制指令 | cli 、sti 、hlt 等 这类指令通常用于处理器状态控制,而不涉及数据计算,所以不直接影响标志位。 |
请注意,实际情况可能更复杂,某些指令在特定条件下也可能影响某些标志位。此外,有些指令可以通过修改EFLAGS寄存器中的标志位来实现更为复杂的条件判断。
11.1 ZF(Zero Flag,零标志位)
ZF(Zero Flag,零标志位)用于指示最近的算术或逻辑运算结果是否为零。在执行加法、减法、比较等指令后,CPU会根据操作结果自动更新 ZF
。
具体来说:
当一个算术
或逻辑运算
的结果
等于0
时,ZF
会被设置为1
(即ZF=1
),表示运算结果
为零
。
当运算结果
不为0
时,ZF
会被清零
(即ZF=0
)。
11.2 PF(Parity Flag,奇偶标志位)
PF(Parity Flag,奇偶标志位)的设计初衷是为了检查和验证数据传输过程中的错误。在早期的计算机系统中,尤其是使用奇偶校验的硬件设计中,会对每个字节(8位)的数据进行奇偶校验,以确保在传输过程中没有出现错误。
奇偶校验是通过计算一个字节内“1”的个数来实现的,分为两种形式:
偶校验: 如果1
的个数为偶数
,则该字节被认为是有效的,此时PF
设置为1
。
奇校验: 如果1
的个数为奇数
,则该字节被认为是有效的,此时虽然也是PF
标志,但意义是在奇校验情况下表示正确。
11.3 SF(Sign Flag,符号标志位)
结果为负
,则 SF = 1
;结果为非负
数(包括正数和零),则 SF=0
。
CPU
在执行算术运算
指令如 add
、sub
、mul
、imul
等时,会根据运算结果
的最高有效位
更新SF标志位。不管
你程序员用不用。
对于编译器而言,如果声明的是有符号整数,并且进行比较操作时,编译器可能会根据需要生成对应的条件转移指令,这些指令通常会参考SF以及其他标志位(如ZF、OF等)来判断数值的大小关系或者溢出情况。
例如:汇编代码中常见的 jns
(Jump if Not Signed,即若结果是非负数则跳转)这样的条件转移指令就依赖于SF标志位。
总结来说:
SF
标志位反映了算术
运算结果
的符号
信息。- 执行涉及符号的
算术指令
后,SF必然
会被影响。(比如处理无符号数
,我们不理SF
即可) - 编译器在处理有符号数的比较和条件分支时,会自动利用SF和其他相关标志位来进行优化和控制流程。
处理无符号数
在处理无符号数时,SF(Sign Flag)标志位的直接用途并不明显。然而,在某些情况下,尽管SF主要设计用于表示有符号数的符号信息,但在特定场景下它也可以间接提供有用的信息:
-
循环移位操作: 在进行逻辑或算术右移时(如 shl、shr 或 sar 指令),对于无符号数来说,SF可以用来判断移位前最高位的内容。例如,当进行无符号数右移时,如果需要知道移位前的最高位是0还是1,可以在移位前查看SF。
-
条件转移指令: 尽管通常不推荐使用SF来判断无符号数比较结果,但在某些复杂条件转移中,SF可能和其他标志位一起被用作转移条件的一部分。比如,通过结合ZF和SF等标志位可以实现更复杂的条件测试,但这种情况较为少见,并且不如针对无符号数专门设计的标志位(如CF)直观。
-
低效或非标准的编程实践: 在极少数情况下,程序员可能会利用SF作为临时存储标志位,但这并不是其设计初衷,也非最佳实践。现代编程中一般会避免这样的做法。
总的来说,对于无符号数运算,程序员更多依赖于其他标志位,如CF(进位标志)来进行大小比较和溢出判断,而SF在无符号计算中的作用相对较小。
检测点 11.1
《汇编语言》- 读书笔记 - 各章检测点归档 - 检测点 11.1
11.4 CF(Carry Flag,进位标志位)
当执行算术
运算时,CF
用于记录运算过程中产生的进位
或借位
情况。
有就 CF=1
没有就 CF=0
- 当加法中有值从
最高有效位
跑到假想的更高位
处,说明发生了进位
。 - 当进行减法时,被减数需要从
假想的更高位
凭空假借1
来计算,这就发生了借位
。
CF(进位标志位): 主要与无符号数
的算术运算相关。无符号数没有 “溢出” 的概念,只有进位和借位。当进行加法或减法运算时,如果结果导致了最高位出逃
(对于二进制来说,就是最高有效位
向更高位
产生了进位或者借位),则CF
会被设置为1
。
对于无符号整数,这可以看作是单纯的数值大小超过了当前数据类型所能表示的最大范围,而这个“超出”并不会改变
数值的正负
性。
加法进位
在二进制加法中,如果两个二进制数相加时,在最低位(最右边)产生了进位,并且该进位需要继续向更高位(左边)进行累加,则称发生了进位。当最高有效位(MSB)也发生进位,意味着结果超出了当前数据类型的表示范围,对于无符号整数来说,这个超出的值跑到假想的更高位处
,实际上在硬件层面无法直接存储,但在计算过程中 CF
会被设置为1
,以表明发生了进位
。
减法借位
在二进制减法中,被减数小于减数时,需要从高位借位来完成减法运算。
例如: 在8位寄存器中执行减法操作,如果最低位需要从更高位借位,那么实际上是借自一个假想的更高位
(也就是第9位)。在实际硬件执行中,当发生借位时,会立即影响到CF
标志位的状态:若发生借位
,则CF置1
;否则,CF清零
。
- 总结
- 加法中的进位:当低位的结果超过了2(即产生了进位),并且这个进位传递到了更高位,则CF置1。
- 减法中的借位:当前的被减数小于减数时,需要从上一位借位才能完成减法,此时CF也会置1。
这种进位或借位不仅限于实际存在的寄存器位,而是根据运算逻辑可能扩展到更高的位
。在真实的硬件实现中,CPU通过状态标志寄存器记录这些信息,而不是真的在内存中增加额外的位去存储进位或借位的结果。
最高有效位 就是 最高位 只是强调了它有效性及在数值表示中的重要地位。
11.5 OF(Overflow Flag,溢出标志位)
在进行有符号数
运算的时候,如结果超过了机器所能表示的范围称为溢出
。
OF
主要用于反映有符号数
运算中的溢出
情况。当两个同样大小类型的有符号数相加或相减后,其结果无法用同样的数据类型正确表示(即结果超出了该数据类型的最小值和最大值之间的范围),就会触发OF
标志。具体而言,当两个正数相加得到一个负数,或者两个负数相加得到一个正数时,就发生了有符号数
的溢出
。
正数溢出示例:
+7FH (0111 1111) 最大正数
+ +01H (0000 0001)
-------------------+80H (1000 0000) 这个结果在8位有符号整数范围内是 -128,但实际上发生了正数溢出
此时,SF(符号标志)= 1,说明结果是一个负数。
负数溢出示例:
-127 (1000 0001)+ -1 (1111 1111)
-----------------------128 (1000 0000) 正确结果-128 (1000 0000)+ -1 (1111 1111)
----------------------+127(0111 1111 溢出导致的错误结果) 在8位有符号整数中,这个结果是 +127,发生了负数溢出
此时,SF(符号标志)= 0,但因为发生了溢出,逻辑上它应该是负数(-129)而不是一个正数。
总结一下:
- 对于
无符号
数运算,如果结果超过了当前数据类型的最大值,则会发生进位,CF
标志位将被设置。 - 对于
有符号
数运算,如果结果超出了当前数据类型能够表示的最大正数或最小负数的范围,则会发生溢出,OF
标志位将被设置。(这里的溢出
就是符号位
被翻转)
检测点 11.2
《汇编语言》- 读书笔记 - 各章检测点归档 - 检测点 11.2
11.6 adc 指令(Add with Carry)
adc | 指令是带进位 的加法 操作。 |
---|---|
格式 | adc 操作对象1 , 操作对象2 |
功能 | 操作对象1 = 操作对象1 +操作对象2 + CF |
比如 | adc ax,bx 实现的功能是:(ax) = (ax) + (bx) + CF |
- 应用场景
在连续的加法运算中需要考虑上一步的进位情况。通过adc
指令,我们可以确保在多步加法
过程中正确处理进位
问题,这对于实现多字节
加法等复杂计算非常有用。
此时可以:- 先
低位
相加。(如果有进位,CF
会被置1
) - 再
高位
相加,此时再加上CF
就实现了进位。如果有更高位,可以继续。 - 在大数连续加法上可以不受限制。(如书中的例子:
两个 128 位数据进行相加
)
- 先
名称 | add128 |
---|---|
功能 | 两个 128 位数据进行相加。 |
参数 | ds:si 指向存储第一个数的内存空间。因数据为 128 位,所以需要8个字单元,由低地址单元到高地址单元依次存放 128 位数据由低到高的各个字。运算结果 存储在第一个 数的存储空间中。ds:di 指向存储第二个数的内存空间。 |
assume cs:code, ds:data
data segment; 8个WORD,共 128 位first dw 1111h,1111h,1111h,1111h,1111h,1111h,1111h,1111h; 8个WORD,共 128 位second dw 2222h,2222h,2222h,2222h,2222h,2222h,2222h,2222h
data endscode segment
start:mov ax,data ; 设置数据段mov ds,axmov ax,offset first ; 第一个数的偏移量mov si,axmov ax,offset second ; 第二个数的偏移量mov di,axcall add128 ; 调用 128位数加法。 first + second。 cs:0Fmov ax, 4c00H ; 退出程序 cs:12int 21H ; cs:15
; ------------------- 子程序 add128 ----------------
; 实现两个 128 位数据进行相加
; --------------------------------------------------
; 参数: ds:si 指向第一个数
; 参数: ds:di 指向第二个数
; 返回: ds:si 保存结果
; --------------------------------------------------
add128: push ax ; 备份寄存器push cxpush sipush disub ax,ax ; 设置 AX=0, CF=0mov cx,8 ; 8个word 需要循环 8 次
add128_s:mov ax,[si]adc ax,[di]mov [si],axinc siinc siinc diinc diloop add128_spop di ; 还原寄存器pop sipop cxpop axret
; ------------------- 子程序 add128 ----------------
code ends
end start
11.7 sbb 指令(SuBtraction with Borrow)
sbb | 是带借位减法 指令,它利用了 CF 位上记录的借位值。 |
---|---|
格式 | sbb 操作对象1 , 操作对象2 |
功能 | 操作对象1 = 操作对象1 - 操作对象2 - CF |
比如 | sbb ax,bx 实现的功能是:(ax) = (ax) - (bx) - CF |
sbb
与 abc
是基于同样的思想设计的两条指令,一个加法一个减法。
不多废话。直接把上面add128
改改,来个 sub128
上代码:
assume cs:code, ds:data
data segment; 8个WORD,共 128 位first dw 2222h,2222h,2222h,2222h,2222h,2222h,2222h,2222h; 8个WORD,共 128 位second dw 1111h,1111h,1111h,1111h,1111h,1111h,1111h,1111h
data endscode segment
start:mov ax,datamov ds,axmov ax,offset firstmov si,axmov ax,offset secondmov di,axcall sub128 ; 128位数减法 cs:0Fmov ax, 4c00H ; 退出程序 cs:12int 21H ; cs:15
; ------------------- 子程序 sub128 ----------------
; 实现两个 128 位数据进行相减
; --------------------------------------------------
; 参数: ds:si 指向第一个数
; 参数: ds:di 指向第二个数
; 返回: ds:si 保存结果
; --------------------------------------------------
sub128: push axpush cxpush sipush disub ax,ax ; 设置 AX=0, CF=0mov cx,8 ; 8个word 需要循环 8 次
sub128_s:mov ax,[si]sbb ax,[di]mov [si],axinc siinc siinc diinc diloop sub128_spop dipop sipop cxpop axret
; ------------------- 子程序 sub128 ----------------
code ends
end start
11.8 cmp 指令(Compare)
cmp | 是比较 指令,功能相当于减法 但不保存结果,只更新标志寄存器 。其它指令通过识别 标志寄存器 来使用比较结果。 |
---|---|
格式 | cmp 操作对象1 , 操作对象2 |
功能 | 计算 操作对象1 - 操作对象2 但不保存结果,只更新标志寄存器 。 |
比如 | cmp ax,ax ,计算 (ax)-(ax) 结果为 0 不保存(ax 内容不变)。仅影响 flag 的相关各位。指令执行后:zf=1 ,pf=1 ,sf=0 ,cf=0 ,of=0 。 |
- 比较指令的设计思路,即:通过做
减法
运算,影响标志寄存器
来记录比较结果
。 其它指令
就可以通过标志寄存器
反过来判断出比较结果
,并加以利用。cmp
指令同add
、sub
指令一样进行比较时对有符号
、无符号
操作是无差别的。下面我们分有符号
、无符号
两种情况来看:
无符号数比较看:ZF(是否为0),CF(是否进借位)
无符号数比较
无符号数
比较看:ZF
(是否为0),CF
(是否进借位)
比较 | 对应减法 | ZF | CF | |
---|---|---|---|---|
ax == bx | ax - bx = 0 结果为零 | 1 | ||
ax != bx | ax - bx ≠ 0 结果不为零 | 0 | ||
ax < bx | ax - bx 借位 | 1 | ||
ax >= bx | ax - bx 没借位(结果可能为零 or不为零 ) | 0 | ||
ax > bx | ax - bx 没借位,并且结果不为零 | 0 | and | 0 |
ax <= bx | ax - bx 可能借位,,结果也可能为零 为零 满足 = ,借位满足< ,得其一即满足 <= | 1 | or | 1 |
有符号数比较
有符号数
比较看:ZF
(是否为0),SF
(是否为负),OF
(是否溢出)
比较 | 对应减法 | ZF | SF | OF |
---|---|---|---|---|
ax == bx | ax - bx = 0 结果为零 | 1 | ||
ax != bx | ax - bx ≠ 0 结果不为零 | 0 | ||
ax < bx | ax - bx 结果为负 ,没溢出 ax - bx 结果 为正 ,溢出 | 1 0 | 0 1 | |
ax >= bx | ax - bx 结果为正 ,没溢出 | 0 | 0 | |
ax > bx | ax - bx 溢出,导致结果为负 | 1 | 1 | |
ax <= bx | 小于和等于的条件组合 | 1or 1 or | 1 0 | 0 1 |
对于有符号数的结果判断,主要依据是SF
(是否为负)。
我们在做比较
时要参考的是算数逻辑
上结果的正负
。但在CPU工作层面 溢出
会导致符号翻转
,所以我们判断 SF
的同时还要考虑 OF
的情况。
如果减法
得到结果为正数
,同时又发生了溢出
,那原本算数逻辑上的符号就应该是负
。
分析见上文 11.5 OF(Overflow Flag,溢出标志位)
11.9 检测比较结果的条件转移指令
本节学习一些根据 cmp
指令的比较结果
进行工作的指令。(比较结果指相关标志位的值)
这些条件转移
指令通常都和cmp
相配合使用,就好像 call
和 ret
指令通常相配合使用一样。
(但并不是意味着这些转移指令
必须跟在 cmp
后面,它们本质上只是根据 标志位
转移。)
与前面 cmp
小节一样,这里也要分有符号
、无符号
两种情况:
根据无符号数比较结果进行转移
指令 | 英文名 | 含义 | 检测标志位 |
---|---|---|---|
je | Jump if Equal | == 则跳转 | ZF=1 |
jz | Jump if Zero | == 则跳转 | ZF=1 |
jne | Jump if Not Equal | != 则跳转 | ZF=0 |
jnz | Jump if Not Zero | != 则跳转 | ZF=0 |
jb | Jump if Below | < 则跳转 | CF=1 |
jc | Jump if Carry | < 则跳转 | CF=1 |
jnae | Jump if Not Above or Equal | < 则跳转 | CF=1 |
jnb | Jump if Not Below | >= 则跳转 | CF=0 |
jae | Jump if Above or Equal | >= 则跳转 | CF=0 |
jnc | Jump if Not Carry | >= 则跳转 | CF=0 |
ja | Jump if Above | > 则跳转 | CF=0 且 ZF=0 |
jna | Jump if Not Above | <= 则跳转 | CF=1 或 ZF=1 |
jbe | Jump if Below or Equal | <= 则跳转 | CF=1 或 ZF=1 |
cmp
与这些 条件转移
指令的配合体现了类似高级语言中 IF
的思想。
根据有符号数比较结果进行转移
工作原理与有符号数
相同,只是检测的标志位
不同。
指令 | 英文名 | 含义 | 检测的标志位 |
---|---|---|---|
je / jz | Jump if Equal / Jump if Zero | == 则跳转 | ZF=1 |
jne / jnz | Jump if Not Equal / Jump if Not Zero | != 则跳转 | ZF=0 |
jg / jnle | Jump if Greater / Jump if Not Less or Equal | > 则跳转 | SF≠OF 且 ZF=0 |
jge / jnl | Jump if Greater or Equal / Jump if Not Less | >= 则跳转 | SF=OF |
jl / jnge | Jump if Less / Jump if Not Greater or Equal | < 则跳转 | SF≠OF |
jle / jng | Jump if Less or Equal / Jump if Not Greater | <= 则跳转 | SF=OF 或 ZF=1 |
1. 编程
- 编程,统计
data
段中数值==8
的字节的个数,用ax
保存统计结果。
编程思路:初始设置(ax)=0
,循环比较每个字节的值,如果==8
就将inc ax
。程序如下。
assume cs:code, ds:data
data segmentdb 8,11,8,1,8,5,63,38
data endscode segment
start:mov ax,datamov ds,axmov bx,0 ; ds:bx 指向第一个字节mov ax,0 ; 初始化累加器mov cx,8 s: cmp byte ptr [bx],8 ; 和8进行比较; --------------------------------------jne next ; 如果不相等转到 next,继续循环inc ax ; 如果相等就将计数值加 1; --------------------------------------next: inc bxloop s ; 程序执行后:(ax)=3mov ax, 4c00H ; 退出程序 CS:17int 21H
code ends
end start
assume cs:code, ds:data
data segmentdb 8,11,8,1,8,5,63,38
data endscode segment
start:mov ax,datamov ds,axmov bx,0 ; ds:bx 指向第一个字节mov ax,0 ; 初始化累加器mov cx,8 s: cmp byte ptr [bx],8 ; 和8进行比较; --------------------------------------je ok ; 如果相等转到 okjmp short next ; 如果不相等转到 next,继续循环ok: inc ax ; 如果相等就将计数值加 1; --------------------------------------next: inc bxloop s ; 程序执行后:(ax)=3mov ax, 4c00H ; 退出程序 CS:19int 21H
code ends
end start
第一个程序用 jne
检测 !=8
跳过 inc ax
进入下一次循环。
第二个程序用 je
检测 ==8
跳到 inc ax
,否则 jmp short next
直接跳过 inc ax
。
两个方案都能实现相同的效果。
2. 编程
- 编程,统计
data
段中数值大于8
的字节的个数,用ax
保存统计结果。
编程思路:初始设置(ax)=0
,循环比较每个字节的值,如果>8
就将inc ax
。程序如下。
assume cs:code, ds:data
data segmentdb 8,11,8,1,8,5,63,38
data endscode segment
start:mov ax,datamov ds,axmov bx,0 ; ds:bx 指向第一个字节mov ax,0 ; 初始化累加器mov cx,8 s: cmp byte ptr [bx],8 ; 和8进行比较; --------------------------------------jna next ; 如果不大于8转到 next,继续循环inc ax ; 如果大于8就将计数值加 1; --------------------------------------next: inc bxloop s ; 程序执行后:(ax)=3mov ax, 4c00H ; 退出程序 cs:17int 21H
code ends
end start
3. 编程
- 编程,统计
data
段中数值小于8
的字节的个数,用ax
保存统计结果。
编程思路:初始设置(ax)=0
,循环比较每个字节的值,如果<8
就将inc ax
。程序如下。
assume cs:code, ds:data
data segmentdb 8,11,8,1,8,5,63,38
data endscode segment
start:mov ax,datamov ds,axmov bx,0 ; ds:bx 指向第一个字节mov ax,0 ; 初始化累加器mov cx,8 s: cmp byte ptr [bx],8 ; 和8进行比较; --------------------------------------jnb next ; 如果不小于8转到 next,继续循环inc ax ; 如果小于8就将计数值加 1; --------------------------------------next: inc bxloop s ; 程序执行后:(ax)=2mov ax, 4c00H ; 退出程序 cs:17int 21H
code ends
end start
检测点 11.3
《汇编语言》- 读书笔记 - 各章检测点归档 - 检测点 11.3
11.10 DF 标志和串传送指令(Direction Flag)
DF
在串处理指令中,控制每次操作后 si
、di
的增减。
串操作指令是指对内存中连续
存储的一系列数据进行相同
操作的一类指令
。
- | 含义 |
---|---|
DF=0 | 表示串操作 过程中地址自动递增 (向上)例如: 在 REP MOVSB 指令中,源指针SI 和目标指针DI 每次操作后会递增1 个字节。 |
DF=1 | 表示串操作 过程中地址自动递减 (向下)例如: 在 REP MOVSB 指令中,源指针SI 和目标指针DI 每次操作后会递减1 个字节。 |
movsb、movsw、rep
- movsb(Move String Byte by Byte)
movsb | 从源地址 向目标地址 逐个字节 地复制数据。 |
---|---|
格式 | movsb |
功能 | 将 ds:si 指向的内存单元中的字节送入 es:di 中,然后根据 df 位的值,将 si 和 di 递增或递减。 |
- movsw(Move String Word by Word)
movsw | 与 movsb 类似,只是逐个字 复制数据。 |
---|---|
格式 | movsw |
- rep (Repeat)
rep
是一个前缀指令,它与一些串操作
指令结合使用,以实现重复执行
这些指令的功能。
rep
指令根据 cx
来决定要重复执行多少次。
movsb
和 movsw
一般都和 rep
配合使用 rep movsb
实现的功能就类似:
s: movsbloop s
cld、std
- cld(Clear Direction Flag)
cld
指令:将标志寄存器的df
位置0
。 - std(Set Direction Flag)
std
指令:将标志寄存器的df
位置1
。
1. 编程
编程,用串传送指令,将 data
段中的第一个
字符串复制到它后面
的空间中。
assume cs:code
data segmentdb 'welcome to masm!'db 16 dup(0)
data ends
code segment
start:mov ax,datamov ds,axmov si,0 ; ds:si 指向 data:0mov es,axmov di,16 ; es:di 指向 data:0010mov cx,16 ; (cx)=16,rep 循环 16 次cld ; 设置 df=0,正向传送(si,di 递增)rep movsbmov ax, 4c00Hint 21H
code ends
end start
2. 编程
编程,用串传送指令,将 F000H
段中的最后 16
个字符复制到 data
段中。
assume cs:code
data segmentdb 16 dup(0)
data ends
code segment
start:mov ax,0f000hmov ds,axmov si,0ffffh ; ds:si 指向 f000:ffffmov ax,datamov es,axmov di,15 ; es:di 指向 data:000Fmov cx,16 ; (cx)=16,rep 循环 16 次std ; 设置 df=1,逆向传送(si,di 递减)rep movsbmov ax, 4c00Hint 21H
code ends
end start
11.11 pushf 和 popf
pushf
和 popf
,为直接访问标志寄存器提供了一种方法。
-
pushf(Push Flags)
pushf
是将标志寄存器
的值压栈
。 -
popf(Pop Flags)
popf
是从栈
中弹出
数据,送入标志寄存器
。
检测点 11.4
《汇编语言》- 读书笔记 - 各章检测点归档 - 检测点 11.4
11.12 标志寄存器在 Debug 中的表示
标志位 | 简写 | SET (a 1 -bit) | CLEARed (a 0 -bit) |
---|---|---|---|
Overflow | OF | OV (Overflow) | NV [No Overflow] |
Direction | DF | DN (decrement) | UP (increment) |
Interrupt | IF | EI (enabled) | DI (disabled) |
Sign | SF | NG (negative) | PL (positive) |
Zero | ZF | ZR [zero] | NZ [Not zero] |
Auxiliary Carry | AF | AC | NA [No AC] |
Parity | PF | PE (even) | PO (odd) |
Carry | CF | CY [Carry] | NC [No Carry] |
实验 11 编写子程序
《汇编语言》- 读书笔记 - 实验11 编写子程序
参考资料
A Guide to DEBUG - The “FLAGS” REGISTER
相关文章:

《汇编语言》- 读书笔记 - 第11章-标志寄存器
《汇编语言》- 读书笔记 - 第11章-标志寄存器 标志寄存器指令与标志位关系11.1 ZF(Zero Flag,零标志位)11.2 PF(Parity Flag,奇偶标志位)11.3 SF(Sign Flag,符号标志位)处…...

1.QT简介(介绍、安装,项目创建等)
1. QT介绍 Qt(官方发音 [kju:t])是一个跨平台的C开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序 Qt 是纯 C 开发的,正常情况下需要先学习C语言、然后在学习C然后才能使用…...

【服务器】服务器推荐
一、引言 在数字世界的浪潮中,服务器作为数据存储和处理的基石,其重要性不言而喻。而在这个繁星点点的市场中,雨云以其独特的优势和超高的性价比,逐渐成为众多企业和个人的首选。今天,就让我带你走进雨云的世界&#…...

信号系统之线性图像处理
1 卷积 图像卷积的工作原理与一维卷积相同。例如,图像可以被视为脉冲的总和,即缩放和移位的delta函数。同样,线性系统的特征在于它们如何响应脉冲。也就是说,通过它们的脉冲响应。系统的输出图像等于输入图像与系统脉冲响应的卷积…...

uniapp腾讯地图JavaScript Api,H5端和原生APP端可用
因项目需要,在uniapp中集成使用腾讯地图,为了方便维护,希望通过一套代码实现H5和APP同时可用。H5显示相对简单,APP端比较麻烦,记录下实现过程 一、集成步骤 1.使用 renderjs script标签使用renderjs,因为…...

MyBatisPlus:PG数组类型自动映射问题
引言: PostGreSQL数据库提供了丰富的数据类型,通过查看官网文档,我们也可以发现,PG也提供了对数组类型的支持。 但是在实际开发中,我们通常是使用MyBatis/MyBatisPlus这种半自动ORM映射框架来实现数据库/表数据基本的增删改查,以及其它操作。那么,问题来了,如何…...

Data-Shape制作UI节点简介
很多小伙伴对于Data-Shape制作简单的UI都是似懂非懂,群里很多小伙伴也总是询问相关的问题,那么,今天我就简单举几个例子,专门介绍下Data-Shape创建简单UI的教程。 首先,本次教程,使用的是Data-Shape 2021.…...

kubernetes负载均衡部署
目录 1.新master节点的搭建 对master02进行初始化配置(192.168.88.31) 将master01的配置移植到master02 修改master02配置文件 2.负载均衡的部署 两台负载均衡器配置nginx 部署keepalived服务 所有node节点操作 总结 实验准备: k8s…...

NestJS入门6:日志中间件
前文参考: NestJS入门1 NestJS入门2:创建模块 NestJS入门3:不同请求方式前后端写法 NestJS入门4:MySQL typeorm 增删改查 NestJS入门5:加入Swagger 1. 安装 nest g middleware logger middleware 2. lo…...

CommonJS、require、moudle实现两个文件传参
目的:实现两个文件传参 文件A给B传入一个参数,并且文件B代码执行后再传回A。 场景 拆分express项目中的app.js文件中的路由、项目越大会使app.js文件变大,复杂 如何使用 app.js文件 导入路由文件调用路由文件,调用的时候传入…...

关于php、php-fpm的解释
PHP语言是由PHP程序解释的,而不是由php-fpm程序解释的。 PHP(Hypertext Preprocessor)是一种通用开源脚本语言,最初是为创建动态Web页面而设计的,但现在也可以用于命令行脚本编写等用途。PHP程序通常由Web服务器&…...

【CMake】(8)包含库文件
示例项目结构 假设你的项目结构如下所示: 项目根目录/ ├── CMakeLists.txt ├── include/ │ └── head.h ├── lib/ │ └── libcalc.a └── src/└── main.cpp链接库 link_directories和target_link_libraries指令用于配置和链接库文件。 link_direc…...

【 JS 进阶 】Web APIs (二)
“人生如舞台,每一个瞬间都是一场精彩的表演。在舞台的灯光下,以坚韧为舞伴,跳出自己的独特舞步,创造属于自己的绚丽人生芳华。” - 露易丝梭罗 学习会为 DOM 注册事件,实现简单可交互的网页特交。 事件是编程语言中的…...

解决弹性布局父元素设置高自动换行,子元素均分高度问题(align-content: flex-start)
案例: <view class"abc"><view class"abc-item" v-for"(item,index) in 8" :key"index">看我</view> </view> <style lang"less">.abc{height: 100px;display: flex;flex-wrap: …...

什么是负载均衡集群?
目录 1、集群是什么? 2、负载均衡集群技术 3、负载均衡集群技术的实现 4、实现效果如图 5、负载均衡分类 6、四层负载均衡(基于IP端口的负载均衡) 7、七层的负载均衡(基于虚拟的URL或主机IP的负载均衡) 8、四层负载与七层…...

【es6】的新特性
声明语法 letconstclass字符串/函数/对象/数组的新语法/扩展功能模版字符串 反引号标签函数Proxy /ReflectPromiseclsss & static 静态方法 & extends 继承SetMapSymbolfor of 可迭代对象迭代器模式 通过 Symbol.interator 对外提供统一个接口外部可以通过 for...of 去…...

Java中的多线程是如何实现的?
在Java中,多线程的实现主要依赖于java.lang.Thread类和java.util.concurrent包中的类。以下是Java实现多线程的基本方法和概念: 1. **继承Thread类:** - 创建一个新的类继承自Thread类。 - 重写Thread类的run()方法,定义线…...

C++知识点总结(22):模拟算法
一、概念 模拟算法 根据题目描述进行筛选提取关键要素,按需求书写代码解决实际问题的算法。 二、步骤 1、提取题目的关键要素 2、根据关键要素的需求完成代码 三、关键要素 1、题目目的 2、样例的执行逻辑(样例分析) 3、数据范围(…...

opengl 学习纹理
一.纹理是什么? 纹理是一个2D图片(甚至也有1D和3D的纹理),它可以用来添加物体的细节;类似于图像一样,纹理也可以被用来储存大量的数据,这些数据可以发送到着色器上。 采样是指用纹理坐标来获取纹…...

STM32控制max30102读取血氧心率数据(keil5工程)
一、前言 MAX30102是一款由Maxim Integrated推出的低功耗、高精度的心率和血氧饱和度检测传感器模块,适用于可穿戴设备如智能手环、智能手表等健康管理类电子产品。 该传感器主要特性如下: (1)光学测量:MAX30102内置…...
高级语言期末2011级A卷
1.编写函数,判定正整数m和n(均至少为2)是否满足:数m为数n可分解的最小质因数(数n可分解的最小质因数为整除n的最小质数) 提示:判定m为质数且m是n的最小因数 #include <stdio.h> #include…...

SpringAMQP消息队列
引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>配置文件 spring:rabbitmq:host: 172.27.99.52 # rabbitMQ的ip地址port: 5672 # 端口username: abcpa…...

二次元风格个人主页HTML源码
源码介绍 直接上传服务器压缩包解压就完事了,修改index.html内代码即可,注释写的很全,替换图片在文件夹img,只有前端,没有后台,大佬如果需要,可以自行添加后台。本源码非常适合个人工作室主页。…...

每日学习录
目录 [蓝桥杯 2022 省 A] 求和 题目描述 [蓝桥杯 2019 省 B] 特别数的和 题目描述 [蓝桥杯 2023 省 A] 填空问题 题目描述 [蓝桥杯 2020 省 AB1] 走方格 题目描述 [蓝桥杯 2017 省 AB] 分巧克力 [蓝桥杯 2016 省 B] 交换瓶子 题目描述 [蓝桥杯 2022 省 A] 求和 题目描…...

linux docker部署深度学习环境(docker还是conda)
在深度学习中,避免不了在远程服务器上进行模型的训练,如果直接在服务器裸机的基础环境跑显然是不可取的,此时搭建用于模型训练的docker环境显得尤为重要。 在深度学习中,避免不了在远程服务器上进行模型的训练,如果直…...

iOS面试:4.多线程GCD
一、多线程基础知识 1.1 什么是进程? 进程是指在系统中正在运行的一个应用程序。对于电脑而已,你打开一个软件,就相当于开启了一个进程。对于手机而已,你打开了一个APP,就相当于开启了一个进程。 1.2 什么是线程&am…...

云计算计算资源池与存储池访问逻辑
在云计算环境中,计算资源池和存储池通常是分开管理和访问的。计算资源池包含了用于运行虚拟机的 CPU、内存等计算资源,而存储池则提供了用于存储虚拟机镜像、数据等的存储资源。 计算资源池和存储池之间通常通过网络进行访问,它们之间不存在直…...

【Linux】部署单机项目(自动化启动)---(图文并茂详细讲解)
目录 一 准备工作 1.1 连接服务器拷贝文件 1.2 解压 二 JDK安装 2.1 配置坏境变量 2.2 查看版本 三 Tomcat(自启动) 3.1 复制启动命令的位置 3.2 添加命令相关配置文件 3.2.1 配置jdk及tomcat目录 3.2.2 添加优先级 3.3 设置自启动命令 3.4 开放端口 四 My…...

修复Microsoft Edge WebView2无法安装的问题
修复Microsoft Edge WebView2无法安装的问题 场景解决方案 场景 系统:win11 电脑:联想14 前提:使用Geek Uninstaller强制删除了Microsoft Edge WebView2 同时下载了clash verge。 发现根本无法运行(点击了无任何反应且图标颜色…...

Linux命令-chgrp命令(用来变更文件或目录的所属群组)
说明 chgrp命令 用来改变文件或目录所属的用户组。该命令用来改变指定文件所属的用户组。其中,组名 可以是用户组的id,也可以是用户组的组名。文件名可以 是由空格分开的要改变属组的文件列表,也 可以是由通配符描述的文件集合。如果用户不是…...