【问题标题】:Intel x86 Assembly - Reading and copying the carry flagIntel x86 Assembly - 读取和复制进位标志
【发布时间】:2015-11-18 18:39:45
【问题描述】:

我目前正在创建一个将十进制转换为二进制的程序。我目前正在使用 shift 方法来获取 0 和 1。

我查看了导致使用 LAHF 和 PUSHF 访问标志并设置它的其他线程;但是,我要做的就是获取进位标志的当前值并将其存储到寄存器中(即:当前位置的 1 或 0),稍后将被复制到数组中。由于我对 LAFH 或 PUSHF 不太熟悉,所以我想知道您是否可以使用 LAFH 或 PUSHF 完成我上面要求的相同任务。

例如,我想将当前的 CF 移动到 eax 中:mov edx,cf(我知道这不起作用,但我正在寻找类似的东西)。在我复制了 1 或 0 之后,我会将它移动到从 C++ 程序传递的数组中。

【问题讨论】:

  • 整数已经是二进制的。 “将整数转换为二进制”是指将二进制整数转换为 base-2 ASCII 表示形式吗?
  • 使用setc 指令。例如,setc dl
  • @RossRidge 抱歉,我的意思是将十进制值转换为二进制。 (以 10 为基数到以 2 为基数的表示)

标签: assembly x86 flags carryflag eflags


【解决方案1】:

几乎与这个问题相同: check if carry flag is set

您可以使用 JC、JNC 根据进位标志进行分支,然后将 mov 1 或 0 移动到您要使用的寄存器中。

或者使用 ADC 命令。

mov eax, 0
adc eax, 0

我将添加 PUSHF 然后弹出到寄存器中并用 XOR 屏蔽掉你想要的位也可以。 ADC 方法可能是最好的

【讨论】:

  • 谢谢!这在我的汇编程序中完美运行。
  • @guest 如上一段所述,您使用XOR 指令挑出进位位的掩码是什么?
【解决方案2】:

我发现在 EDX 中存储进位最明显的方法是:

setc  dl
movzx edx, dl

它比其他答案中提出的方法更短(6 个字节),但最短的(5 个字节)必须是:

pushfd
pop   edx
and   edx, 1

【讨论】:

  • 更短:xor edx,edx / 生成标志 / setc dl。 5 字节性能好(选择xor 之前或movzx 之后depends on microarchitecture。最短:sbb edx, edx 2 字节,也相当不错的性能。或者sbb edx, edx / neg edx 4 字节,如果你真的需要 0/1 而不是0/-1。sbb reg,reg 在某些情况下实际上被 gcc 使用。(例如,在 /bin/ls 的反汇编中看到。)我没有投票权,否则我会投票赞成。其他答案大多是疯狂的.
  • @AndrewNguyen:您应该将接受更改为这个答案。这样更好。
  • @PeterCordes 您的第一个示例通过XOR松开进位标志
  • 哦,对了。当然,您必须将 xor 放在生成标志的指令之前,我应该这么说。在编辑窗口内修复:)
【解决方案3】:

只做一个基于进位的条件赋值:

mov eax, 1
jc carry_set ; If carry is indeed set, skip the next line
mov eax, 0
carry_set:

一般来说,进位通常用于条件跳转,而不是作为值。看看是否可以用这种方式重新编写更大的代码。

编辑:现代英特尔 CPU 也有条件移动命令:

mov eax, 0
cmovc eax, 1 ; assign if carry is set

【讨论】:

  • 感谢您的回复!如果我只能选择两个答案!这两个似乎都可以正常工作,因为我刚刚测试了两者并以相同的结果结束。
  • setc al / movzx eax, al 会比其中任何一个都好很多setcc 存在于 386 年。
【解决方案4】:

您总是可以尝试用借位进行减法。比如……

SBB EAX, EAX

如果设置了进位标志,EAX 将为 0xFFFFFFFF。如果清楚,结果将是0x00000000。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多