《汇编语言》- 读书笔记 - 第11章-标志寄存器
《汇编语言》- 读书笔记 - 第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 | 小于和等于的条件组合 | 1or1 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内置…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
