相关疑难解决方法(0)

GCC 内联程序集错误:“'int' 的操作数大小不匹配”

首先,如果有人知道标准 C 库的一个函数,该函数无需查找二进制零即可打印字符串,但需要绘制字符数,请告诉我!

否则,我有这个问题:

void printStringWithLength(char *str_ptr, int n_chars){

asm("mov 4, %rax");//Function number (write)
asm("mov 1, %rbx");//File descriptor (stdout)
asm("mov $str_ptr, %rcx");
asm("mov $n_chars, %rdx");
asm("int 0x80");
return;

}
Run Code Online (Sandbox Code Playgroud)

GCC 将以下错误告知“int”指令:

"Error: operand size mismatch for 'int'"
Run Code Online (Sandbox Code Playgroud)

有人可以告诉我这个问题吗?

c assembly gcc x86-64 inline-assembly

3
推荐指数
1
解决办法
6387
查看次数

Android 中的 SYSCALL_INLINE

我需要在 Android NDK 内部使用 syscall 来防止挂钩包装函数。在 Linux 中有像 SYSCALL_INLINE 这样的宏,它允许在没有包装函数的情况下使用系统调用。因此宏将系统调用汇编代码直接嵌入到项目中。

我在 Android NDK 中找不到类似的宏。

也许我可以像这样编写自己的函数;https://git.busybox.net/uClibc/tree/libc/sysdeps/linux/arm/syscall.c

但我需要有相同功能的 arm、arm_64、x86 和 x86_64 版本。

你能帮助我吗?我怎样才能找到解决办法?

assembly android multiplatform system-calls android-ndk

3
推荐指数
1
解决办法
1540
查看次数

内联汇编中访问thread_local变量

我正在处理一些具有使用内联汇编的优化版本的C ++代码。优化版本显示的行为不是线程安全的,可以追溯到3个全局变量,可以从程序集内部进行广泛访问。

__attribute__ ((aligned (16))) unsigned int SHAVITE_MESS[16];
__attribute__ ((aligned (16))) thread_local unsigned char SHAVITE_PTXT[8*4];
__attribute__ ((aligned (16))) unsigned int SHAVITE_CNTS[4] = {0,0,0,0};
Run Code Online (Sandbox Code Playgroud)

...

asm ("movaps xmm0, SHAVITE_PTXT[rip]");
asm ("movaps xmm1, SHAVITE_PTXT[rip+16]");
asm ("movaps xmm3, SHAVITE_CNTS[rip]");
asm ("movaps xmm4, SHAVITE256_XOR2[rip]");
asm ("pxor   xmm2,  xmm2");
Run Code Online (Sandbox Code Playgroud)

我天真地认为解决此问题的最简单方法是使变量成为thread_local,但这会导致程序集中出现段错误-似乎程序集不知道变量是否是线程局部的?

我在一个小thread_local测试用例的汇编中进行了研究,以查看gcc如何处理它们,mov eax, DWORD PTR fs:num1@tpoff并尝试修改代码以执行相同的操作:

asm ("movaps xmm0, fs:SHAVITE_PTXT@tpoff");
asm ("movaps xmm1, fs:SHAVITE_PTXT@tpoff+16");
asm ("movaps xmm3, fs:SHAVITE_CNTS@tpoff");
asm ("movaps xmm4, fs:SHAVITE256_XOR2@tpoff");
asm ("pxor   xmm2,  xmm2");
Run Code Online (Sandbox Code Playgroud)

如果所有变量也都是thread_local,则该方法有效,它也与参考实现(非汇编)匹配,因此看起来可以成功工作。但是,这似乎是特定于CPU的,如果我看一下-m32我用get 进行编译的输出mov eax, DWORD PTR …

c++ x86 assembly gcc thread-local-storage

3
推荐指数
1
解决办法
194
查看次数

在 asm volatile 内联 PTX 指令中,为什么还要指定“内存”副作用?

考虑以下来自 CUDA 的Inline PTX Assebly指南 (v10.2) 的摘录:

编译器假定asm()语句除了更改输出操作数之外没有副作用。为确保在生成 PTX 期间不会删除或移动 asm,您应该使用 volatile 关键字,例如:

asm volatile ("mov.u32 %0, %%clock;" : "=r"(x));
Run Code Online (Sandbox Code Playgroud)

通常写入的任何内存都将被指定为输出操作数,但如果对用户内存有隐藏的副作用(例如,通过操作数间接访问内存位置),或者如果您想停止任何内存优化在生成 PTX 期间执行的 asm() 语句周围,您可以在第三个冒号后添加“内存”clobbers 规范...

这听起来像是两者 volatile:: "memory"旨在表明内存中的副作用。现在,当然,可能存在非记忆副作用(例如 for trap;)。但是 - 当我使用 时volatile,也指定:: "memory")不是没用/没有意义吗?

稍微相关:当使用内联 PTX asm() 指令时,'volatile' 有什么作用?

redundancy cuda inline-assembly language-lawyer ptx

3
推荐指数
1
解决办法
176
查看次数

通过“LD_PRELOAD”替换“malloc”、“calloc”、“realloc”和“free”时出现分段错误

背景

我尝试更换malloc(3)/ calloc(3)/ realloc(3)/free(3)通过LD_PRELOAD环境变量。我尝试使用静态链接的自定义函数,它们工作得很好。

但是,当我将它作为共享库附加到 时LD_PRELOAD,它总是会导致段错误。


关于功能的简短技术说明

  • 我使用 Linux x86-64mmap(2)munmap(2)syscall for malloc(3)and free(3)
  • calloc(3)只是对malloc(3)乘法溢出检查的调用。
  • realloc(3)电话malloc(3),然后复制旧的数据到新分配的内存和取消映射旧内存。

问题

  • 我的方法有什么问题,以至于它总是导致段错误?
  • 我该如何调试它(gdb 和 valgrind 也有段错误)?
  • 我在这里错过了什么?

笔记

我完全意识到mmap每次malloc调用时总是使用是一个坏主意,尤其是对于性能而言。我只想知道为什么我的方法不起作用。


输出

ammarfaizi2@integral:~$ gcc -shared mem.c -O3 -o my_mem.so
ammarfaizi2@integral:~$ LD_PRELOAD=$(pwd)/my_mem.so ls
Segmentation fault (core dumped)
ammarfaizi2@integral:~$ LD_PRELOAD=$(pwd)/my_mem.so cat
Segmentation fault (core dumped)
ammarfaizi2@integral:~$ LD_PRELOAD=$(pwd)/my_mem.so w
Segmentation fault (core …
Run Code Online (Sandbox Code Playgroud)

c linux malloc x86-64 ld-preload

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

GCC 优化会损坏系统调用存根

GCC 的最新版本(包括版本 12)实现了过程间分析,该分析会严重损坏 ARM/Thumb 上系统调用存根的以下(仅限 GCC)代码。

typedef struct { int sender; int arg; } message;

#define syscall(op)  asm volatile ("svc %0" :: "i"(op))

#define SYS_SEND 9

#define NOINLINE __attribute((noinline))

void NOINLINE send(int dest, int type, message *msg)
{
    syscall(SYS_SEND);
}

void send_int(int d, int t, int v)
{
    message msg;
    msg.arg = v;
    send(d, t, &msg);
}
Run Code Online (Sandbox Code Playgroud)

目的是操作系统的陷阱处理程序将send通过访问参数寄存器的保存值来找到三个参数r0——r2在陷阱的异常帧中。问题显然是优化器在查看 的主体时send认为其消息参数的字段未被使用。msg.arg因此,主体中对 的赋值send_int被删除。这是通过编译上述源代码揭示的

arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -O -g -Wall -ffreestanding -c …
Run Code Online (Sandbox Code Playgroud)

c optimization gcc arm inline-assembly

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

at&t asm inline c ++问题

我的守则

const int howmany = 5046;
char buffer[howmany];
    asm("lea     buffer,%esi"); //Get the address of buffer
    asm("mov     howmany,%ebx");         //Set the loop number
    asm("buf_loop:");                      //Lable for beginning of loop
    asm("movb     (%esi),%al");             //Copy buffer[x] to al
    asm("inc     %esi");                   //Increment buffer address
    asm("dec     %ebx");                   //Decrement loop count
    asm("jnz     buf_loop");              //jump to buf_loop if(ebx>0)
Run Code Online (Sandbox Code Playgroud)

我的问题

我正在使用gcc编译器.出于某种原因,我的缓冲区/ howmany变量在我的asm眼中是不确定的.我不知道为什么.我只想将缓冲区数组的起始地址移动到esi寄存器中,在将每个元素复制到al寄存器时循环"howmany"次.

c x86 assembly gcc inline-assembly

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

rep_movsl的Clobber列表

我正在尝试使用内联汇编的示例:http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html 但是有些事让我感到困惑:

  • 关于clobber的行为
    Clobbering实质上告诉GCC不信任指定寄存器/存储器中的值.

    "好吧,当GCC能够确切地知道你之前和之后对寄存器做了什么时,这确实很有帮助......如果你告诉它将(x + 1)放入寄存器中,它甚至足够聪明. ,如果你没有破坏它,后来C代码引用(x + 1),并且它能够保持该寄存器空闲,它将重用计算.哇."

这一段是否意味着clobbering将禁用常见的子表达式消除?

  • 关于clobber列表的教程中存在一些不一致:
    对于输入/输出列表中指定的寄存器,不需要将它们放入clobber列表中,因为GCC知道; 但是在关于rep_movsl(或rep_stosl)的示例中:

    asm("cld \n\t""rep \n\t""stosl":/*无输出寄存器*/:"c"(计数),"a"(fill_value),"D"(dest):" %ecx","%edi");

虽然"S,D,c"在输出操作数中,但它们再次被列为破坏.我在C中尝试了一个简单的片段:

#include<stdio.h>
int main()
{
  int a[] = {2, 4, 6};
  int b[3];
  int n = 3;
  int v = 12;
  asm ("cld\n\t"
       "rep\n\t"
       "movsl"
       :
       : "S" (a), "D" (b), "c" (n)
       : );
//     : "%ecx", "%esi", "%edi" );
  printf("%d\n", b[1]);
}
Run Code Online (Sandbox Code Playgroud)

如果我使用评论的clobber列表,GCC会抱怨:

ac:8:3:错误:在重新加载'asm'ac时,无法在类'CREG'中找到寄存器:8:3:错误:'asm'操作数有不可能的约束

如果我使用空的clobber列表,它将编译并输出为4.

c x86 assembly gcc inline-assembly

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

gcc arm 在系统调用之前优化掉参数

我正在尝试使用 gcc arm 在 arm7tdmi-s 上实现一些“OSEK-Services”。不幸的是,提高优化级别会导致“错误”的代码生成。我不明白的主要事情是编译器似乎忽略了过程调用标准,例如通过将参数移动到寄存器 r0-r3 将参数传递给函数。我知道函数调用可以内联,但参数仍然需要在寄存器中才能执行系统调用。

考虑以下代码来演示我的问题:

unsigned SysCall(unsigned param)
{
    volatile unsigned ret_val;
    __asm __volatile
    (
        "swi 0          \n\t"    /* perform SystemCall */
        "mov %[v], r0   \n\t"    /* move the result into ret_val */
        : [v]"=r"(ret_val) 
        :: "r0" 
    );

    return ret_val;              /* return the result */
}

int main()
{
    unsigned retCode;
    retCode = SysCall(5); // expect retCode to be 6 when returning back to usermode
}
Run Code Online (Sandbox Code Playgroud)

我在汇编中编写了顶级软件中断处理程序,如下所示:

.type   SWIHandler, %function
.global SWIHandler
SWIHandler:

    stmfd   sp! , …
Run Code Online (Sandbox Code Playgroud)

c assembly arm system-calls inline-assembly

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

在内联 C 汇编中执行系统调用会导致段错误

我最近涉足低级编程,并希望制作一个somesyscall接受(CType rax, CType rbx, CType rcx, CType rdx). struct CType 看起来像:

/*
    TYPES:
        0 int
        1 string
        2 bool
*/
typedef struct {
    void* val;
    int typev;
} CType;
Run Code Online (Sandbox Code Playgroud)

该功能有点混乱,但理论上应该可以工作:

#include <errno.h>
#include <stdbool.h>
#include "ctypes.h"

//define functions to set registers
#define seteax(val) asm("mov %0, %%rax" :: "g" (val) : "%rax")
#define setebx(val) asm("mov %0, %%rbx" :: "g" (val) : "%rbx")
#define setecx(val) asm("mov %0, %%rcx" :: "g" (val) : "%rcx")
#define setedx(val) asm("mov %0, %%rdx" …
Run Code Online (Sandbox Code Playgroud)

c ubuntu assembly system-calls

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

将内联汇编代码插入 C 函数 - I/O 问题

我正在使用 GNU arm-none-eabi 工具链为我的 Cortex M3 微控制器开发嵌入式 C 应用程序。

我计划采用供应商在我的 C 应用程序中实现的汇编子例程。我计划创建一个新的 C 函数,然后在其中使用扩展内联汇编协议编写内联汇编块。在这篇文章中,我计划将此汇编子例程视为黑匣子,并计划向此论坛询问如何构建输入和破坏列表;该例程没有输出。

汇编子例程期望在调用之前预先设置 r0、r1 和 r2。此外,子例程使用寄存器 r4、r5、r6、r7、r8、r9 作为临时寄存器来执行其功能。它写入设备上的一系列内存,由 r0 和 r1 指定,分别是起始地址和停止地址。

所以,我正在检查我的假设是否正确。我的问题如下。

  1. 我认为我应该写的函数是这样的吗?:
void my_asm_ported_func(int reg_r0, int reg_r1, int reg_r2 {
    __asm__ __volatile__ (
        "ldr r0, %0        \n\t",
        "ldr r1, %1        \n\t",
        "ldr r2, %2        \n\t",
        "<vendor code...>  ",
        :  /* no outputs */
        : "r" (reg_r0), "r" (reg_r1), "r" (reg_r2) /* inputs */
        : "r0", "r1", "r2", "r4", "r5", "r6", 
          "r7", "r8", "r9", "memory" /* clobbers …
Run Code Online (Sandbox Code Playgroud)

c arm bare-metal inline-assembly cortex-m

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