使用内联汇编在 C 中添加值
Adding values in C using inline assembly
我想掌握 C 中内联汇编的基础知识(ATT 汇编),所以我通过添加 2 个变量来练习。
好的,这是按预期工作的; src 变量被复制到 dst 变量,然后 dst 变量被添加 5。 src 和 dst 的值分别为 1 和 6。
int src = 1;
int dst = 0;
asm ("mov %[SRC], %[DEST]\n\t"
"add , %0"
: [DEST] "=r" (dst));
: [SRC] "r" (src));
但是当我尝试这个时,src 和 dst 的值仍然是 1 和 6。我期待 src 的值为 1,dst 的值为 5,因为将 5 添加到 dst(其值为0,因为 MOV 操作已被删除)应该有输出 5。
int 源=1;
int dst = 0;
asm ("add , %[DEST]"
: [DEST] "=r" (dst)
: [SRC] "r" (src));
然后我尝试使用以下代码删除 src 作为输入操作数,但现在 dst 获得值 11。
int dst = 0;
asm (
"add , %[DEST]"
: [DEST] "=r" (dst));
现在我对它的工作原理有点困惑。我误会了什么?
您的代码的第一部分按预期工作。有
mov %[SRC], %[DEST] ; copies %[SRC] into %[DEST], which is now 1
add , %0 ; adds 5 to %0 (which is %[DEST]), so that's 6
第二部分不起作用,因为您从不使用 %[SRC]
,并且因为 %[DEST]
不是输入操作数,所以它的值不会进入计算。你只是得到 gcc 决定使用的寄存器中的内容。第三部分同样失败。
要让它工作,您需要将 dst
指定为输入和输出操作数,因为您既要使用它的值又要更改它。但是,这不起作用:
asm("add , %0" // This does not work!
: "=r" (dst)
: "r" (dst));
因为现在您有一个输入操作数 %1
,其值为 dst
和一个不同的输出操作数 %0
,其值将被写入 dst
,并且您永远不会使用%1
。这个符号可以让你写
asm("mov %1, %0; add , %0" // needlessly inefficient!
: "=r" (dst)
: "r" (dst));
但这当然是不必要的低效。为了使用单个寄存器执行此操作,您需要使用 匹配约束 ,如下所示:
asm("add , %0"
: "=r" (dst)
: "0" (dst));
这告诉 gcc 允许 %0
作为输入操作数,并且它的值是 dst
。 Here 是 gcc 手册的相关部分。
有了命名的操作数,最后,它看起来像这样:
asm ("add , %[DEST]"
: [DEST] "=r" (dst)
: "[DEST]" (dst));
我想掌握 C 中内联汇编的基础知识(ATT 汇编),所以我通过添加 2 个变量来练习。
好的,这是按预期工作的; src 变量被复制到 dst 变量,然后 dst 变量被添加 5。 src 和 dst 的值分别为 1 和 6。
int src = 1;
int dst = 0;
asm ("mov %[SRC], %[DEST]\n\t"
"add , %0"
: [DEST] "=r" (dst));
: [SRC] "r" (src));
但是当我尝试这个时,src 和 dst 的值仍然是 1 和 6。我期待 src 的值为 1,dst 的值为 5,因为将 5 添加到 dst(其值为0,因为 MOV 操作已被删除)应该有输出 5。
int 源=1; int dst = 0;
asm ("add , %[DEST]"
: [DEST] "=r" (dst)
: [SRC] "r" (src));
然后我尝试使用以下代码删除 src 作为输入操作数,但现在 dst 获得值 11。
int dst = 0;
asm (
"add , %[DEST]"
: [DEST] "=r" (dst));
现在我对它的工作原理有点困惑。我误会了什么?
您的代码的第一部分按预期工作。有
mov %[SRC], %[DEST] ; copies %[SRC] into %[DEST], which is now 1
add , %0 ; adds 5 to %0 (which is %[DEST]), so that's 6
第二部分不起作用,因为您从不使用 %[SRC]
,并且因为 %[DEST]
不是输入操作数,所以它的值不会进入计算。你只是得到 gcc 决定使用的寄存器中的内容。第三部分同样失败。
要让它工作,您需要将 dst
指定为输入和输出操作数,因为您既要使用它的值又要更改它。但是,这不起作用:
asm("add , %0" // This does not work!
: "=r" (dst)
: "r" (dst));
因为现在您有一个输入操作数 %1
,其值为 dst
和一个不同的输出操作数 %0
,其值将被写入 dst
,并且您永远不会使用%1
。这个符号可以让你写
asm("mov %1, %0; add , %0" // needlessly inefficient!
: "=r" (dst)
: "r" (dst));
但这当然是不必要的低效。为了使用单个寄存器执行此操作,您需要使用 匹配约束 ,如下所示:
asm("add , %0"
: "=r" (dst)
: "0" (dst));
这告诉 gcc 允许 %0
作为输入操作数,并且它的值是 dst
。 Here 是 gcc 手册的相关部分。
有了命名的操作数,最后,它看起来像这样:
asm ("add , %[DEST]"
: [DEST] "=r" (dst)
: "[DEST]" (dst));