是否可以在php脚本中加入汇编代码?
我的意思是这样: asm( //assembly code here mov dx, 4 // etc... ) asm() - php函数 可能吗? 解决方案 不,这是不可能的.您最接近的是使用exec()或类似功能来调用外部程序或脚本. 其他解决方案 简而言之,否. PHP脚本被编译为特定于其特定虚拟机的字节码(假设在此处使用Zend Engine).因此,您无法将本机和PHP代码与标准分配混合. 但是,可以为PHP编写C扩展,您可以在其中使用内联汇编.
0 2023-06-01
编程技术问答社区
避免用内联的asm优化离开变量
我正在阅读 nile-benchmarking"> nile-benchmarking"> nile-benchmmarking">防止编译器优化时,描述了 escape()来自Chandler Carruths Talk 从阅读中,我假设如果我具有" g"(val)之类的输入约束,那么编译器将无法优化val.但是在下面的g()中,没有生成代码.为什么? 如何重写doNotOptimize()以确保生成g()的代码? template void doNotOptimize(T const& val) { asm volatile("" : : "g"(val) : "memory"); } void f() { char x = 1; doNotOptimize(&x); // x is NOT optimized away } void g() { char x = 1; doNotOptimize(x); /
0 2023-05-24
编程技术问答社区
将最重要的设定位以下的所有位清零的最有效方法是什么?
因此,对于以下序列: 0001000111000 所需的结果将是: 0001000000000 我完全意识到,可以通过汇编bsrl(或类似的位二widdlinghack)找到MSB的索引,然后>> >> >>将数字移动数字(index -1),然后 解决方案 没有一个指令可以做到这一点. bmi1 blsi dst,src 可以隔离最高.即x & -x.如果x86具有blsi的位曲线版本,我们可以使用它,但事实并非如此. ,但是您可以做得比建议更好.全零输入始终将是位扫描和移位的特殊情况.否则,我们的输出完全设置为1位.是1
0 2023-05-24
编程技术问答社区
为什么在8086上LOOP比DEC,JNZ快?
我的教授声称,循环在8086上更快,因为仅获取了一个指令,而不是两个指令,例如dec cx,jnz.因此,我认为我们通过避免额外的获取和解码为迭代节省时间. ,但在讲座的早期,他还提到循环做的事情与dec,jnz在引擎盖下的工作相同,我认为它的解码也应该更加复杂,因此速度差异应该平衡.那么,为什么循环指令更快?我通过后来,教授使用相同的推理来解释为什么rep字符串操作可能比循环 +个体运动说明更快,但是由于我并没有完全相信以前的方法,所以我在这里问了这个问题. 解决方案 不是解码,这是问题,通常是在8086上获取. 启动两个单独的指令 - 模式操作可能比仅获取一个loop指令的微码更昂贵.我猜这是下表中不包括Code-Fetth瓶颈的数字的说明. 同样或更重要的是,8086通常是通过内存访问(包括CodeFetch)瓶颈的. (8088几乎总是是,与8086的16位公共汽车不同的是8位公共汽车的稻草呼吸. ). dec cx是1个字节,jnz rel8是
6 2023-05-24
编程技术问答社区
为什么用算术法而不是_bittest来打印二进制的数字更快?
下两个代码部分的目的是用二进制打印号码. 第一个通过两个说明(_bittest)来执行此操作,而第二个则通过纯算术指令(是三个说明)来做. 第一个代码部分: #include #include #include long num = 78002; int main() { unsigned char bits[32]; long nBit; LARGE_INTEGER a, b, f; QueryPerformanceCounter(&a); for (size_t i = 0; i
0 2023-05-24
编程技术问答社区
如何理解影响分支预测的宏观`可能'?
我注意到,如果我们知道控制流的可能性很大,或者是错误的,我们可以告诉编译器,例如,在Linux内核中,有很多likely unlikely,实际上是由由gcc提供,所以我想找出它的工作原理,然后检查那里的组件: 20:branch_prediction_victim.cpp **** if (array_aka[j] >= 128) 184 .loc 3 20 0 is_stmt 1 185 00f1 488B85D0 movq -131120(%rbp), %rax 185 FFFDFF 186 00f8 8B8485F0 movl -131088(%rbp,%rax,4), %eax 186 FFFDFF 187 00ff 83F87F cmpl $127, %eax
0 2023-05-24
编程技术问答社区
x86-64对16-32-或64-位的支持是否比其他的更好?"原生 "或 "扩展 "这两个词有什么含义?
根据 wiki x86-64支持16-bit,32-bit和64位程序.它在更快地运行代码的意义上是否比其他人更好地支持一个?有人(可能正在吹我的屁股)告诉我,Operteron CPU是第一个运行64位,仍然是32bits的本地人. 在这种情况下成为"本地"意味着什么?我在Wikipedia上注意到它说64位是X86的延伸,那么这会有什么影响? 解决方案 X86-64能够在基本上相同的单位时间内执行多种操作数宽度的许多说明,因此,具有64位操作数的说明并不比其他宽度更快或较慢,作为一般规则. (某些较小的指令实际上可以通过部分注册的写摊位减慢). ,但有64位指令更有效,从某种意义上说,每单位时间都会处理更多数据位. (对于整数操作数,我想知道这在实践中的有效性:大多数只是平台的数字很小,并且处理全零零或ALL-ONES的前56位并没有真正增加价值,而只会增加热量). x86-64还为组装编码器和编译器提供了另外的8个整数寄存器,这有助于复杂的循环避免溢出到内
0 2023-05-24
编程技术问答社区
开关实现;arm;汇编;aarch64;arm64
我在Aarch64汇编程序上实现"开关"运算符的方式很有趣. 在ARM32平台上,我使用了 之类的东西 ldr pc, [pc, ta, LSL#2] nop // alignment .int .L.case1 .int .L.case2 ... .int .L.caseN 但是,由于64位版本对" PC"注册使用有很大限制,因此该实现不再起作用. 似乎最简单的方法是使用一对比较和分支操作,例如 cmp ta, #1 b.eq .L.case1 cmp ta, #2 b.eq .L.case2 ... ,但有时有十几个案件,在达到最后的"案例"之前会导致大量延误. 您可以分享您的想法如何在Aarch64上实施快速切换. 谢谢:) 解决方案 我没
0 2023-05-24
编程技术问答社区
如何提高64位C/intel汇编程序的内存性能/数据定位性
我正在使用爱好计划来教自己高性能计算技术. 我的PC有一个Intel Ivy Bridge Core i7 3770处理器,带有32 GB的内存和Microsoft VS2010 C编译器的免费版本. 64位程序需要大约20 GB的内存,因为它具有五个4 GB查找表(Bytevecm ... Bytevecx下面).此搜索程序的内部循环写为单独的C文件(因为我可能希望以后用汇编版本替换它),如下所示: #define H_PRIME 1000003 int inner( const char* bytevecM, const char* bytevecD, const char* bytevecC, const char* bytevecL, const char* bytevecX, int startval, int endval, int m2, int d2, int c2, int l2, int x2, int
0 2023-05-24
编程技术问答社区
是leaq太慢了,还是有其他原因,较小的汇编列表比较长的列表更慢?
我不知道任何真正的组装,但是可以读取GCC -S输出以评估给定C代码的实际成本. 这个问题不是关于分析和基准的太多,而是教育意义.我需要有人向我解释为什么[1]片段不比第二个摘要快. 好吧,曾经想到:"是的,像MUL这样的某些操作非常昂贵,但是如果一个组件比另一个组件大于另一个组件,则应该慢一点". 这是真的,直到我遇到了这两个: unsigned char bytes[4] = {0, 0, 0, 5}; // 1 int32_t val = *((int32_t*)bytes); /* produces: leaq -16(%rbp), %rax movl (%rax), %eax movl %eax, -4(%rbp) movl $0, %eax */ // 2 val = bytes[3] |
0 2023-05-24
编程技术问答社区
L1高速缓存的延迟访问时间
在此Web链接中: http://www.7-cpu.com/cpu/cpu/ivybridge..html 说Ivy Bridge L1缓存访问的延迟是: l1数据缓存延迟= 4个循环,用于通过指针进行简单访问 l1数据缓存延迟= 5个循环,用于使用复杂地址计算(size_t n, *p; n = p [n]). 而不是"简单",它们是否意味着指针大小与单词大小相同?因此,如果指针为32位,它是32位OS,那么这将是"简单"的,否则会花费"复杂"潜伏期? 我只是不太了解他们对两个潜伏期的差异的解释. 解决方案 完整的x86有效地址看起来像displacement + base + index * scale(其中displacement是常数,base和index是寄存器,scale是1、2、4或8). 如果仅存在displacement(或者也许是base术语),他们听起来很简单,而拥有index * scale则肯定会属于复杂类别.
2 2023-05-24
编程技术问答社区
与mov reg, imm64相比,RIP-relative寻址的表现如何?
众所周知,X86-64指令不支持64位即时值(除了MOV).因此,当代码从32到64位迁移时,类似的说明: cmp rax, addr32 不能用以下内容替换: cmp rax, addr64 在这种情况下,我正在考虑两种替代方案:(a)使用刮擦寄存器加载常数或(b)使用RIP轴承的地址.两种方法看起来像这样: mov r11, addr64 ; scratch register cmp rax, r11 ptr64: dq addr64 ... cmp rax, [rel ptr64] ; encoded as cmp rax, [rip+offset] 我写了一个非常简单的循环,以比较两种方法的性能(我在下面粘贴了).尽管(b)使用间接指针,但(a)在说明中具有即时编码(可能导致使用i-cache的使用情况更糟).令人惊讶的是,我发现(b)运行速度比(a)快10%.在更常见的现实世界代码中,这种结果是
0 2023-05-24
编程技术问答社区
地址操作数如何影响机器代码的性能和大小?
从32位CPU模式开始,有可用于X86体系结构的扩展地址操作数.一个人可以指定基础地址,位移,索引寄存器和缩放系数. 例如,我们想大步浏览32位整数的列表(每两个都来自32字节长的数据结构的数组,%rdi作为数据索引,%rbx作为基本指针). addl $8, %rdi # skip eight values: advance index by 8 movl (%rbx, %rdi, 4), %eax # load data: pointer + scaled index movl 4(%rbx, %rdi, 4), %edx # load data: pointer + scaled index + displacement 我知道,这种复杂的解决方案适合单个机器代码指令.但是,这种操作的成本是多少?与独立指针计算相比,它与之相比如何: addl $32, %rbx # skip eight values
2 2023-05-24
编程技术问答社区
通过MOV交换变量的成本,XOR
让我们交换2个变量. int temp = a; a = b; b = temp; 这是一些半优化的ASM伪代码: mov eax, dword ptr [rbp+4] mov ebx, dword ptr [rbp+8] mov dword ptr [rbp+8], eax mov dword ptr [rbp+4], ebx 与彼此的对象相关的速度会更快吗? a ^= b ^= a ^= b; asm psuedocode: mov eax, dword ptr[rbp+4] xor eax, dword ptr[rbp+8] xor dword ptr[rbp+8], eax xor eax, dword ptr[rbp+8] xor dword ptr[rbp+8], eax mov eax, dword ptr[rbp+4] 其中哪一个会更快? (欢迎来宾) 解决方案 将其拉入两个寄存器,然后向后写交换内容可能是解决方案中最快的.
0 2023-05-24
编程技术问答社区
为什么我的装配代码比C实施慢得多
我正在学习组装.因此,我编写了一个例程,如果输入是非负的,则返回其输入的平方根,并且它将返回0否则. 我已经在汇编和C中实现了例程,我想了解为什么使用-O2编译的C例程比我的汇编例程快得多. C例程的分解代码看起来比我的装配程序更复杂,因此我不明白我在哪里出错. 组装例程(srt.asm): global srt section .text srt: pxor xmm1,xmm1 comisd xmm0,xmm1 jbe P sqrtsd xmm0,xmm0 retq P: pxor xmm0,xmm0 retq 我将上述编译为 nasm -g -felf64 srt.asm c例程(srtc.c) #include #include #include extern double srt(double); double srt1(double x) { return sqrt(
2 2023-05-24
编程技术问答社区
如何确定CPE:每元素循环数
如何确定程序的CPE? 例如,我有此循环的汇编代码: # inner4: data_t = float # udata in %rbx, vdata in %rax, limit in %rcx, # i in %rdx, sum in %xmm1 1 .L87: # loop: 2 movss (%rbx,%rdx,4), %xmm0 # Get udata[i] 3 mulss (%rax,%rdx,4), %xmm0 # Multiply by vdata[i] 4 addss %xmm0, %xmm1 # Add to sum 5 addq $1, %rdx # Increment i 6 cmpq %rcx, %rdx
0 2023-05-24
编程技术问答社区
为什么在一个未滚动的ADD循环内重新初始化一个寄存器会使它运行得更快,即使循环内有更多的指令?
我有以下代码: #include #include #define ITERATIONS "10000" int main() { /* ====================================== The first case: the MOV is outside the loop. ====================================== */ auto t1 = std::chrono::high_resolution_clock::now(); asm("mov $100, %eax\n" "mov $200, %ebx\n" "mov $" ITERATIONS ", %ecx\n" "lp_test_time1:\n" " add %eax, %ebx\n" //
0 2023-05-24
编程技术问答社区
python是否将函数参数中的加载到寄存器中,还是将它们保存在堆栈上?
因此,我正在写一个功能,该功能将元组作为参数,并为其做很多事情.这就是外观: def swap(self, location): if (location[0] = self.r or location[1] >= self.c): return False self.board[0][0] = self.board[location[0]][location[1]] self.board[location[0]][location[1]] = 0 self.empty = (location[0],location[1]) 我正在尝试使我的代码效率尽可能高效,因此,由于我没有修改location的值,因此将变量加载到寄存器(loc0 = location[0]; loc1 = location[1])中是否有意义(零 - 循环读
6 2023-05-24
编程技术问答社区
你能用汇编直接访问缓存吗?
缓存在效率方面是核心. 我知道缓存通常会自动发生. 但是,我想自己控制缓存使用情况,因为我认为我可以比某些不知道确切程序的启发式方法做得更好. 因此,我需要汇编指令才能直接移动访问或从缓存存储单元移动. 喜欢: movL1 address content 我知道有一些说明给出"缓存系统"的提示,但是我不确定这是否足够/从缓存订单. 是否有允许完整缓存控制的汇编器? 旁注:为什么要改进缓存: 考虑一个假设的CPU,带有1个寄存器和一个包含2个单元的缓存. 考虑以下两个程序: (其中x,y,z,a是存储单元) "START" "move 1 to x" "move 2 to y" "move 3 to z" "move 4 to a" "move z to x" "move y to x" "END" "START" "move 1 to x" "move 2 to y" "move 3 to z" "move 4 to
2 2023-05-24
编程技术问答社区