首先,如果有人知道标准 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)
有人可以告诉我这个问题吗?
我需要在 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 版本。
你能帮助我吗?我怎样才能找到解决办法?
我正在处理一些具有使用内联汇编的优化版本的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 …
考虑以下来自 CUDA 的Inline PTX Assebly指南 (v10.2) 的摘录:
编译器假定
asm()语句除了更改输出操作数之外没有副作用。为确保在生成 PTX 期间不会删除或移动 asm,您应该使用 volatile 关键字,例如:Run Code Online (Sandbox Code Playgroud)asm volatile ("mov.u32 %0, %%clock;" : "=r"(x));通常写入的任何内存都将被指定为输出操作数,但如果对用户内存有隐藏的副作用(例如,通过操作数间接访问内存位置),或者如果您想停止任何内存优化在生成 PTX 期间执行的 asm() 语句周围,您可以在第三个冒号后添加“内存”clobbers 规范...
这听起来像是两者 volatile,:: "memory"旨在表明内存中的副作用。现在,当然,可能存在非记忆副作用(例如 for trap;)。但是 - 当我使用 时volatile,也指定:: "memory")不是没用/没有意义吗?
我尝试更换malloc(3)/ calloc(3)/ realloc(3)/free(3)通过LD_PRELOAD环境变量。我尝试使用静态链接的自定义函数,它们工作得很好。
但是,当我将它作为共享库附加到 时LD_PRELOAD,它总是会导致段错误。
mmap(2)和munmap(2)syscall for malloc(3)and free(3)。calloc(3)只是对malloc(3)乘法溢出检查的调用。realloc(3)电话malloc(3),然后复制旧的数据到新分配的内存和取消映射旧内存。我完全意识到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) 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) 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"次.
我正在尝试使用内联汇编的示例:http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html 但是有些事让我感到困惑:
"好吧,当GCC能够确切地知道你之前和之后对寄存器做了什么时,这确实很有帮助......如果你告诉它将(x + 1)放入寄存器中,它甚至足够聪明. ,如果你没有破坏它,后来C代码引用(x + 1),并且它能够保持该寄存器空闲,它将重用计算.哇."
关于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.
我正在尝试使用 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) 我最近涉足低级编程,并希望制作一个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) 我正在使用 GNU arm-none-eabi 工具链为我的 Cortex M3 微控制器开发嵌入式 C 应用程序。
我计划采用供应商在我的 C 应用程序中实现的汇编子例程。我计划创建一个新的 C 函数,然后在其中使用扩展内联汇编协议编写内联汇编块。在这篇文章中,我计划将此汇编子例程视为黑匣子,并计划向此论坛询问如何构建输入和破坏列表;该例程没有输出。
汇编子例程期望在调用之前预先设置 r0、r1 和 r2。此外,子例程使用寄存器 r4、r5、r6、r7、r8、r9 作为临时寄存器来执行其功能。它写入设备上的一系列内存,由 r0 和 r1 指定,分别是起始地址和停止地址。
所以,我正在检查我的假设是否正确。我的问题如下。
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 ×8
assembly ×7
gcc ×5
arm ×3
system-calls ×3
x86 ×3
x86-64 ×2
android ×1
android-ndk ×1
bare-metal ×1
c++ ×1
cortex-m ×1
cuda ×1
ld-preload ×1
linux ×1
malloc ×1
optimization ×1
ptx ×1
redundancy ×1
ubuntu ×1