我在 VS 中有一个函数,我在其中传递一个指向该函数的指针。然后我想将指针存储在寄存器中以进一步操作。你是怎样做的?
我努力了
float __declspec(align(16)) x[16] =
{
0.125000, 0.125000, 0.125000, 0,
-0.125000, 0.125000, -0.125000, 0,
0.125000, -0.125000, -0.125000, 0,
-0.125000, -0.125000, 0.125000, 0
};
void e()
{
__asm mov eax, x // doesn't work
__asm mov ebx, [eax]
}
void f(float *p)
{
__asm mov eax, p // does work
__asm mov ebx, [eax]
}
int main()
{
f(x);
e();
}
Run Code Online (Sandbox Code Playgroud) 我对 GNU 汇编内联非常陌生,我已经阅读了多篇文章,但仍然不完全了解发生了什么。根据我的理解:
movl %eax, %ebx\n\t将移动无论是在%eax成ebx,但不会将内容添加到对方
addl %eax, %ebx\n\t将添加%eaxwith的内容ebx并将其保存在最右边的寄存器中
addl %1, %0\n\t这就是我感到困惑的地方,我们要添加 1 和 0?为什么我们需要%0那里?
我在做一个操作系统的实现工作。
首先是代码:
//generate software interrupt
void generate_interrupt(int n) {
asm("mov al, byte ptr [n]");
asm("mov byte ptr [genint+1], al");
asm("jmp genint");
asm("genint:");
asm("int 0");
}
Run Code Online (Sandbox Code Playgroud)
我正在用-masm=intelgcc 中的选项编译上面的代码。此外,这不是生成软件中断的完整代码。
我的问题是我收到错误n undefined,我该如何解决,请帮忙?
在 llvm pass 模块中编写一些内联程序集后,我收到此错误:
<inline asm>:1:2: error: unkown use of instruction mnemonic without a size suffix
test %rsi, $1
^
Run Code Online (Sandbox Code Playgroud)
我的理解是这个错误意味着我正在尝试使用指令不支持的操作数大小,或者大小不明确。我仔细阅读了 Intel x86_64 软件开发手册,我相当确定我明确指定了“REX.W + F7 /0 id”或“TEST r/m64,imm32”操作。我需要更明确地说我想要 REX 版本吗?如何?
是否可以使用 GCC 或 Clang 编写内联汇编(英特尔语法),而无需了解 clobber 列表“东西”?
我会猜测“不”,因为 clobber 列表“东西”确保您不会覆盖编译器写入的寄存器(立即在您的内联汇编开始之前)?
我有一小段代码,其中有一些内联程序集可以在 O0 中正确打印 argv[0],但不会在 O2 中打印任何内容(使用 Clang 时。另一方面,GCC 打印存储在 envp[0] 中的字符串打印 argv[0] 时)。这个问题也仅限于 argv(其他两个函数参数可以在启用或不启用优化的情况下按预期使用)。我用 GCC 和 Clang 对此进行了测试,两个编译器都有这个问题。
这是代码:
void exit(unsigned long long status) {
asm volatile("movq $60, %%rax;" //system call 60 is exit
"movq %0, %%rdi;" //return code 0
"syscall"
: //no outputs
:"r"(status)
:"rax", "rdi");
}
int open(const char *pathname, unsigned long long flags) {
asm volatile("movq $2, %%rax;" //system call 2 is open
"movq %0, %%rdi;"
"movq %1, %%rsi;"
"syscall"
: //no outputs
:"r"(pathname), "r"(flags)
:"rax", "rdi", …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 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) 那么关键字“inline”会导致调用被函数体替换吗?所以我猜这意味着我们完全跳过电话?就像如果我们查看 .asm 文件,我们不会找到调用指令?
我想要这样的东西:
template <const char *op, int lane_select>
static int cmpGT64Sx2(V64x2 x, V64x2 y)
{
int result;
__asm__("movups %1,%%xmm6\n"
"\tmovups %2,%%xmm7\n"
// order swapped for AT&T style which has destination second.
"\t " op " %%xmm7,%%xmm6\n"
"\tpextrb %3, %%xmm6, %0"
: "=r" (result) : "m" (x), "m" (y), "i" (lane_select*8) : "xmm6");
return result;
}
Run Code Online (Sandbox Code Playgroud)
显然它必须是一个模板,因为它必须在编译时已知。该lane_select 工作正常,它是一个模板,但它是一个操作数。我希望opasm 中的 是不同的,例如pcmpgtd或pcmpgtq等。如果有帮助:我总是想要某种形式的 x86 pcmpgt,只需要更改最后一个字母。
编辑:
这是 valgrind 的一个测试用例,其中运行确切的指令非常重要,以便我们可以检查输出的定义性。
我最近阅读了这篇名为Embedded Systems/Mixed C and Assembly Programming 的文档
它主要涉及 C 和 C++ 如何允许用户通过称为内联汇编的技术使用汇编代码,该技术看起来像这样:
#include<stdio.h>
void main() {
int a = 3, b = 3, c;
asm {
mov ax,a
mov bx,b
add ax,bx
mov c,ax
}
printf("%d", c);
}
Run Code Online (Sandbox Code Playgroud)
我想知道在其他高级语言(如 Java、Python 和其他语言)中是否可以进行类似的交互,或者是否只能使用 C 和 C++。
inline-assembly ×10
assembly ×9
gcc ×4
x86 ×4
c ×3
c++ ×3
x86-64 ×2
arm ×1
att ×1
clang ×1
function ×1
inline ×1
java ×1
linux ×1
llvm ×1
machine-code ×1
osdev ×1
system-calls ×1
templates ×1
visual-c++ ×1