读取 CF、PF、ZF、SF、OF [英] Reading CF, PF, ZF, SF, OF

查看:28
本文介绍了读取 CF、PF、ZF、SF、OF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为自己的汇编语言编写一个虚拟机,我希望能够在执行加法等操作时设置 x86-64 架构中设置的进位、奇偶校验、零、符号和溢出标志.

I am writing a virtual machine for my own assembly language, I want to be able to set the carry, parity, zero, sign and overflowflags as they are set in the x86-64 architecture, when I perform operations such as addition.

注意事项:

  • 我使用的是 Microsoft Visual C++ 2015 &英特尔 C++ 编译器 16.0
  • 我正在编译为 Win64 应用程序.
  • 我的虚拟机(目前)只对 8 位整数进行算术运算
  • 我(目前)对任何其他标志(例如 AF)不感兴趣

我目前的解决方案是使用以下功能:

My current solution is using the following function:

void update_flags(uint16_t input)
{
    Registers::flags.carry = (input > UINT8_MAX);
    Registers::flags.zero = (input == 0);
    Registers::flags.sign = (input < 0);
    Registers::flags.overflow = (int16_t(input) > INT8_MAX || int16_t(input) < INT8_MIN);

    // I am assuming that overflow is handled by trunctation
    uint8_t input8 = uint8_t(input);
    // The parity flag
    int ones = 0;
    for (int i = 0; i < 8; ++i)
        if (input8 & (1 << i) != 0) ++ones;

    Registers::flags.parity = (ones % 2 == 0);
}

对于添加,我将使用如下:

Which for addition, I would use as follows:

uint8_t a, b;
update_flags(uint16_t(a) + uint16_t(b));
uint8_t c = a + b;

为了澄清,我想知道是否有更有效/更简洁的方法(例如直接访问 RFLAGS)另外我的代码可能不适用于其他操作(例如乘法)

To clarify, I want to know if there is a more efficient/neat way of doing this (such as by accessing RFLAGS directly) Also my code may not work for other operations (e.g. multiplication)

EDIT 2 我现在已将代码更新为:

EDIT 2 I have updated my code now to this:

void update_flags(uint32_t result)
{
    Registers::flags.carry = (result > UINT8_MAX);
    Registers::flags.zero = (result == 0);
    Registers::flags.sign = (int32_t(result) < 0);
    Registers::flags.overflow = (int32_t(result) > INT8_MAX || int32_t(result) < INT8_MIN);
    Registers::flags.parity = (_mm_popcnt_u32(uint8_t(result)) % 2 == 0);
}

还有一个问题,我的进位标志代码能正常工作吗?我还希望它为减法过程中发生的借用"设置正确.

One more question, will my code for the carry flag work properly?, I also want it to be set correctly for "borrows" that occur during subtraction.

注意:我正在虚拟化的汇编语言是我自己设计的,旨在简单并基于英特尔的 x86-64(即 Intel64)实现,因此我希望这些标志的行为方式大致相同.

Note: The assembly language I am virtualising is of my own design, meant to be simple and based of Intel's implementation of x86-64 (i.e. Intel64), and so I would like these flags to behave in mostly the same way.

推荐答案

我似乎已经解决了这个问题,方法是将更新标志的参数拆分为一个无符号和有符号的结果,如下所示:

I appear to have solved the problem, by splitting the arguments to update flags into an unsigned and signed result as follows:

void update_flags(int16_t unsigned_result, int16_t signed_result)
{
    Registers::flags.zero = unsigned_result == 0;
    Registers::flags.sign = signed_result < 0;
    Registers::flags.carry = unsigned_result < 0 || unsigned_result > UINT8_MAX;
    Registers::flags.overflow = signed_result < INT8_MIN || signed_result > INT8_MAX
}

对于加法(应该为有符号和无符号输入产生正确的结果),我会执行以下操作:

For addition (which should produce the correct result for both signed & unsigned inputs) I would do the following:

int8_t a, b;
int16_t signed_result = int16_t(a) + int16_t(b);
int16_t unsigned_result = int16_t(uint8_t(a)) + int16_t(uint8_t(b));
update_flags(unsigned_result, signed_result);
int8_t c = a + b;

带符号的乘法我会做以下事情:

And signed multiplication I would do the following:

int8_t a, b;
int16_t result = int16_t(a) * int16_t(b);
update_flags(result, result);
int8_t c = a * b;

其他更新标志的操作依此类推

And so on for the other operations that update the flags

注意:我在这里假设 int16_t(a) 符号扩展,并且 int16_t(uint8_t(a)) 零扩展.

Note: I am assuming here that int16_t(a) sign extends, and int16_t(uint8_t(a)) zero extends.

我也决定不使用奇偶校验标志,如果我以后改变主意,我的 _mm_popcnt_u32 解决方案应该可以工作..

I have also decided against having a parity flag, my _mm_popcnt_u32 solution should work if I change my mind later..

附言感谢所有回复的人,这很有帮助.此外,如果有人能发现我的代码中的任何错误,我们将不胜感激.

P.S. Thank you to everyone who responded, it was very helpful. Also if anyone can spot any mistakes in my code, that would be appreciated.

这篇关于读取 CF、PF、ZF、SF、OF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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