如何检查emu8086中CF标志是否为1? [英] How to check if the CF flag is 1 in emu8086?

查看:496
本文介绍了如何检查emu8086中CF标志是否为1?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图查找CARRY标志是否为1,但是我不知道如何检查它.我写了下面的代码,但是我需要一些帮助来问问问号.

I am trying to find if the CARRY flag is 1 or not, but I don't know how to check it. I wrote the below code, but I need some help for question marks I put in.

  LEA DX, MSG
  MOV AH, 09H
  INT 21H

  MOV AH, 01H
  INT 21H
  MOV NUM, AL

  SHR NUM, 1
  CMP ??, 1
  JE FINISH

FINISH: MOV AH, 4CH
  INT 21H

  NUM DB 0

  RET

推荐答案

您不能直接使用CMP指令,因为这些标志对于x86指令而言不是有效的操作数.它们仅由某些指令隐式使用.

You cannot use the CMP instruction directly, since the flags are not valid operands for x86 instructions. They are only used implicitly by certain instructions.

最简单的解决方案是使用条件分支.这类似于您已经熟悉的JE指令,除了它根据进位标志(CF)的值而不是像JE那样的零标志(ZF)分支.

The simplest solution is just to use a conditional branch. This works analogously to the JE instruction you are already familiar with, except that it branches based on the value of the carry flag (CF), instead of the zero flag (ZF) like JE does.

要有条件地转移进位标志(CF)的状态,请使用JCJNC.如果设置了进位标志(CF == 1),则JC将分支,而如果未设置进位标志(CF == 0),则JNC将分支.如果 C arry,这些操作码的助记符就是" J ump",如果 N ot < J ump C arry".

To conditionally branch on the status of the carry flag (CF), you would use JC or JNC. JC will branch if the carry flag is set (CF == 1), whereas JNC will branch if the carry flag is not set (CF == 0). The mnemonics for these opcodes are simply "Jump if Carry" and "Jump if Not Carry".

jc  CarryFlagIsSet     ; jump if CF == 1
; else fall through: code for CF == 0 goes here

或者用另一种方式做:

jnc CarryFlagIsNotSet  ; jump if CF == 0
; else fall through: code for CF == 1 goes here


因此,按照您的示例,类似:


So, in keeping with your example, something like:

shr  num, 1        ; put least significant bit in CF
jc   num_was_odd   ; (or jnc LSBNotSet  aka num_was_even)

但是 Peter Cordes指出注释,您拥有的代码几乎肯定是错误的,因为无论是否采用分支,都将执行相同的代码.换句话说,分支目标等效于穿透代码.您可能想拥有更多类似的东西:

But as Peter Cordes points out in a comment, the code you have is almost certainly wrong, since the identical code will be executed whether or not the branch is taken. In other words, the branch destination is equivalent to the fall-through code. You probably want to have something more like:

TOPOFLOOP:
  LEA DX, MSG
  MOV AH, 09H
  INT 21H

  MOV AH, 01H
  INT 21H
  MOV NUM, AL

  SHR NUM, 1
  JC  TOPOFLOOP     ; keep looping as long as CF == 1
                    ; otherwise, if CF == 0, fall through to FINISH
                    ; (use JNC to reverse the logic)

FINISH:
  MOV AH, 4CH
  INT 21H  
  RET

(除了对一个注册值进行操作要比在内存中存储一​​个值快得多),因此,如果可能的话,应将NUM放在一个寄存器中.此外,汇编语言操作码和寄存器不区分大小写,因此您可以轻松地以小写形式编写代码.我认为这既易于键入,也易于阅读,但它纯粹是样式,因此由您自己决定.)

(Except that it is much faster to operate on an enregistered value than one stored in memory, so if possible, you should place NUM in a register. Also, assembly language opcodes and registers are case-insensitive, so you can just as easily write the code in lowercase. I think this is both easier to type and easier to read, but it's purely stylistic and therefore up to you.)

当您要编写无分支代码(这几乎总是可以提高性能,如果您能找到一种足够聪明的编写代码的方法)时,可以使用

When you want to write branchless code (which almost always improves performance, if you can figure out a clever enough way to write the code), you can use the SBB instruction. If both operands are the same register, this will set that register to -1 if the carry flag is set (CF == 1), or set that register to 0 if the carry flag is not set (CF == 0). This works because SBB actually performs the operation DEST = (DEST - (SRC + CF)). When DEST and SRC are the same value, this is equivalent to DEST = -CF.

如果确切地拥有寄存器的值镜像CF更方便,则可以将其与

In cases where it would be more convenient to have the register's value mirror CF exactly, this can be combined with the NEG instruction:

; Perform operation that will set CF.
...

; Set AX to the same value as CF.
sbb  ax, ax    ; CF ==  1 then AX = -1; otherwise, AX = 0
neg  ax        ; AX == -1 then AX =  1; otherwise, AX = 0

在某些情况下,您甚至可以在 ADC指令中使用类似的方式.这将执行操作DEST = DEST + SRC + CF.当DESTSRC都为零时,这等效于DEST = CF.棘手的是,目标寄存器必须在进位标志置位之前预先清零,或者以不影响进位标志的方式清零:

In certain cases, you can even use the ADC instruction in an analogous manner. This performs the operation DEST = DEST + SRC + CF. When DEST and SRC are both zero, this is equivalent to DEST = CF. The tricky part about this is that the destination register has to be either pre-zeroed before the carry flag gets set, or zeroed in such a way that the carry flag is not affected:

; Pre-zero AX in preparation for later use of ADC.
xor  ax, ax

; Perform operation that will set CF.
; (NOTE: Cannot modify AX register here, nor AL nor AH!)
...

; Set AX to the same value as CF.
adc  ax, ax

; Perform operation that will set CF.
...

; Zero AX in such a way that flags are not clobbered.
mov  ax, 0

; Set AX to the same value as CF.
adc  ax, ax

请注意,如果要将CF的值存储在内存中,则可以使用以下形式的ADC:

Note that if you wanted to store the value of CF in memory, you could use the following form of ADC:

adc  DWORD PTR [value], 0

在更现代的体系结构上,可以使用SETCCMOVC指令(或SETNC/CMOVNC用于逆逻辑-助记符与JC/JNC相同).通常,这些是编写无分支代码的更快的方法.但是在8086上都不可用.条件集(SETcc)指令是随Pentium一起引入了条件移动(CMOVcc)专业版.

On more modern architectures, you could use either the SETC or CMOVC instructions (or SETNC/CMOVNC for the converse logic—the mnemonics are the same as JC/JNC). These are generally even faster ways to write branchless code; however, neither are available on the 8086. Conditional set (SETcc) instructions were introduced with the 386, while conditional moves (CMOVcc) were introduced with the Pentium Pro.

这篇关于如何检查emu8086中CF标志是否为1?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆