Tag: assembly

Cygwin gcc – asm错误:

我有一个用C编写的项目,最初是在Linux上完成的,但现在必须在Windows上完成。 部分代码在几个地方包含这一行 asm(“movl temp, %esp”); 但这会导致“未定义的引用’temp’”错误。 使用gcc 4.3.2编译器(在另一台机器上测试)在Linux上进行编译没有问题,这是我在Cygwin上的版本。 还有另一种方法可以完成这条线的工作吗?

如何防止ARM编译器5 armcc内联汇编程序中的LDM / STM指令扩展?

我正在尝试使用ARM编译器5 armcc编译的.c文件中的内联汇编中的STM / LDM指令生成AXI总线突发访问。 inline void STMIA2(uint32_t addr, uint32_t w0, uint32_t w1) { __asm { STMIA addr!, { w0, w1 } } } 但ARM编译器armcc用户指南第7.18段说:“所有LDM和STM指令都扩展为LDR和STR指令序列,效果相同。但是,编译器可能会在优化期间将单独的指令重新组合成LDM或STM。 “ 这就是实践中真正发生的事情,LDM / STM在某些情况下会扩展为一组LDR / STR,这些指令的顺序是任意的。 这会影响性能,因为我们使用的HW针对突发处理进行了优化。 这也打破了function正确性,因为我们使用的HW考虑了单词序列并忽略了偏移(但编译器认为改变指令的顺序是安全的)。 要解决这个问题,可以使用嵌入式汇编程序而不是内联汇编程序,但这会导致额外的函数调用 – 返回影响性能的因素。 所以我想知道是否有办法在不损失性能的情况下正确生成LDM / STM? 我们能够在GCC中做到这一点,但没有找到任何armcc的解决方案。 目标CPU:Cortex M0 +(ARMv6-M)。 编辑:从设备都是片上设备,大多数都是非内存设备。 对于支持突发访问区域的非内存从站的每个寄存器都保留了地址空间(例如[0x10000..0x10100]),我不完全确定为什么,也许CPU或总线不支持固定(非增量) )地址。 HW忽略该区域内的偏移。 例如,完整请求可以是16字节,并且完整请求的第一个字是第一个字写入的(即使偏移是非零)。

SPARC程序集参数中的printf格式说明符?

如何使用SPARC程序集获得相当于此C的内容: printf( “Hello, my name is %s.\n”, name ); 使用函数原型: void printName( const char* msg, const char* name ) 其中msg是“你好,我的名字是%s。\ n”。 我知道我可以使用.asciz在数据段中定义“Hello,my name is%s。\ n”而没有第一个参数msg,但有没有办法将字符串传递给一个具有%的汇编函数它的标识符? char *甚至可以采用格式标识符吗? 我尝试了以下但是我获得了核心转储。 C中的函数调用: char * msg = “Hello, my name is %s.\n”; char * name = “Foo”; printName( msg, name ); 部件: mov %i0, %o0 mov %i1, %o1 call […]

是否有专门设计用于编译1到1的C函数或宏,以及跨平台方式的位操作汇编指令?

我有一个涉及仿真的项目(如果你查看我的post历史,你会看到我到底有多远!)我正在寻找使用C进行伪二进制翻译并使用优化器和/或编译器使用C代码将我的switch语句内容编译为单个汇编指令,主要用于非常标准的指令,如mov s, add , SR和其他简单的位操作和算术指令。 我希望同时为ARM和x86-64这样做,尽可能少地在两个程序集中编写。 如果我所描述的东西不存在,那么我想知道是否有某种“汇编语言”可以用来编写我的代码然后将该汇编编译成x86-64和ARM。

ARM-C互通

我正在尝试一个简单的ARM-C互通程序。 这是代码: #include #include int Double(int a); extern int Start(void); int main(){ int result=0; printf(“in C main\n”); result=Start(); printf(“result=%d\n”,result); return 0; } int Double(int a) { printf(“inside double func_argument_value=%d\n”,a); return (a*2); } 汇编文件如下 – .syntax unified .cpu cortex-m3 .thumb .align .global Start .global Double .thumb_func Start: mov r10,lr mov r0,#42 bl Double mov lr,r10 mov […]

紧凑型AVX2寄存器,因此根据掩码选择的整数是连续的

在优化arrays压缩的问题中,最佳答案指出: 具有最新指令集的SSE / AVX寄存器允许更好的方法。 我们可以直接使用PMOVMSKB的结果,将其转换为PSHUFB之类的控制寄存器。 Haswell(AVX2)可以实现吗? 或者它需要AVX512的一种口味? 我有一个包含int32s的AVX2向量,以及一个比较结果的相应向量。 我想以某种方式将其改组,以便在掩码中设置相应msb的元素(比较true)在向量的低端是连续的。 我能看到的最好的是使用_mm256_movemask_ps / vmovmskps(没有* d变体?)得到一个掩码,然后在256 AVX2向量查找表中使用它来获得跨通道_m256_permutevar8x32_epi32 / vpermd的随机掩码

如何使用扩展的gcc程序集指定x87 FPU堆栈的破坏底部?

在我们的代码库中,我发现了这个代码片段,用于在x87上快速,朝向负无穷大1舍入: inline int my_int(double x) { int r; #ifdef _GCC_ asm (“fldl %1\n” “fistpl %0\n” :”=m”(r) :”m”(x)); #else // … #endif return r; } 我不是非常熟悉GCC扩展汇编语法,但是从我从文档中收集到的内容: r必须是一个记忆位置,我写回来的东西; x必须也是一个内存位置,数据来自哪里。 没有clobber规范,所以编译器可以放心,在代码片段的末尾,寄存器就像他离开时一样。 现在,提出我的问题:最终FPU堆栈是平衡的,但如果所有8个位置都已经在使用并且我已经溢出呢? 编译器如何知道它不能信任ST(7)离开它的位置? 应该添加一些clobber吗? 编辑我试图在clobber列表中指定st(7) ,它似乎影响codegen,现在我将等待对此事实的一些确认。 作为旁注:在glibc和MinGW中查看准系统lrint的实现我看到类似的东西 __asm__ __volatile__ (“fistpl %0” : “=m” (retval) : “t” (x) : “st”); 我们要求输入直接放在ST(0) (这避免了可能无用的fldl ); 什么是”st” clobber? 文档似乎只提到t (即堆栈的顶部)。 是的,它取决于当前的舍入模式,在我们的应用程序中应该总是“朝向负无穷大”。

-O2将printf(“%s \ n”,str)优化为puts(str)

用clang玩弄,我编译了一个包含这一行的C程序: printf(“%s\n”, argv[0]); 在没有优化的情况下进行编译时,在设置寄存器后,程序集输出称为printf : movq (%rcx), %rsi movq %rax, %rdi movb $0, %al callq _printf 我尝试使用clang -O2编译。 printf调用被替换为puts调用: movq (%rsi), %rdi callq _puts 虽然这在这种情况下非常有意义,但它提出了两个问题: 在优化编译中,函数调用替换的频率是多少? 这是频繁的还是stdio是个例外? 我可以为自己的库编写编译器优化吗? 我该怎么办?

执行从x86程序集编译的程序时出现分段错误?

我是汇编语言的新手,我必须实现一个函数,在我的例子中是sin(x),可以从C源文件调用。 我必须制作两个单独的文件:* .c和* .s在ubuntu上通过gcc编译时都很好,但是当程序执行时它会给出错误“Segmentation fault”… 编译我输入: gcc -c -o sinc.o sinx.c -g3 gcc -c -o sins.o sinx.s -g3 gcc -o sinx sinc.o sins.o -g3 当我启动程序时: ./sinx 它打印: …….insert x: 我把x放进去然后: segmentation fault 它停止了 这是两个文件: /*———————————–Sin[x]—————————————-*/ extern float Sin(float x); //extern assembly function #include //necessary libraries int main() // main function { float x; //allocate variable […]

C /汇编:如何更改CPU寄存器中的单个位?

我是软件故障注入领域的新研究员,目前我的最终目标是编写一段能够改变CPU寄存器中单个位的代码。 我在考虑用C语言(在代码中包含一些程序集调用)。 考虑到这一点,我在Stack Overflow中找到了这个很棒的线程和关于如何访问32位CPU寄存器内容的简单示例: 是否可以在C中访问32位寄存器? 这样,我就能编写这个简单的代码: #include int main() { register int value; register int ecx asm(“ecx”); printf(“Contents of ecx: %d\n”, ecx); asm(“movl %%ecx, %0;” : “=r” (value) : ); //Assembly: this stores the ecx value into the variable value printf(“Contents of value: %d\n”, value); return 0; } 这似乎是对这个主题的一个很好的介绍,那里提供的答案给了我很好的见解和信息来源(我已经阅读了GCC文档),但现在我需要进一步,即我需要了解怎么能我更改了CPU寄存器中单个位的内容(或者至少,要启动,更简单一些:如何更改CPU寄存器值?)。 如果有人能给我一个提示或告诉我最合适的来源,我会非常感激。 最好的,并提前感谢,João PS:不知道这是否有帮助,但我正在使用CentOS 6.5 32位系统(虽然CPU是64位,更准确地说是Intel Pentium双CPU […]