我正在尝试计算大量uint64的位奇偶校验.比特奇偶校验是指接受uint64的函数,如果设置的比特数是偶数则输出0,否则为1.
目前我正在使用以下功能(@Troyseph,在这里找到):
uint parity64(uint64 n){
n ^= n >> 1;
n ^= n >> 2;
n = (n & 0x1111111111111111) * 0x1111111111111111;
return (n >> 60) & 1;
}
Run Code Online (Sandbox Code Playgroud)
相同的SO页面具有以下汇编例程(由@papadp提供):
.code
; bool CheckParity(size_t Result)
CheckParity PROC
mov rax, 0
add rcx, 0
jnp jmp_over
mov rax, 1
jmp_over:
ret
CheckParity ENDP
END
Run Code Online (Sandbox Code Playgroud)
它利用了机器的奇偶校验标志.但我不能让它与我的C程序一起工作(我知道旁边没有汇编).
问题.如何在C源文件中包含上面(或类似)代码作为内联汇编,以便该parity64()函数运行该代码?
(我在Intel Xeon Haswell上使用GCC和64位Ubuntu 14)
如果它有任何帮助,则parity64()在以下例程中调用该函数:
uint bindot(uint64* a, uint64* b, uint64 entries){
uint parity …Run Code Online (Sandbox Code Playgroud) 好吧,所以我对组装很新,事实上,我对组装很新.我写了一段代码,它只是意味着从用户那里获取数字输入,乘以10,并通过程序退出状态将结果表示给用户(通过在终端中输入echo $?)问题是,它是没有给出正确的数字,4x10显示为144.所以我认为输入可能是一个字符,而不是一个整数.我的问题是,如何将字符输入转换为整数,以便它可以用于算术计算?
如果有人能够回答我记得我是初学者,那将是很棒的:)另外,我怎样才能将所述整数转换回字符?
section .data
section .bss
input resb 4
section .text
global _start
_start:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 4
int 0x80
mov ebx, 10
imul ebx, ecx
mov eax, 1
int 0x80
Run Code Online (Sandbox Code Playgroud) 你为什么要用:
MOV EAX, 22
SHL EAX, 2
Run Code Online (Sandbox Code Playgroud)
...乘以4而不是仅仅使用MUL指令?
我知道这也可以用SHR而不是DIV.
这样做有什么好处?
你也可以用奇数做这个或者它只能是偶数吗?
我是AVX的新手(来自ARM NEON),并且令人不快地惊讶于AVX缺少许多U8算术,绝对差异在于他们之间缺失.
因此我不得不求助于max(a,b)-min(a,b)内联函数:
static inline __m256i _mm256_abd_epu8(__m256i a, __m256i b)
{
return _mm256_sub_epi8(_mm256_max_epu8(a, b), _mm256_min_epu8(a, b));
}
Run Code Online (Sandbox Code Playgroud)
我很好奇是否有更有效的方法来处理这个问题.
是的,我知道_mm256_sad_epu8,但我需要自己的差异,而不是总和.
我很感激任何输入,并且没关系AVX2任何向后兼容性.
提前致谢.
我有作业来编写汇编代码以检查数字是否为奇数或偶数。我有这个代码
code_seg SEGMENT
ASSUME cs:code_seg, ds:data_seg;
mov ax, 11;
test ax, 1;
end: jmp end;
code_seg ENDS
Run Code Online (Sandbox Code Playgroud)
并检查数字是否是偶数,我看是否设置了零标志。我知道测试指令就像逻辑与,如果结果为0,它将设置零标志。我的问题是:如何检查数字是否为奇/偶?其实我不知道为什么有些偶数(二进制)和(逻辑与)1给出0的结果?
我试图用Linux命令定义一个C语言的计算器,dc程序的结构并不那么重要,你需要知道我得到两个数字,我想在打字时划分它们/.因此,我将这两个数字发送到进行除法的汇编函数(参见下面的代码).但这仅适用于正数.
当输入999 3 /返回333是正确的,但在打字的时候-999 3 /,我得到了陌生号码1431655432,并输入两个负数时,像-999 -3 /任何两个负数每次我得到0.
程序集中的代码是:
section .text
global _div
_div:
push rbp ; Save caller state
mov rbp, rsp
mov rax, rdi ; Copy function args to registers: leftmost...
mov rbx, rsi ; Next argument...
cqo
idiv rbx ; divide 2 arguments
mov [rbp-8], rax
pop rbp ; Restore caller state
Run Code Online (Sandbox Code Playgroud) 有没有一种方法可以计算 mod 运算,而无需在汇编 x86 语言中使用 DIV 或 IDIV?
例如,可以使用 DIV 来获取除法的剩余部分。但是,除了使用 DIV 之外,还有其他选择吗?
考虑以下汇编代码循环:
#include <iostream>
#define ADD_LOOP(i, n, v) \
asm volatile ( \
"movw %1, %%cx ;" \
"movq %2, %%rax ;" \
"movq $0, %%rbx ;" \
"for: ;" \
"addq %%rax, %%rbx ;" \
"decw %%cx ;" \
"jnz for ;" \
"movq %%rbx, %0 ;" \
: "=x"(v) \
: "n"(i), "x"(n) \
: "%cx", "%rax", "%rbx" \
);
int main() {
uint16_t iter(10000);
uint64_t num(5);
uint64_t val;
ADD_LOOP(iter, num, val)
std::cout << val << std::endl;
return 0; …Run Code Online (Sandbox Code Playgroud) 如果编译器将高级语言转换为机器代码,为什么我们甚至需要汇编程序呢?是否有任何汇编级语言,我们不能使用编译器?
我从同事那里听说 C++ 比 Java 更快,在寻求最高性能时,特别是对于金融应用程序,这是一条必经之路。但我的观察有点不同。谁能指出我实验的失败或在讨论中添加一些科学变量?
注1:我在 C++ 编译器中使用-O3(最大优化)和-O2 。
注2:包含每种语言的简短完整源代码。您可以随意在自己的机器上运行、进行更改、得出结论并分享。
注意3:如果将两个源代码并排放在编辑器中,您将看到它们的实现是等效的。
更新:我尝试clang++过g++各种优化选项(-O2、-O3、-Os、-march=native等),它们都产生了比 Java 慢的结果。我认为此时为了使 C++ 更快,我必须深入研究生成的汇编代码并进行一些汇编编程。我想知道在编写大型实际应用程序时这种方法(汇编编程和汇编调试)有多实用。
基准测试有什么作用?
执行 1000 万次,丢弃前 100 万次进行预热,并输出平均、最短和最长时间。
对于C++我得到:(使用 -O3 和 -O2)
$ g++ --version
g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
$ g++ TimeBubbleSort.cpp -o TimeBubbleSort -std=c++11 -O3
$ ./TimeBubbleSort 10000000 1000000 60
Value …Run Code Online (Sandbox Code Playgroud)