最小的代码大小循环来计算寄存器中的位(递减另一个寄存器)?

时间:2018-04-07 10:29:21

标签: assembly x86 micro-optimization code-size

我需要在8086 *中编写以下C代码片段 装配尽可能短(少于10个 但是我只能设法用12个字节写它。

任何想法?

while (ax) {
    bx--;
    ax &= ax-1;
}

1 个答案:

答案 0 :(得分:2)

您正在尝试的操作称为填充计数,即计算寄存器中的设置位数。

在较新的CPU中实际上只有一条指令。而且,由于在2018年定位原始8086真的不那么有趣。

简单的答案是:

Traceback (most recent call last):
  File "site-packages\pandas\__init__.py", line 26, in <module>
  File "c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages\pandas\_libs\__init__.py", line 4, in <module>
  File "c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 714, in load_module
    module = loader.load_module(fullname)
  File "pandas/_libs/tslib.pyx", line 1, in init pandas._libs.tslib
ModuleNotFoundError: No module named 'pandas._libs.tslibs.timedeltas'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "TrivialTest.py", line 2, in <module>
  File "c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages\pandas\__init__.py", line 35, in <module>
ImportError: C extension: No module named 'pandas._libs.tslibs.timedeltas' not built.
If you want to import pandas from the source directory, you may need to run 'python setup.py build_ext --inplace --force' to build the C extensions first.
[18776] Failed to execute script TrivialTest

6个字节,如果您愿意在f3 0f b8 c0 popcnt eax,eax 29 c3 sub ebx,eax 中允许正值并且可以假定/确保ebx从零开始为零,则可以减少到4个字节。

请注意,不需要使用16位寄存器,这已有很多年了。

如果您希望代码在原始8086(不支持ebx)上运行,则必须保留循环。

以下完全简单的代码需要12个字节:

popcnt

通过以稍微低效的方式计数位,可以将其减少到9个字节。在这里,我们只测试所有16位的ax。

85 c0                   test   ax,ax          ;is AX zero?
74 08                   je     <done>         ;yes, bail out
<loop>:
4b                      dec    bx             ;bx--
89 c1                   mov    cx,ax
49                      dec    cx             ;cx = ax - 1
21 c8                   and    ax,cx          ;ax = ax & (ax-1) 
75 f8                   jne    <loop>         ;repeat until done
<done>:

诀窍是了解代码的作用,然后以不同的方式对其进行重新定义。