如何检查emu8086中CF标志是否为1?

2024-01-28

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

  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 指令来说不是有效的操作数。它们仅由某些指令隐式使用。

最简单的解决方案就是使用条件分支 http://x86.renejeschke.de/html/file_module_x86_id_146.html。这类似于JE您已经熟悉的指令,除了它基于进位标志(CF)的值而不是零标志(ZF)的值进行分支JE does.

要根据进位标志 (CF) 的状态有条件地分支,您可以使用JC or JNC. JC如果设置了进位标志(CF == 1),则将分支,而JNC如果进位标志是则分支not设置(CF == 0)。这些操作码的助记符很简单“Jump if C阿里”和“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

因此,根据您的示例,类似:

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

But 正如彼得·科德斯在评论中指出的那样 https://stackoverflow.com/questions/41335653/how-to-check-cf-flag-is-1-in-emu8086/41345823#comment69885438_41335653,您的代码几乎肯定是错误的,因为无论是否采用分支,都会执行相同的代码。换句话说,分支目的地相当于失败代码。您可能想要更多类似的东西:

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

(除了它是much对注册值进行操作比对内存中存储的值进行操作更快,因此如果可能的话,您应该将NUM在寄存器中。此外,汇编语言操作码和寄存器不区分大小写,因此您可以轻松地用小写字母编写代码。我认为这更容易输入和阅读,但这纯粹是风格上的,因此取决于你。)


当您想要编写无分支代码时(如果您能找到一种足够聪明的方法来编写代码,这几乎总是可以提高性能),您可以使用SBB操作说明 http://x86.renejeschke.de/html/file_module_x86_id_286.html。如果两个操作数是同一寄存器,则如果设置了进位标志 (CF == 1),则将该寄存器设置为 -1;如果未设置进位标志 (CF == 0),则将该寄存器设置为 0。这有效是因为SBB实际执行操作DEST = (DEST - (SRC + CF)). When DEST and SRC是相同的值,这相当于DEST = -CF.

如果精确地获得寄存器的值镜像 CF 会更方便,则可以将其与NEG操作说明 http://x86.renejeschke.de/html/file_module_x86_id_216.html:

; 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操作说明 http://x86.renejeschke.de/html/file_module_x86_id_4.html以类似的方式。这将执行操作DEST = DEST + SRC + CF. When DEST and SRC都为零,这相当于DEST = CF。棘手的部分是,目标寄存器必须在进位标志设置之前预先清零,或者以不影响进位标志的方式清零:

; 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:

adc  DWORD PTR [value], 0

在更现代的架构上,您可以使用SETC or CMOVC说明(或SETNC/CMOVNC对于逆逻辑——助记符与JC/JNC)。这些通常是编写无分支代码的更快方法;然而,这两者在 8086 上都不可用。条件集 (SETcc) 指示 http://x86.renejeschke.de/html/file_module_x86_id_288.html随 386 一起推出,同时条件移动 (CMOVcc) http://x86.renejeschke.de/html/file_module_x86_id_34.html是随 Pentium Pro 一起推出的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何检查emu8086中CF标志是否为1? 的相关文章

  • 为什么X86中没有NAND、NOR和XNOR指令?

    它们是您可以在计算机上执行的最简单的 指令 之一 它们是我亲自实施的第一个指令 执行 NOT AND x y 会使执行时间和依赖链长度和代码大小加倍 BMI1 引入了 andnot 这是一个有意义的补充 是一个独特的操作 为什么不是这个问题
  • 整数溢出问题

    我不断遇到整数溢出问题 我不知道如何解决它 有人可以帮忙吗 edx 包含 181 eax 包含 174 xor eax edx mov edx 2 div edx 假设你谈论的是x86 div edx这实际上没有意义 32位div将edx
  • 标志寄存器中保留/未定义位的用途是什么?

    在 Z80 8080 8085 和 8086 处理器的标志寄存器中 被记录为 保留 或 未定义 的位 1 3 5 的用途是什么 这些位未使用 也就是说 没有指令明确地将它们设置为任何值 设计人员认为 5 6 个标志就足够了 他们只是将标志寄
  • IDA pro asm 指令更改

    我只是想知道我怎样才能 更改IDA视图A中的asm指令 如何编辑指令 对于 实例 jnz 到 jmp 如何插入新指令 call func1 调用 func2 插入到现有的 代码 我知道如何制作 diff 文件 我知道如何在我的 DLL 上应
  • 当 mov 指令导致页面错误并且在 x86 上禁用中断时会发生什么?

    我最近在自定义 Linux 内核 2 6 31 5 x86 驱动程序中遇到一个问题 其中 copy to user 会定期不将任何字节复制到用户空间 它将返回传递给它的字节数 表明它没有复制任何内容 经过代码检查 我们发现代码在调用 cop
  • long double(GCC 特定)和 __float128

    我正在寻找有关的详细信息long double and float128在 GCC x86 中 更多是出于好奇而不是因为实际问题 可能很少有人需要这些 我只是有史以来第一次 truly需要一个double 但我想知道你的工具箱里有什么以及它
  • 无法在 64 位 Linux 上从汇编 (yasm) 代码调用 C 标准库函数

    我有一个函数foo以汇编语言编写 并在 Linux Ubuntu 64 位上使用 yasm 和 GCC 编译 它只是使用以下命令将消息打印到标准输出puts 如下所示 bits 64 extern puts global foo secti
  • 在 x86 程序集中打印寄存器值的简单方法

    我需要在 8086 Assembly 中编写一个程序 接收来自用户的数据 进行一些数学计算并在屏幕上打印答案 我已经编写了程序的所有部分并且一切正常 但我不知道如何打印号码显示到屏幕上 在我所有计算结束时 答案是 AX 它被视为无符号 16
  • ICC 中的 -O3 会扰乱内在函数,使用 -O1 或 -O2 或相应的手动汇编即可

    这是后续这个问题 http stackoverflow com questions 49791664 o2 in icc messes up assembler fine with o1 in icc and all optimizatio
  • 从c调用汇编函数

    我试图从 c 调用汇编函数 但我不断收到错误 text globl integrate type integrate function integrate push ebp mov esp ebp mov 0 edi start loop
  • 如何在 MacOS 上使用 nasm 进行编译

    我正在尝试在汇编器上编译并链接我的第一个程序 我尝试编译以下代码 include stud io inc global main section text main xor eax eax again PRINT Hello PUTCHAR
  • 如何计算汇编中的内存位移?

    我一直在研究 yasm 汇编语言 并生成了一个包含以下内容的列表文件 我需要帮助理解第一列中的内存位移是如何计算的 提前致谢 1 line 1 1 memory asm 2 section data 3 00000000 04000000
  • 为什么 mov %ax, %ds 汇编+反汇编为 mov %eax,%ds,与原来不一致?

    test S text global start start xor ax ax mov ax ds mov ax ss mov ax es mov ax fs mov ax gs 我通过这样做得到了反汇编代码文件 x86 64 elf g
  • x86 asm 图形设置的分辨率高于 640x480?

    我刚刚开始使用汇编语言 感觉像学习新东西 并且遇到了一些问题 到目前为止 我一直在浏览的所有教程都没有回答 或者太旧而无法知道 1 我尝试了一些搜索 也许我只是不知道正确的关键字 但我找不到用于更改屏幕分辨率等的图形模式的更新列表 我发现的
  • 如何反汇编、修改然后重新组装 Linux 可执行文件?

    无论如何 这可以做到吗 我使用过 objdump 但它不会产生我所知道的任何汇编器都可以接受的汇编输出 我希望能够更改可执行文件中的指令 然后对其进行测试 我认为没有任何可靠的方法可以做到这一点 机器代码格式非常复杂 比汇编文件还要复杂 实
  • movsbl指令的作用是什么? [复制]

    这个问题在这里已经有答案了 我在网上搜索过 但找不到明确的示例来理解该指令的作用 因此 如果有人可以举一个例子 这对我来说将会非常有帮助 用符号从字节扩展到长字移动 在Intel语法中 该指令的助记符是MOVSX 当变量类型为 C 时 C
  • 如何恢复 x86-64 寄存器保存约定

    fibonacci cmpq 1 rdi ja recursive movl 1 eax ret recursive push rbp push r10 movq rdi r10 leaq 2 rdi rdi call fibonacci
  • 测试 xmm/ymm 寄存器是否为零的更快方法?

    It s fortunate that PTEST does not affect the carry flag but only sets the rather awkward ZF also affects both CF and ZF
  • 如何使 gcc 为 -fpatchable-function-entry 发出多字节 NOP?

    gcc确实有能力使用多字节用于对齐循环和函数的 NOP 然而当我尝试 fpatchable function entry option https gcc gnu org onlinedocs gcc Instrumentation Opt
  • 为什么 GCC 在堆栈上压入额外的返回地址?

    我目前正在学习汇编的基础知识 在查看 GCC 6 1 1 生成的指令时遇到了一些奇怪的情况 这是来源 include

随机推荐