过去的情况是,如果你需要直接在 Linux 中进行系统调用而不使用现有的库,你可以只包含它<linux/unistd.h>,它会定义一个类似于以下的宏:
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type name(type1 arg1,type2 arg2,type3 arg3) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3))); \
if (__res>=0) \
return (type) __res; \
errno=-__res; \
return -1; \
}
Run Code Online (Sandbox Code Playgroud)
然后你可以在代码中的某个地方放置:
_syscall3(ssize_t, write, int, fd, const void *, buf, size_t, count);
Run Code Online (Sandbox Code Playgroud)
这将为您定义一个write正确执行系统调用的函数。
似乎这个系统已经被更强大的东西(我猜测每个进程都会获得的“[vsyscall]”页面)取代。
那么程序在较新的 Linux 内核上直接执行系统调用的正确方法(请具体)是什么?我意识到我应该使用 libc 并让它为我完成工作。但我们假设我有充分的理由想知道如何做到这一点:-)。
在 x86 内联汇编中,我可以这样写:
asm ("cpuid"
: "=a" (_eax),
"=b" (_ebx),
"=c" (_ecx),
"=d" (_edx)
: "a" (op));
Run Code Online (Sandbox Code Playgroud)
所以在 matchin 约束中,而不是只写“=r”并让编译器选择寄存器,我可以说我想使用哪个特定的寄存器(=a 例如使用 %eax)
我怎样才能为 ARM 程序集做到这一点?ARM GCC 汇编手册http://www.ethernut.de/en/documents/arm-inline-asm.html指出,例如,我可以将约束“r”用于通用寄存器 R0-R15“w”之一" 对于 VFP 浮点寄存器 S0-S31 之一
但是我怎样才能将一个操作数限制在例如 s1 呢?或特定的通用寄存器?
据我所知,在SPARC中,32位整数存储在单个寄存器中,64位整数存储在相邻寄存器对中,偶数寄存器包含高32位,奇数寄存器包含低32位.
我需要编写一些专门的SPARC内联汇编宏(内联汇编函数也可以)处理64位整数双字对,我无法弄清楚如何一般地引用(使用GCC扩展内联汇编)到我的内联装配中两半的一对.虽然我的汇编宏比下面显示的MULTIPLY()宏稍微复杂一些,但乘法示例(如果有效)将演示如何处理64位双字对的两半.谁能告诉我如何修复我的MULTIPLY()宏?
万一重要,我正在......
bash-2.03 $ uname -a
SunOS [...] 5.8 Generic_117350-39 sun4u sparc SUNW,Ultra-80
这是我的简单示例程序(在C中):
#include <stdio.h>
//#include <stdint.h>
#define uint32 unsigned long int
#define uint64 unsigned long long int
#define MULTIPLY(r, a, b) /* (r = a * b) */ \
asm("umul %1, %2, %0;" /* unsigned mul */ \
: /* regs out */ "=h"(r) \
: /* regs in */ "r"(a), "r"(b));
#if 0
: /* clobbers */ "%y" );
#endif
int main(int argc, char** argv)
{ …Run Code Online (Sandbox Code Playgroud) 鉴于此代码:
#include <stdio.h>
int main(int argc, char **argv)
{
int x = 1;
printf("Hello x = %d\n", x);
}
Run Code Online (Sandbox Code Playgroud)
我想在内联汇编中访问和操作变量 x 。理想情况下,我想使用内联汇编更改其值。GNU 汇编器,并使用 AT&T 语法。
假设我想从双核 x64 CPU 上的这些寄存器(以及所有这些)中读取值。我怎样才能做到这一点?我可以简单地写一些类似的东西:
uint64_t rax = 0, rbx = 0;
__asm__ __volatile__ (
/* read value from rbx into rbx */
"movq %%rdx, %0;\n"
/* read value from rax into rax*/
"movq %%rax, %1;\n"
/* output args */
: "=r" (rbx), "=r" (rax)
: /* no input */
/* clear both rdx and rax */
: "%rdx", "%rax"
);
Run Code Online (Sandbox Code Playgroud)
然后只是打印出来rax和rbx?干杯
我有兴趣了解程序员在纯 Common Lisp 中的底层水平如何(或者,如果做不到这一点,则在特定于实现的扩展中)。谷歌还没有给我找到太多这方面的信息,所以我想听听专家们的说法。这篇文章提到了 SBCL 的一个功能来定义作者所说的“虚拟操作符”,但是搜索“common lisp 虚拟操作符”并没有得到太多结果。作者还提到找到相关文档有多么困难。其他实现是否存在类似的系统,标准中是否有任何基础(尽管考虑到这样的功能主要用于编写 ISA 特定的代码,但对于它的用户来说,可移植性不应该是真正的优先事项) ,在哪里可以找到此类功能的文档?
如果能找到一种方法将“可编程编程语言”概念扩展到低级代码(特别是对于效率非常重要且其他用 C 或汇编语言编写的库可能不可用的领域),那就太好了。
我有以下代码,可以用 gcc 命令很好地编译gcc ./example.c。程序本身调用函数“add_two”,它只是将两个整数相加。要在扩展汇编指令中使用 intel 语法,我需要首先切换到 intel,然后再切换回 AT&T。根据 gcc 文档,可以使用gcc -masm=intel ./exmaple.
每当我尝试使用 switch 编译它时,-masm=intel它都不会编译,我不明白为什么?我已经尝试删除该指令,.intel_syntax但它仍然无法编译。
#include <stdio.h>
int add_two(int, int);
int main(){
int src = 3;
int dst = 5;
printf("summe = %d \n", add_two(src, dst));
return 0;
}
int add_two(int src, int dst){
int sum;
asm (
".intel_syntax;" //switch to intel syntax
"mov %0, %1;"
"add %0, %2;"
".att_syntax;" //switch to at&t syntax
: "=r" (sum) //output
: "r" (src), "r" …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种通过模板函数自动执行 gcc 内联汇编调用的方法。
例如,我有以下虚拟函数将值存储到指针中。现在我专门针对不同类型的模板函数。每当代码发生变化时,我都需要针对每个专业化进行更改。
template <typename T>
void store_ptr(T *location, T value);
template <>
void store_ptr<char>(char *location, char value) {
__asm__ __volatile__(
"strb %1, [%0]\n\t"
: "+r" (location)
: "r" (value)
: "memory"
);
}
template <>
void store_ptr<short>(short *location, short value) {
__asm__ __volatile__(
"strh %1, [%0]\n\t"
: "+r" (location)
: "r" (value)
: "memory"
);
}
Run Code Online (Sandbox Code Playgroud)
如果模板可以根据模板类型对指令附录(“b”、“h”...)进行字符串化,那就太好了。
template <typename T>
void store_ptr<T>(T *location, T value) {
__asm__ __volatile__(
"str" stringify_template_type(T) " %1, [%0]\n\t"
: "+r" (location)
: "r" …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 RDMSR 和 WRMSR 指令读取 PMC(性能监控计数器)。
\n\n在我的具有 Intel i7 6700 CPU (Skylake) 的 Linux 桌面上,我编写了一个简单的驱动程序代码:
\n\nstatic int my_init(void)\n{\n unsigned int msr;\n u64 low, high;\n\n msr = 0x187;\n low = 0x412e;\n high = 0x0;\n\n asm volatile("1: wrmsr\\n"\n "2:\\n"\n : : "c" (msr), "a"(low), "d" (high) : "memory");\n\n msr = 0xC2;\n asm volatile("1: rdmsr\\n"\n "2:\\n"\n : "=a" (low), "=d" (high) : "c" (msr)); \n\n printk("val: %lu\\n", (low) | ((high) << 32));\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n参考Intel手册(18.2 ARCHITECTURAL PERFORMANCE MONITORING in Intel\xc2\xae …
某些使用goto限定符的扩展汇编语句无法使用 GCC 10.1.0 进行编译。具体来说,
int foo(int count)
{
asm goto ("dec %0; jb %l[stop]"
: "+r" (count)
:
:
: stop);
return count;
stop:
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(这是GCC 扩展 asm 文档中的一个示例)无法使用消息编译expected ‘:’ before string constant。删除"+r" (count)和dec %0允许它成功编译,但无论我在何时尝试在与 goto 标签相同的 asm 语句中提供输出操作数时,它都会以同样的方式出错。
inline-assembly ×10
c ×5
gcc ×5
c++ ×3
assembly ×2
x86 ×2
arm ×1
c++11 ×1
common-lisp ×1
goto ×1
intel ×1
intel-pmu ×1
intel-syntax ×1
kernel ×1
linux ×1
macros ×1
sparc ×1
system-calls ×1
templates ×1