是否可以使用整数算术实现按位运算符?

2024-03-06

我面临着一个相当特殊的问题。我正在为不支持按位运算的体系结构开发编译器。然而,它处理带符号的 16 位整数算术,我想知道是否可以仅使用以下方法来实现按位运算:

  • Addition (c = a + b)
  • 减法 (c = a - b)
  • Division (c = a / b)
  • 乘法 (c = a * b)
  • Modulus (c = a % b)
  • Minimum (c = 最小值(a,b))
  • Maximum (c = 最大值(a, b))
  • 比较 (c = (a )
  • Jumps (goto、for 等)

我希望能够支持的按位运算是:

  • Or (c = a |乙)
  • And (c = a & b)
  • Xor (c = a ^ b)
  • 左移 (c = a )
  • 右移 (c = a >> b)
  • (所有整数都有符号,所以这是一个问题)
  • 有符号移位 (c = a >>> b)
  • 一个的补语 (a = ~b)
  • (已经找到解决办法了,见下文)

通常情况下,问题是相反的。如何使用按位黑客实现算术优化。但在本例中并非如此。

可写内存是非常稀缺在这种架构上,因此需要按位运算。按位函数本身不应使用大量临时变量。然而,恒定的只读数据和指令存储器是丰富的。这里还需要注意的是,跳转和分支并不昂贵,并且所有数据都可以轻松缓存。跳转花费的周期是算术(包括加载/存储)指令的一半。换句话说,上述所有支持的功能的成本是单次跳转周期的两倍。


一些可能有帮助的想法:

我发现你可以做一个人的补语(取反位)使用以下代码:

// Bitwise one's complement
b = ~a;
// Arithmetic one's complement
b = -1 - a;

我还记得除以二的幂时的旧移位技巧,所以按位移位可以表示为:

// Bitwise left shift
b = a << 4;
// Arithmetic left shift
b = a * 16; // 2^4 = 16

// Signed right shift
b = a >>> 4;
// Arithmetic right shift
b = a / 16;

对于其余的按位运算我有点一无所知。我希望该架构的架构师能够提供位操作。

我还想知道是否有一种快速/简单的方法可以在不使用内存数据表的情况下计算二的幂(用于移位操作)。一个简单的解决方案是跳入乘法领域:

b = 1;
switch (a)
{
  case 15: b = b * 2;
  case 14: b = b * 2;
  // ... exploting fallthrough (instruction memory is magnitudes larger)
  case 2: b = b * 2;
  case 1: b = b * 2;
}

或设置和跳跃方法:

switch (a)
{
  case 15: b = 32768; break;
  case 14: b = 16384; break;
  // ... exploiting the fact that a jump is faster than one additional mul
  //     at the cost of doubling the instruction memory footprint.
  case 2: b = 4; break;
  case 1: b = 2; break;
}

第一个移位解决方案(shift 是移位距离,不能为负数,a 是要移位的操作数,也包含完成后的结果)。所有三个班次操作均使用功率表。

// table used for shift operations
powtab = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, -32768 };

// logical shift left
if (shift > 15) {
     a = 0; // if shifting more than 15 bits to the left, value is always zero
} else {
     a *= powtab[shift];
}

// logical shift right (unsigned)
if (shift > 15) {
    a = 0; // more than 15, becomes zero
} else if (shift > 0) {
    if (a < 0) {
        // deal with the sign bit (15)
        a += -32768;
        a /= powtab[shift];
        a += powtab[15 - shift];
    } else {
        a /= powtab[shift];
    }
}

// arithmetic shift right (signed)
if (shift >= 15) {
    if (a < 0) {
        a = -1;
    } else {
        a = 0;
    }
} else if (shift > 0) {
    if (a < 0) {
        // deal with the sign bit
        a += -32768;
        a /= powtab[shift];
        a -= powtab[15 - shift];
    } else {
        // same as unsigned shift
        a /= powtab[shift];
    }
}

对于 AND、OR 和 XOR,我无法想出一个简单的解决方案,因此我将通过循环每个位来实现。可能有更好的技巧来做到这一点。伪代码假设 a 和 b 是输入操作数,c 是结果值,x 是循环计数器(每个循环必须恰好运行 16 次):

// XOR (^)
c = 0;
for (x = 0; x <= 15; ++x) {
    c += c;
    if (a < 0) {
        if (b >= 0) {
            c += 1;
        }
    } else if (b < 0) {
        c += 1;
    }
    a += a;
    b += b;
}

// AND (&)
c = 0;
for (x = 0; x <= 15; ++x) {
    c += c;
    if (a < 0) {
        if (b < 0) {
            c += 1;
        }
    }
    a += a;
    b += b;
}

// OR (|)
c = 0;
for (x = 0; x <= 15; ++x) {
    c += c;
    if (a < 0) {
        c += 1;
    } else if (b < 0) {
        c += 1;
    }
    a += a;
    b += b;
}

假设所有变量都是 16 位并且所有操作都表现为有符号(因此当设置位 15 时 a

编辑:我实际上测试了所有可能的操作数值(-32768 到 32767)的移位范围从 0 到 31 的正确性,并且它工作正常(假设整数除法)。对于 AND/OR/XOR 代码,在我的机器上进行详尽的测试需要太长时间,但由于这些代码非常简单,所以无论如何都不应该出现边缘情况。

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

是否可以使用整数算术实现按位运算符? 的相关文章

随机推荐

  • OpenCV 从 BGR 颜色转换为灰度时出错

    我正在尝试使用以下代码将图像从 BGR 转换为灰度格式 img cv2 imread path to image file gray cv2 cvtColor img cv2 COLOR BGR2GRAY 这似乎工作正常 我检查了数据类型i
  • 没有 php.ini 与brew

    我用brew安装了PHP7 它说 The php ini file can be found in usr local etc php 7 0 php ini 但我在那里什么也没看到 所以我确认了php fpm i Configuratio
  • 嵌入、嵌入高级或动态地图之间的区别

    我正在使用 Google Maps Javascript API 将地图添加到网站 现在 当谷歌改变他们的价格时 我不确定我的极限是多少 这site https cloud google com maps platform pricing
  • 如何刷新 DbContext

    我想刷新我的所有实体DbContext在没有重新创建它的情况下 我尝试了以下操作 但没有一个有意义 var context IObjectContextAdapter myDbContext ObjectContext var refres
  • 在 Windows 上构建 Boost

    我正在尝试使用 mingw 在 Windows 7 x64 机器上构建 boost 库 当我尝试运行 b2 时 b2 build dir C boost build toolset gcc with python 构建库时出现错误 Jamr
  • C# 在包含任何字符的设置中序列化 List 的方法 (Regex/xml)

    我正在寻找一种简洁 干净的方法将字符串列表存储到C 设置 http msdn microsoft com en us library aa730869 28VS 80 29 aspx文件 据我所知 您无法将 List 对象存储到这些设置中
  • SQL Server 2005中的连接错误

    我有一个问题 我运行应用程序 C 并收到错误 与网络相关或 发生特定于实例的错误 建立与 SQL 的连接 服务器 找不到服务器或 无法访问 验证 实例名称正确且 SQL 服务器配置为允许远程 连接 提供商 SQL 网络 接口 错误 26 错
  • 如何将 iMessage 扩展的 sqlite 存储文件下载到 MacBook

    我们正在开发 iMessage 扩展 它成功地使用了核心数据 我们需要评估 store sqlite 文件 但找不到它 我们尝试这样找到它 在 Xcode 中 窗口 gt 设备 In Installed Apps 选择我们的扩展 Downl
  • 如何使用 gmock 测试类是否调用其基类的方法

    class Foo public int x int y void move void class SuperFoo public Foo public int age void update SuperFoo update void mo
  • 自定义验证在版本 4.1.1 的联系表单 7 中不起作用

    我必须在联系表单 7 中制作一个带有自定义验证字段的表单 它不适用于联系表单 7 的最新版本 4 1 1 但适用于旧版本 我创建了一个用于从表单获取优惠券代码的字段 如果优惠券是从 HIP 开始的 我想验证该条目 我的代码如下 add fi
  • 如何“git pull”到非当前分支的分支?

    当你跑步时git pull on the master分支 它通常从origin master 我在另一个名为newbranch 但我需要运行一个执行以下操作的命令git pull from origin master into maste
  • 重新启动 kube-proxy 等待条件

    在 Windows 10 中运行 minikube start 时 出现以下错误 错误 重新启动集群时出错 重新启动 kube proxy 等待 kube proxy 启动以进行 configmap 更新 等待条件超时 请帮我解决给定的问题
  • Delphi DataSnap 框架向 JSON 消息添加内容

    我正在使用 Delphi XE DataSnap REST 服务器并尝试返回 JSON 序列化对象 我的方法返回给客户端的结果如下所示 type ServerMethodsUnit1 TJSONIssue id 1 fields FIssu
  • SyntaxError:解析错误仅发生在 safari 中

    我收到 SyntaxError Parse Error 仅在 safari 上 这是有问题的代码
  • MySql PHP 从逗号分隔的数据(标签)中选择不同值的计数

    如何从 MySql 中以逗号分隔值存储的数据中选择不同值的计数 最后我将使用 PHP 从 MySql 输出数据 里面有每个帖子的标签 所以最后 我尝试输出数据 就像 stackoverflow 处理标签的方式一样 如下所示 tag name
  • 将 setIcon 首选项设置为 ColorDrawable 在 Android 5.0 Lollipop 上不起作用

    在我的应用程序中 我使用以下行来区分一些首选项 preference setIcon new ColorDrawable color 在 Lollipop 之前的 Android 版本中 它工作正常 并且首选项显示所选颜色的方形图标 但在
  • 将共享库打包到 elf 中 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一个实用程序可以ALL精灵需要的SO将它们变成静态然后将精灵转换为SO的自由 以下是一些您可能会
  • 共享目标通用应用程序 Windows 10 方法

    我为此苦苦挣扎了几个小时 但找不到有效的解决方案 我的应用程序是共享的目标应用程序 问题是当它运行并且用户想要共享内容时 protected override async void OnShareTargetActivated ShareT
  • .* 有什么作用?正则表达式实际上意味着什么?

    我使用 Perl 已有十年了 但最近我对使用 感到困惑 正则表达式 它似乎与最小字符数不匹配 有时它会给出不同的结果 例如 对于此字符串 aaaaaaaaaaaaaaaaaaaaaaammmmmmmmmmmbaaaaaaaaaaaaaaaa
  • 是否可以使用整数算术实现按位运算符?

    我面临着一个相当特殊的问题 我正在为不支持按位运算的体系结构开发编译器 然而 它处理带符号的 16 位整数算术 我想知道是否可以仅使用以下方法来实现按位运算 Addition c a b 减法 c a b Division c a b 乘法