标签: inline-assembly

如何在GCC x86内联汇编中使用地址常量

GCC工具链默认使用AT&T汇编语法,但可通过该.intel_syntax指令获得对Intel语法的支持.

此外,AT和T以及英特尔语法都有a prefix和a noprefix版本,不同之处在于它们是否需要使用%sigil 为寄存器名称添加前缀.

根据存在的指令,地址常量的格式会发生变化.

我们考虑以下C代码

*(int *)0xdeadbeef = 0x1234;
Run Code Online (Sandbox Code Playgroud)

使用objdump -d,我们发现它被编译为以下汇编程序指令

movl $0x1234,0xdeadbeef
Run Code Online (Sandbox Code Playgroud)

由于没有涉及到寄存器,这对于正确的语法.att_syntax prefix.att_syntax noprefix,即.嵌入在C代码中,它们看起来像这样

__asm__(".att_syntax prefix");
__asm__("movl $0x1234,0xdeadbeef");

__asm__(".att_syntax noprefix");
__asm__("movl $0x1234,0xdeadbeef");
Run Code Online (Sandbox Code Playgroud)

您可以选择用括号括起地址常量,即.

__asm__("movl $0x1234,(0xdeadbeef)");
Run Code Online (Sandbox Code Playgroud)

也会奏效.

将sigil添加到普通地址常量时,代码将无法复制

__asm__("movl $0x1234,$0xdeadbeef"); // won't compile
Run Code Online (Sandbox Code Playgroud)

当用paranthesis围绕这个表达式时,编译器将发出错误的代码而不发出警告,即

__asm__("movl $0x1234,($0xdeadbeef)"); // doesn't warn, but doesn't work!
Run Code Online (Sandbox Code Playgroud)

这将错误地发出指令

movl $0x1234,0x0
Run Code Online (Sandbox Code Playgroud)

在Intel模式下,PTR如果可能存在歧义,则地址常量必须以段寄存器为前缀,以及操作数大小和标志.在我的机器上(采用Windows XP和当前MinGW和Cygwin GCC版本的英特尔双核笔记本电脑),ds默认使用该寄存器.

常量周围的方括号是可选的.如果省略了段寄存器,但是括号存在,也可以正确识别地址常量.但是,忽略寄存器会在我的系统上发出警告.

prefix模式中,段寄存器必须以前缀为前缀%,但仅使用括号仍然有效.这些是生成正确指令的不同方法:

__asm__(".intel_syntax noprefix");
__asm__("mov DWORD PTR ds:0xdeadbeef,0x1234");
__asm__("mov …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc inline-assembly

9
推荐指数
1
解决办法
7767
查看次数

在C/C++中使用内联汇编

我正在尝试使用内联汇编...我读过这个页面http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx但我无法理解传递给我的函数的参数.

我正在写一个C写的例子..这是我的函数头:

write2(char *str, int len){
}
Run Code Online (Sandbox Code Playgroud)

这是我的汇编代码:

global write2
write2:
    push ebp
    mov ebp, esp
    mov eax, 4      ;sys_write
    mov ebx, 1      ;stdout
    mov ecx, [ebp+8]    ;string pointer
    mov edx, [ebp+12]   ;string size
    int 0x80        ;syscall
    leave
    ret
Run Code Online (Sandbox Code Playgroud)

我该怎么做才能将代码传递给C函数...我正在做这样的事情:

write2(char *str, int len){
    asm ( "movl 4, %%eax;"
          "movl 1, %%ebx;"
          "mov %1, %%ecx;"
          //"mov %2, %%edx;"
          "int 0x80;"
           :
           : "a" (str), "b" (len)
    );
}
Run Code Online (Sandbox Code Playgroud)

那是因为我没有输出变量,所以我该如何处理呢?此外,使用此代码:

global main
main:
    mov ebx, 5866       ;PID
    mov ecx, …
Run Code Online (Sandbox Code Playgroud)

c linux x86 assembly inline-assembly

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

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

当我尝试编译此代码时:

#include <stdio.h>

main(int argc, char *argv[]) {
   double y = 0;

   __asm__ ("fldl $150;"
            "fsqrt;"
            "fstl %0;" : : "g" (y) );

   printf("%f\n", y);


   return 0;
}
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

sqrt.c: Assembler messages:
sqrt.c:6: Error: suffix or operands invalid for `fld'
Run Code Online (Sandbox Code Playgroud)

为什么这不起作用?为什么我不能将数字"150"推入堆栈进行浮点运算?

c assembly gcc inline-assembly x87

9
推荐指数
2
解决办法
6364
查看次数

在GCC内联汇编中包装CMPXCHG8B的正确方法,32位

我正在尝试为ia32编写GCC内联asm for CMPXCHG8B.不,我不能用__sync_bool_compare_and_swap.它必须使用和不使用-fPIC.

到目前为止,我所做的最好(编辑:毕竟不起作用,详见下面我自己的答案)

register int32 ebx_val asm("ebx")= set & 0xFFFFFFFF;
asm ("lock; cmpxchg8b %0;"
     "setz %1;"
     : "+m" (*a), "=q" (ret), "+A" (*cmp)
     : "r" (ebx_val), "c" ((int32)(set >> 32))
     : "flags")
Run Code Online (Sandbox Code Playgroud)

但是我不确定这实际上是否正确.

"b" ((int32)(set & 0xFFFFFFFF))由于PIC,我不能为ebx_val 做,但register asm("ebx")编译器接受了显然变量.

BONUS:ret变量用于分支,因此代码最终看起来像这样:

cmpxchg8b [edi];
setz cl;
cmp cl, 0;
je foo;
Run Code Online (Sandbox Code Playgroud)

任何想法如何描述输出操作数,使它成为:

cmpxchg8b [edi]
jz foo
Run Code Online (Sandbox Code Playgroud)

谢谢.

x86 assembly gcc inline-assembly

9
推荐指数
1
解决办法
2593
查看次数

转换帮助:__ asm__ __volatile__

我想将C的outb函数移植到D.

static __inline void outb (unsigned char value, unsigned short int port)
{
    __asm__ __volatile__ ("outb %b0,%w1"
                          :
                          :
                         "a" (value),
                          "Nd" (port));
}
Run Code Online (Sandbox Code Playgroud)

这是D版.

extern(C) 
{
    void outb (ubyte value, ushort port)
    {
        // I couldn't figure out this part
   }

}
Run Code Online (Sandbox Code Playgroud)

这些是关于该主题的一些链接.

D内联汇编程序

http://dlang.org/iasm.html

GCC-内联汇编-HOWTO

http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

但我不懂汇编语言,所以我需要一些帮助.任何帮助,将不胜感激.谢谢.

c assembly d inline-assembly

9
推荐指数
2
解决办法
1154
查看次数

在gcc内联x86_64汇编中约束r10寄存器

我正在编写一个非常轻量级的libc替换库,以便我可以更好地理解内核 - 应用程序界面.第一项任务显然是使一些系统调用包装器到位.我已经成功地获得了1到3个参数包装器,但我正在努力使用4参数varient.这是我的出发点:

long _syscall4(long type, long a1, long a2, long a3, long a4)
{
    long ret;
    asm
    (
        "syscall"
        : "=a"(ret)
        : "a"(type), "D"(a1), "S"(a2), "d"(a3), "r10"(a4)
        : "c", "r11"
    );
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

编译器给我以下错误:

error: matching constraint references invalid operand number
Run Code Online (Sandbox Code Playgroud)

我的_syscall3函数工作正常但不使用r10或有一个clobber列表.

有什么想法吗?

c gcc x86-64 system-calls inline-assembly

9
推荐指数
2
解决办法
1618
查看次数

Linux内核程序集和逻辑

我的问题有些奇怪,但我会尽力解释.

看看linux内核的语言,我得到了C和汇编,即使我读了一篇文章说[引用] Unix的第二次迭代完全用C语言编写[/ quote]

我认为这是误导性的,但当我说内核有汇编代码时,我得到了两个问题

  1. 内核中有哪些汇编文件,它们的用途是什么?
  2. 程序集依赖于体系结构,因此如何在多个CPU体系结构上安装linux

如果Linux内核真的完全用C语言编写,那么它是如何获得编译所需的GCC的呢?

我做了一个完整的find / -name *.s ,只是在/ usr/src/linux-headers- `uname -r/中的某处有一个汇编文件(asm-offset.s)

不知怎的,我不认为这有助于GCC的工作,那么linux如何在没有组装的情况下工作,或者如果它使用汇编它在哪里以及它如何在依赖于arch时稳定.

提前致谢

linux assembly kernel inline-assembly

9
推荐指数
2
解决办法
5966
查看次数

在内联汇编的多个替代操作数约束之间进行选择时,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
查看次数

内联asm是ANSI C标准的一部分吗?

我一直认为这是因为许多IDE和语法突出显示工具没有在C中突出显示ASM,但它们总是使用C++.内联汇编是否是C标准(ANSII或ISO)的一部分?

c c++ inline-assembly

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

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

我想在测试夹具的测试中引起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
查看次数

标签 统计

inline-assembly ×10

assembly ×6

c ×6

gcc ×6

linux ×2

x86 ×2

arm ×1

c++ ×1

cortex-m3 ×1

d ×1

kernel ×1

system-calls ×1

x86-64 ×1

x87 ×1