标签: inline-assembly

这个x86内联汇编在做什么?

我遇到了这段代码,需要了解它在做什么.它似乎只是宣布两个字节,然后什么都不做......

uint64_t x;
__asm__ __volatile__ (".byte 0x0f, 0x31" : "=A" (x));
Run Code Online (Sandbox Code Playgroud)

谢谢!

c x86 assembly inline-assembly

8
推荐指数
1
解决办法
1202
查看次数

当我从内联汇编中调用它们时,如何将参数传递给C++函数

所以,我希望能够从c ++ dll调用函数.出于某些原因,我想从我的C++代码中的__asm块中调用它们.我的问题是:我知道在调用函数之前,我必须按照函数调用约定指定的顺序在堆栈上推送它的参数.但是,我可以简单地做这样的事情:

int a=5;   
double b = 5.0;  
__asm{  
       push b 
       push a  
       call functionAddress  
}
Run Code Online (Sandbox Code Playgroud)

令我担心的是,我似乎记得汇编中的标准字大小是2字节,而C++中int的大小通常是4bytes,而double是8字节.所以,在上面的例子中,我真的推送每个变量的全部值,或只是前几个字节?如果上面的代码不正确,那么正确的方法是什么?另外,如果我们调用的函数返回一个double,那么这个值存储在哪里?我假设它不能在寄存器中,因为它只能存储32位(4字节).对这个混乱的任何帮助将非常感激:)

x86 callstack inline-assembly argument-passing

8
推荐指数
1
解决办法
3813
查看次数

如何在GCC C++中编写多行内联汇编代码?

这看起来不太友好:

__asm("command 1"
      "command 2"
      "command 3");
Run Code Online (Sandbox Code Playgroud)

我是否真的必须在每一行都加上双引号?

另外......因为多行字符串文字在GCC中不起作用,所以我也不能作弊.

assembly gcc inline-assembly

8
推荐指数
2
解决办法
4185
查看次数

如何在gcc内联汇编中使用全局变量

我试图使用这样的内联汇编,作为全局变量,但编译器通过对saved_sp的未定义引用给出错误.

__asm__ __volatile__ (
        "movq saved_sp, %rsp\n\t" );
Run Code Online (Sandbox Code Playgroud)

saved_sp被声明为static long saved_sp全局(对于一个文件).我在这做什么错?

c linux assembly gcc inline-assembly

8
推荐指数
2
解决办法
5433
查看次数

如何制作一个可以运行x86十六进制代码的C程序

我有一个十六进制代码数组,可以转换为汇编指令,我想在C中创建可以执行这些代码的程序.

unsigned char rawData[5356] = {
    0x4C, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0C, 0x00, 0x00,
    0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x2E, 0x74, 0x65, 0x78,
    0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xB4, 0x05, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x68, 0x08, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x60,
    0x2E, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, …
Run Code Online (Sandbox Code Playgroud)

c x86 inline-assembly

8
推荐指数
1
解决办法
2860
查看次数

在内联汇编的多个替代操作数约束之间进行选择时,GCC可以发出不同的指令助记符吗?

我正在尝试为GCC编写内联x86-64程序集以有效地使用MULQ指令.MULQ将64位寄存器RAX与另一个64位值相乘.另一个值可以是任何64位寄存器(甚至是RAX)或内存中的值.MULQ将产品的高64位放入RDX,将低64位放入RAX.

现在,很容易表达一个正确的mulq作为内联汇编:

#include <stdint.h>
static inline void mulq(uint64_t *high, uint64_t *low, uint64_t x, uint64_t y)
{
    asm ("mulq %[y]" 
          : "=d" (*high), "=a" (*low)
          : "a" (x), [y] "rm" (y)    
        );
}
Run Code Online (Sandbox Code Playgroud)

此代码是正确的,但不是最佳的.MULQ是可交换的,所以如果y恰好在RAX中,那么离开原点y并进行乘法是正确的.但GCC不知道这一点,因此会发出额外的指令将操作数移动到预先定义的位置.我想告诉GCC它可以将任一输入放在任一位置,只要一个在RAX中结束而MULQ引用另一个位置.GCC有一个这样的语法,称为"多个替代约束".注意逗号(但是整个asm()被破坏了;见下文):

asm ("mulq %[y]" 
      : "=d,d" (*high), "=a,a" (*low)
      : "a,rm" (x), [y] "rm,a" (y)    
    );
Run Code Online (Sandbox Code Playgroud)

不幸的是,这是错误的.如果GCC选择第二个替代约束,它将发出"mulq%rax".要清楚,请考虑以下功能:

uint64_t f()
{
    uint64_t high, low;
    uint64_t rax;
    asm("or %0,%0": "=a" (rax));
    mulq(&high, &low, 7, rax);
    return high;
}
Run Code Online (Sandbox Code Playgroud)

编译gcc -O3 -c -fkeep-inline-functions mulq.c,GCC发出这个程序集:

0000000000000010 …
Run Code Online (Sandbox Code Playgroud)

gcc inline-assembly

8
推荐指数
2
解决办法
1583
查看次数

以编程方式导致未定义的指令异常

我想在测试夹具的测试中引起ARM Cortex-M3未定义指令异常.IAR编译器支持这种内联汇编,如下所示:

asm("udf.w#0");

不幸的是,GNU CC内联汇编程序不知道NXP LPC177x8x的这个操作码.它写诊断:

ccw3kZ46.s:404: Error: bad instruction `udf.w #0'
Run Code Online (Sandbox Code Playgroud)

如何创建导致未定义指令异常的函数?

gcc arm cortex-m3 inline-assembly

8
推荐指数
4
解决办法
7096
查看次数

Retq指令,它返回哪里

我无法理解汇编指令retq返回的位置.

据我所知,当我的普通代码执行时,它会返回到堆栈中指定的地址.但它如何知道堆栈中的返回地址位于何处?

简而言之,它是否使用rbp或esp来查找堆栈中的地址?

stack-overflow inline-assembly

8
推荐指数
1
解决办法
1万
查看次数

英特尔的时间戳读取asm代码示例是否使用了两个以上的寄存器?

我正在研究使用x86 CPU中的时间戳寄存器(TSR)来测量基准性能.它是一个有用的寄存器,因为它以单调时间单位测量,不受时钟速度变化的影响.很酷.

这是一份英特尔文档,显示了使用TSR进行可靠基准测试的asm片段,包括使用cpuid进行管道同步.见第16页:

http://www.intel.com/content/www/us/en/embedded/training/ia-32-ia-64-benchmark-code-execution-paper.html

要读取开始时间,它说(我注释了一下):

__asm volatile (
    "cpuid\n\t"             // writes e[abcd]x
    "rdtsc\n\t"             // writes edx, eax
    "mov %%edx, %0\n\t" 
    "mov %%eax, %1\n\t"
    //
    :"=r" (cycles_high), "=r" (cycles_low)  // outputs
    :                                       // inputs
    :"%rax", "%rbx", "%rcx", "%rdx");       // clobber
Run Code Online (Sandbox Code Playgroud)

我不知道为什么暂存寄存器用来取的价值观edxeax.为什么不删除MOVS和读取TSR值右出的edxeax?像这样:

__asm volatile(                                                             
    "cpuid\n\t"
    "rdtsc\n\t"
    //
    : "=d" (cycles_high), "=a" (cycles_low) // outputs
    :                                       // inputs
    : "%rbx", "%rcx");                      // clobber     
Run Code Online (Sandbox Code Playgroud)

通过这样做,您可以保存两个寄存器,从而降低C编译器需要溢出的可能性.

我对吗?或者那些MOV在某种程度上是战略性的?

(我同意你确实需要临时寄存器来读取停止时间,因为在那种情况下指令的顺序是相反的:你有rdtscp,...,cpuid.cpuid指令破坏了rdtscp的结果).

谢谢

c benchmarking assembly inline-assembly rdtsc

8
推荐指数
1
解决办法
803
查看次数

你如何解释gcc对i386的IN,OUT指令的内联汇编约束?

据我所知,gcc内联汇编中使用的约束告诉gcc输入和输出变量必须(或必须),以便生成有效的汇编.正如精细手册所说,"对操作数放置的限制".

这是一个教程中特定的工作示例.

static inline uint8_t inb(uint16_t port)
{
    uint8_t ret;
    asm volatile ( "inb %1, %0"
                   : "=a"(ret)
                   : "Nd"(port) );
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

inb是AT&T语法 - 代表IN从I/O端口接收一个字节的i386 指令.

以下是本指令的规格,取自i386手册.需要注意的是端口号,从去0x00000xFFFF.

IN AL,imm8  // Input byte from immediate port into AL
IN AX,imm8  // Input word from immediate port into AX
IN EAX,imm8 // Input dword from immediate port into EAX
IN AL,DX    // Input byte from port DX into AL
IN AX,DX …
Run Code Online (Sandbox Code Playgroud)

x86 gcc g++ inline-assembly osdev

8
推荐指数
1
解决办法
349
查看次数