Tag: x86

在_mm256_rsqrt_ps()中处理零

鉴于_mm256_sqrt_ps()相对较慢,并且我生成的值会立即被_mm256_floor_ps()截断,看看它似乎在做: _mm256_mul_ps(_mm256_rsqrt_ps(eightFloats), eightFloats); 是获得额外性能和避免管道停滞的方法。 不幸的是,零值,我当然得到崩溃计算1/sqrt(0) 。 围绕这个的最佳方法是什么? 我试过这个(有效并且更快),但是有更好的方法,还是我会在某些条件下遇到问题? _mm256_mul_ps(_mm256_rsqrt_ps(_mm256_max_ps(eightFloats, _mm256_set1_ps(0.1))), eightFloats); 我的代码用于垂直应用程序,因此我可以假设它将在Haswell CPU(i7-4810MQ)上运行,因此可以使用FMA / AVX2。 原始代码大约是: float vals[MAX]; int sum = 0; for (int i = 0; i < MAX; i++) { int thisSqrt = (int) floor(sqrt(vals[i])); sum += min(thisSqrt, 0x3F); } vals所有值都应该是整数值。 (为什么一切都不仅仅是int是一个不同的问题…)

如何在编译/链接时使用地址进行计算?

我写了一些用于初始化IDT的代码,它将32位地址存储在两个不相邻的16位半中。 IDT可以存储在任何地方,并通过运行LIDT指令告诉CPU在哪里。 这是初始化表的代码: void idt_init(void) { /* Unfortunately, we can’t write this as loops. The first option, * initializing the IDT with the addresses, here looping over it, and * reinitializing the descriptors didn’t work because assigning a * a uintptr_t (from (uintptr_t) handler_func) to a descr (aka * uint64_t), according to the compiler, “isn’t […]

x86汇编:INC和DEC指令和溢出标志

在x86汇编中,当有符号整数上的add或sub操作溢出时,溢出标志置位;当无符号整数上的操作溢出时,置载标志置位。 但是,当涉及到inc和dec指令时,情况似乎有些不同。 根据该网站 , inc指令根本不影响进位标志。 但是我找不到有关inc和dec如何影响溢出标志的任何信息,如果有的话。 发生整数溢出时,是否设置inc或dec设置溢出标志? 对于有符号整数和无符号整数,这种行为是否相同? ============================= 编辑 ==================== ========= 好的,基本上这里的共识是,在设置标志方面,INC和DEC应该与ADD和SUB的行为相同,但进位标志除外。 这也是英特尔手册中的内容。 问题是,当涉及到无符号整数时,我实际上无法在实践中重现这种行为。 请考虑以下汇编代码(使用GCC内联汇编以便更轻松地打印结果。) int8_t ovf = 0; __asm__ ( “movb $-128, %%bh;” “decb %%bh;” “seto %b0;” : “=g”(ovf) : : “%bh” ); printf(“Overflow flag: %d\n”, ovf); 这里我们递减一个带符号的8位值-128。 由于-128是可能的最小值,溢出是不可避免的。 正如预期的那样,打印出: Overflow flag: 1 但是当我们使用无符号值执行相同操作时,行为并不像我预期的那样: int8_t ovf = 0; __asm__ ( “movb $255, %%bh;” […]

使用时间戳计数器和clock_gettime进行缓存未命中

作为本主题的后续内容 ,为了计算内存未命中延迟,我使用_mm_clflush , __rdtsc和_mm_lfence (基于此问题/答案的代码)编写了以下代码。 正如您在代码中看到的,我首先将数组加载到缓存中。 然后我刷新一个元素,因此缓存行从所有缓存级别逐出。 为了在-O3期间保留顺序,我放了_mm_lfence 。 接下来,我使用时间戳计数器来计算延迟或读取array[0] 。 正如您在两个时间戳之间看到的那样,有三个指令:两个lfence和一个read 。 所以,我必须减去lfence开销。 代码的最后一部分计算开销。 在代码结束时,打印开销和未命中延迟。 但是,结果无效! #include #include #include int main() { int array[ 100 ]; for ( int i = 0; i < 100; i++ ) array[ i ] = i; uint64_t t1, t2, ov, diff; _mm_lfence(); _mm_clflush( &array[ 0 ] ); _mm_lfence(); […]

为什么在function序言/尾声中使用ebp?

前段时间我正在尝试编写汇编程序并将其与C程序链接,我发现我可以跳过标准的C调用序言尾声 push ebp mov ebp, esp (sub esp, 4 … mov esp, ebp) pop ebp 只是跳过这一切,只需通过esp ,就像 mov eax, [esp+4] ;; take argument mov [esp-4], eax ;; use some local variable storage 它似乎工作得很好。 为什么使用这个ebp – 可能更快地通过ebp解决或者是什么?

如何在16位模式下使用GDB?

我有以下代码,我试图实现一个使用BIOS函数打印字符串的函数: int printString(char* string) { int i = 0; while (*(string + i) != ‘\0’) { char al = *(string + i); char ah = 0xe; int ax = ah * 256 + al; interrupt(0x10,ax,0,0,0); i++; } return i; } 函数中断在汇编中实现。 它调用适当的BIOS中断,如第一个参数所给出的,其余参数分别包含ax,bx,cx和dx寄存器的内容: .global _interrupt _interrupt: push bp mov bp, sp push si push ds mov […]

调用always_inline’_mm_mullo_epi32’时内联失败:目标特定选项不匹配

我正在尝试使用使用SIMD内在函数的cmake编译C程序。 当我尝试编译它时,我得到两个错误 / usr / lib / gcc / x86_64-linux-gnu / 5 / include / smmintrin.h :326:1:错误:内联调用always_inline’_mm_mullo_epi32’失败:目标特定选项不匹配_mm_mullo_epi32(__ m128i __X,__ m128i __Y) / usr / lib / gcc / x86_64-linux-gnu / 5 / include / tmmintrin.h :136:1:错误:内联调用always_inline’_mm_shuffle_epi8’失败:目标特定选项不匹配_mm_shuffle_epi8(__ m128i __X,__ m128i __Y) 这个问题已经通过设置在这里解决了StackOverflow set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -msse4.1”) 我尝试了相同的和许多其他选项。 但我的项目仍然无法编译。 set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -msse4.1”) set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -sse4_1”) set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -march=nehalem”) […]

在没有编译器的情况下创建C函数会生成prologue / epilogue&RET指令吗?

考虑这个function: void foo(){ //do something } 在assembly中,它看起来像这样(不准确): push something ;do stuff pop something ret 但我不想要这个生成的代码( RET , PUSH , POP ……)。 我只想要一个代码块的标签,所以我必须回复自己: void bar(){ //do something asm(“iret”) //i want to use this function as a ISR } 在汇编中,它看起来像这样: ; do something iret 没有PUSH , POP或RET 。 是否有任何预处理器指令或关键字可以让我实现这一目标? 我在Windows下使用GCC和NASM ,我正在尝试生成自己的中断服务例程(ISR)。

如何在Assembly Langauge X86中检测溢出条件

我有一个任务,我们必须编写两个函数。 还必须使用处理器的条件代码检测溢出条件,并返回0以指示已遇到错误。 我能够写出这些function。 .file “formula.c” .text .globl _nCr .def _nCr; .scl 2; .type 32; .endef _nCr: pushl %ebp movl %esp, %ebp subl $56, %esp movl 8(%ebp), %eax movl %eax, (%esp) testl %eax, %eax call _factorial movl %eax, -12(%ebp) movl 12(%ebp), %eax addl $1, %eax movl %eax, (%esp) call _factorial movl %eax, -16(%ebp) movl 12(%ebp), %eax […]

如何使用GNU C Vector Extensions从/向数组加载/存储?

我正在使用GNU C Vector Extensions ,而不是Intel的_mm_*内在函数。 我想做与英特尔的_m256_loadu_pd内在相同的事情。 逐个分配值很慢:gcc生成的代码有4个加载指令,而不是一个单独的vmovupd ( _m256_loadu_pd确实生成)。 typedef double vector __attribute__((vector_size(4 * sizeof(double)))); int main(int argc, char **argv) { double a[4] = {1.0, 2.0, 3.0, 4.0}; vector v; /* I currently do this */ v[0] = a[0]; v[1] = a[1]; v[2] = a[2]; v[3] = a[3]; } 我想要这样的东西: v = (vector)(a); 要么 v […]