Tag: 汇编

在Fortran代码中调用C函数/子例程

我正在尝试编译和链接调用c子例程的Fortran代码: Fortran代码: program adder integer a,b a=1 b=2 call addnums(a,b) stop end program C代码: void addnums( int* a, int* b ) { int c = (*a) + (*b); /* convert pointers to values, then add them */ printf(“sum of %i and %i is %i\n”, (*a), (*b), c ); } 我使用以下命令在Windows环境中编译和链接。 ifort -c adder.f cl -c […]

使用`GCCs`预处理器作为汇编程序

有各种开源组装商,如gas , nasm和yasm 。 它们具有不同的pseudo-ops和macro语法。 对于许多开源项目,汇编程序经过预处理以替换常量和平台条件。 假设您可以使用所有当前attributes和#pragmas ,排除翻译性能(编译/汇编到二进制时间), gcc会创建汇编程序有什么限制? 我不是在谈论内联汇编 。 #define MOV(RA,RB) (OXFEB10000UL | RA << 16 | RB) #define ADD(RA,RB) (OXFEB20000UL | RA << 16 | RB) #define RET (OXFEB7ABCDUL) unsigned long add4[] __attribute(section(".text")) = { ADD(R0,R1), ADD(R2,R3), MOV(R1,R2), ADD(R0,R1), RET() }; 我相信使用指针算法可以进行模拟. 和其他labels 。 也许这是一个XY问题 ; 我试图理解为什么有这么多assembly工。 似乎所有事情都可以由预处理器完成,而汇编程序实际上是程序员的首选; 或者我缺少技术限制。 我想这可能与’你可以使用汇编程序做的事情有关,你无法用shell代码做’。 编辑:我已将其从C重新标记为编译器 。 […]

仅使用恒定移位来模拟可变位移?

我试图找到一种方法来执行间接左移/右移操作而不实际使用变量移位操作或任何分支。 我正在研究的特定PowerPC处理器有一个怪癖,即按常数立即移位,就像 int ShiftByConstant( int x ) { return x << 3 ; } 是快速的,单操作的,超标量的,而变量的变换,如 int ShiftByVar( int x, int y ) { return x << y ; } 是一个微编码操作,需要7-11个周期才能执行,而管道的其余部分都停止运行 。 我想做的是找出哪些非微码整数PPC操作sraw解码然后单独发出它们。 这对于sraw本身的延迟没有帮助 – 它将用6替换一个op – 但是在这六个操作之间我可以将一些工作双重调度到其他执行单元并获得净增益。 我似乎无法找到μopssraw解码到的任何地方 – 有没有人知道如何用一系列常量移位和基本整数运算替换变量位移? (for循环或开关或其中带有分支的任何东西都不起作用,因为分支惩罚甚至比微码惩罚更大。) 这不需要在assembly中回答; 我希望学习算法而不是特定的代码,所以用C语言或高级语言甚至伪代码的答案都会非常有用。 编辑:我应该补充一些说明: 我甚至不担心可移植性 PPC具有条件移动,因此我们可以假设存在无分支内部函数 int isel(a,b,c){return a> = 0? b:c; } (如果你写出一个做同样事情的三元组,我会明白你的意思) 整数乘法也是微编码的,甚至比sraw慢。 […]

在Linux内核中使用修饰符“P”和约束“p”超过“m”的gcc内联汇编

我正在阅读Linux内核源代码(3.12.5 x86_64)以了解如何处理进程描述符。 我发现获取当前进程描述符我可以使用current_thread_info()函数,其实现如下: static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; ti = (void *)(this_cpu_read_stable(kernel_stack) + KERNEL_STACK_OFFSET – THREAD_SIZE); return ti; } 然后我查看了this_cpu_read_stable() : #define this_cpu_read_stable(var) percpu_from_op(“mov”, var, “p” (&(var))) #define percpu_from_op(op, var, constraint) \ ({ \ typeof(var) pfo_ret__; \ switch (sizeof(var)) { \ … case 8: \ asm(op “q “__percpu_arg(1)”,%0″ \ : “=r” […]

如何在C或Assembly中修改Stack上的返回地址

如您所知,当子程序调用时,当前PC(程序计数器)值存储在堆栈中。 我想在子程序中修改它,如下所示。 我希望使用gcc编译器在Intel Core-i7 3632QM上执行此操作。 void main() { foo(); } void foo() { pop return address from stack; modify return address; push it to stack; }

如何在C中使用asm添加两个64位数时访问进位标志

是的,谢谢你的工作。 @PeterCordes。 __int128有效。 但是还有一件事,正如你所说的使用多精度算法的内在函数,即C中的_addcarry_u64 ,使用头文件immintrin.h我有以下代码 #include #include #include #include unsigned char _addcarry_u64(unsigned char c_in, uint64_t src1, uint64_t src2,uint64_t *sum); int main() { unsigned char carry; uint64_t sum; long long int c1=0,c2=0; uint64_t a=0x0234BDFA12CD4379,b=0xA8DB4567ACE92B38; carry = _addcarry_u64(0,a,b,&sum); printf(“sum is %lx and carry value is %un”,sum,carry); return 0; } 你能指出我的错误吗? 我正在获得对_addcarry_u64未定义引用。 一些快速谷歌没有回答问题,如果要使用任何其他头文件或它与gcc不兼容,为什么这样 最初我有这个代码用于添加两个64位数字: static __inline int is_digit_lessthan_ct(digit_t […]

在intel 64bit机器上启用/禁用缓存:CD位始终设置?

我试图在Xen中禁用我的机器Intel(R)Xeon(R)CPU E5-1650 v2 @ 3.50GHz的所有级别的缓存。 我写了一个工具来调用以下汇编代码来禁用/启用缓存并显示CR0寄存器的值。 case XENMEM_disable_cache: __asm__ __volatile__( “pushq %%rax\n\t” “movq %%cr0,%%rax\n\t” “orq $0x40000000,%%rax\n\t” “movq %%rax,%%cr0\n\t” “movq %%cr0, %0\n\t” “wbinvd\n\t” “popq %%rax” : “=r”(cr0) : :); // gdprintk(XENLOG_WARNING, “gdprintk:XENMEM_disable_cache disable cache! // TODO IMPLEMENT\n”); printk(“printk: disable cache! cr0=%#018lx\n”, cr0); rc = 0; break; case XENMEM_enable_cache: __asm__ __volatile__( “pushq %%rax\n\t” “movq %%cr0,%%rax\n\t” “andq $0xffffffffbfffffff,%%rax\n\t” […]

如何使用内联汇编指定直接浮点数?

当我尝试编译此代码时: #include main(int argc, char *argv[]) { double y = 0; __asm__ (“fldl $150;” “fsqrt;” “fstl %0;” : : “g” (y) ); printf(“%f\n”, y); return 0; } 我收到此错误: sqrt.c: Assembler messages: sqrt.c:6: Error: suffix or operands invalid for `fld’ 为什么这不起作用? 为什么我不能将数字“150”推入堆栈进行浮点运算?

X86程序集 – 处理IDIV指令

我目前正在编写一个简单的C编译器,它将.c文件作为输入并生成汇编代码(X86,AT&T语法)。 一切都很好,但是当我尝试执行IDIVQ指令时,我得到一个浮点exception。 这是我的意见: int mymain(int x){ int d; int e; d = 3; e = 6 / d; return e; } 这是我生成的代码: mymain: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 movq %rdi, -40(%rbp) movq $3, -8(%rbp) movq $6, %rax movq -8(%rbp), %rdx movq %rdx, %rbx idivq %rbx movq […]

为什么初始化这样的二维数组会更糟​​?

for(int i = 0; i<100; i++) for(int j = 0; j<100; j++) array[j][i] = 0; // array[i][j] = 0; 我的教授说,第一种方式初始化二维数组要比第二种方式要昂贵得多。 有人可以解释引擎盖下面发生了什么事情吗? 或者,这两种初始化方法是否具有相同的性能?