我很难用内联汇编来击败我的编译器.
什么是一个好的,非人为的函数示例,编译器很难制作真正,快速和简单的函数?但是使用内联汇编制作相对简单.
我在Linux下开始使用汇编程序.我已将以下代码保存为testasm.c
并使用以下代码进行编译:gcc testasm.c -otestasm
编译器回复:"'asm'中的不可能约束".
#include <stdio.h>
int main(void)
{
int foo=10,bar=15;
__asm__ __volatile__ ("addl %%ebx,%%eax"
: "=eax"(foo)
: "eax"(foo), "ebx"(bar)
: "eax"
);
printf("foo = %d", foo);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?(我从这里复制了这个例子.)
Debian Lenny,内核2.6.26-2-amd64
gcc版本4.3.2(Debian 4.3.2-1.1)
解决方案:
查看已接受的答案 - 似乎不再支持'modified'子句.
下面的代码只是在屏幕上显示一个消息框.
地址是硬编码的,以方便:
int main ()
{
asm("xorl %eax, %eax \n"
"xorl %ebx, %ebx \n"
"xorl %ecx, %ecx \n"
"xorl %edx, %edx \n"
"pushl %ecx \n" //$0x0
"pushl $0x20206c6c \n" //" ll"
"pushl $0x642e3233 \n" //"d.23"
"pushl $0x72657375 \n" //"resu"
"movl %esp, %ecx \n" //store "user32.dll" address in %ecx
"movl $0x7c801d7b, %ebx \n" //store address of LoadLibraryA in %ebx
"pushl %ecx \n"
"call *%ebx \n"
"movl $0xef30675e, %ecx \n"
"addl $0x11111111, %ecx \n"
"pushl %ecx \n"
"pushl $0x42656761 \n"
"pushl $0x7373654d …Run Code Online (Sandbox Code Playgroud) 我编写了一个程序,试图读取和写入控制寄存器.
程序编译很好,但是当即将执行内联汇编时,它会产生分段错误.
码:
void instructions(int val)
{
int i;
int value;
for(i = 0; i < val; i++)
__asm__("mov %cr0, %eax");
}
Run Code Online (Sandbox Code Playgroud)
我使用了GDB并逐步完成了每个装配线,并且mov %cr0,%eax正在发生分段故障.
谁知道什么是错的?
我正在为ARM Cortex-M3处理器开发自定义操作系统.要与我的内核交互,用户线程必须生成SuperVisor Call(SVC)指令(以前称为SWI,用于SoftWare中断).ARM ARM中该指令的定义是:

这意味着该指令需要立即参数,而不是寄存器值.
这使我很难以可读的方式构建我的界面.它需要如下代码:
asm volatile( "svc #0");
Run Code Online (Sandbox Code Playgroud)
当我更喜欢像
svc(SVC_YIELD);
Run Code Online (Sandbox Code Playgroud)
但是,我无法构造这个函数,因为SVC指令需要立即参数,当值通过寄存器传入时我无法提供.
对于后台,svc指令在内核中解码如下
#define SVC_YIELD 0
// Other SVC codes
// Called by the SVC interrupt handler (not shown)
void handleSVC(char code)
{
switch (code) {
case SVC_YIELD:
svc_yield();
break;
// Other cases follow
Run Code Online (Sandbox Code Playgroud)
这个案例陈述正在迅速失控,但我认为没有解决这个问题.欢迎任何建议.
我最初考虑过
__attribute__((naked)) svc(char code)
{
asm volatile ("scv r0");
}
Run Code Online (Sandbox Code Playgroud)
但是,当然,这不起作用,因为SVC需要寄存器参数.
蛮力企图解决问题看起来像:
void svc(char code)
switch (code) {
case 0:
asm volatile("svc #0");
break;
case 1:
asm …Run Code Online (Sandbox Code Playgroud) 我正在研究用LLVM编译的语言.只是为了好玩,我想做一些微基准测试.其中一个,我在一个循环中运行了一百万个sin/cos计算.在伪代码中,它看起来像这样:
var x: Double = 0.0
for (i <- 0 to 100 000 000)
x = sin(x)^2 + cos(x)^2
return x.toInteger
Run Code Online (Sandbox Code Playgroud)
如果我使用以下形式使用LLVM IR内联汇编来计算sin/cos:
%sc = call { double, double } asm "fsincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}" (double %"res") nounwind
Run Code Online (Sandbox Code Playgroud)
这比分别使用fsin和fcos而不是fsincos更快.但是,它比我分别调用llvm.sin.f64and llvm.cos.f64intrinsics,编译调用C math lib函数要慢,至少使用我正在使用的目标设置(x86_64启用了SSE).
似乎LLVM在单/双精度FP之间插入一些转换 - 这可能是罪魁祸首.这是为什么?对不起,我是大会上的新手:
.globl main
.align 16, 0x90
.type main,@function
main: # @main
.cfi_startproc
# BB#0: # %loopEntry1
xorps %xmm0, %xmm0
movl $-1, %eax
jmp .LBB44_1
.align 16, 0x90
.LBB44_2: # %then4
# in Loop: Header=BB44_1 Depth=1 …Run Code Online (Sandbox Code Playgroud) 我阅读了FastMM4的源代码,并注意到这个有趣的功能
function GetThreadID: Cardinal;
{$ifdef 32Bit}
asm
mov eax, FS:[$24]
end;
{$else}
begin
Result := GetCurrentThreadID;
end;
{$endif}
Run Code Online (Sandbox Code Playgroud)
我已经测试了它,它有效,所以我的问题是任何解释为什么它有效?
我在编译期间收到以下错误:
error: ‘asm’ undeclared (first use in this function)
EXCHANGE( s, *(a) );
^
Run Code Online (Sandbox Code Playgroud)
在头文件中调用宏,如下所示:
EXCHANGE( s, *(a) );
Run Code Online (Sandbox Code Playgroud)
并且宏的实际定义如下:
#define EXCHANGE(R,M) asm volatile ( "xchg %1, %0" : "+m" (M), "+r" (R) )
Run Code Online (Sandbox Code Playgroud)
宏调用和定义存在于同一个头文件中.出了什么问题?
我正在使用CMAKE来构建项目,CFLAGS如下:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-braces")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat=2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wswitch-default")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpointer-arith")
#-Wno-deprecated-declarations to suppress the deprecation errors with newer version of JSON-C
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wbad-function-cast") …Run Code Online (Sandbox Code Playgroud) 对于我的项目,我必须使用内联汇编指令(如rdtsc)来计算某些C/C++指令的执行时间.
以下代码似乎适用于英特尔,但不适用于ARM处理器:
{unsigned a, d;asm volatile("rdtsc" : "=a" (a), "=d" (d)); t0 = ((unsigned long)a) | (((unsigned long)d) << 32);}
//The C++ statement to measure its execution time
{unsigned a, d;asm volatile("rdtsc" : "=a" (a), "=d" (d)); t1 = ((unsigned long)a) | (((unsigned long)d) << 32);}
time = t1-t0;
Run Code Online (Sandbox Code Playgroud)
我的问题是:
如何在ARM处理器上编写类似于上面的内联汇编代码(计算指令的执行经过时间)?
亲爱的Assembly/C++ dev,
问题是:传播两个ASM块之间的进位(或任何标志)是现实的还是完全疯狂的,即使它有效?
几年前,我为低于512位的大型算术开发了一个整数库(在编译时).我此时没有使用GMP,因为对于这种规模,GMP由于内存分配而变慢,并且模型选择二进制表示工作台.
我必须承认我创建了我的ASM(字符串块)使用BOOST_PP,它不是非常光荣(好奇的看看它vli).图书馆运作良好.
但是我注意到,此时不可能在两个ASM内联块之间传播状态寄存器的进位标志.这是合乎逻辑的,因为对于编译器在两个块之间生成的任何助记符,寄存器被复位(mov指令除外(来自我的汇编知识)).
昨天我有一个想法,传播两个ASM块之间的进位有点棘手(使用递归算法).它工作,但我认为我很幸运.
#include <iostream>
#include <array>
#include <cassert>
#include <algorithm>
//forward declaration
template<std::size_t NumBits>
struct integer;
//helper using object function, partial specialization is forbiden on functions
template <std::size_t NumBits, std::size_t W, bool K = W == integer<NumBits>::numwords>
struct helper {
static inline void add(integer<NumBits> &a, const integer<NumBits> &b){
helper<NumBits, integer<NumBits>::numwords>::add(a,b);
}
};
// first addition (call first)
template<std::size_t NumBits, std::size_t W>
struct helper<NumBits, W, 1> {
static …Run Code Online (Sandbox Code Playgroud)