【发布时间】:2021-01-19 01:41:09
【问题描述】:
这看起来不太友好:
__asm("command 1"
"command 2"
"command 3");
我真的必须在每一行加上双引号吗?
另外...由于多行字符串文字在 GCC 中不起作用,所以我也无法作弊。
【问题讨论】:
标签: gcc assembly inline-assembly
这看起来不太友好:
__asm("command 1"
"command 2"
"command 3");
我真的必须在每一行加上双引号吗?
另外...由于多行字符串文字在 GCC 中不起作用,所以我也无法作弊。
【问题讨论】:
标签: gcc assembly inline-assembly
我总是在 Internet 上找到一些示例,即该人手动插入制表符和换行符而不是 \t 和 \n,但它对我不起作用。不太确定您的示例是否可以编译。但我就是这样做的:
asm volatile( // note the backslash line-continuation
"xor %eax,%eax \n\t\
mov $0x7c802446, %ebx \n\t\
mov $1000, %ax \n\t\
push %eax \n\t\
call *%ebx \n\t\
add $4, %esp \n\t\
"
: "=a"(retval) // output in EAX: function return value
:
: "ecx", "edx", "ebx" // tell compiler about clobbers
// Also x87 and XMM regs should be listed.
);
或者在每一行加上双引号,而不是使用\ line-continuation。 C 字符串文字仅由空格(包括换行符)单独连接成一个长字符串文字。 (这就是为什么你需要 \n 在里面,所以当它被汇编器看到时它是单独的行)。
这样不那么难看,并且可以在每一行放置 C cmets。
asm volatile(
"xor %eax,%eax \n\t"
"mov $0x7c802446, %ebx \n\t"
"mov $1000, %ax \n\t"
"push %eax \n\t" // function arg
"call *%ebx \n\t"
"add $4, %esp \n\t" // rebalance the stack: necessary for asm statements
: "=a"(retval)
:
: "ecx", "edx", "ebx" // clobbers. Function calls themselves kill EAX,ECX,EDX
// function calls also clobber all x87 and all XMM registers, omitted here
);
【讨论】:
\t\n 的替代方法是用分号分隔指令。 \t\n 更好,因为生成的 asm 输出不会一团糟。通常使用 "insn \n\t" "insn2 \n\t" 等,并让字符串连接起作用,而不是用反斜杠结束每一行。
C++ 多行字符串文字
有趣的是,这个问题如何为我指明了答案:
main.cpp
#include <cassert>
#include <cinttypes>
int main() {
uint64_t io = 0;
__asm__ (
R"(
incq %0
incq %0
)"
: "+m" (io)
:
:
);
assert(io == 2);
}
编译运行:
g++ -o main -pedantic -std=c++11 -Wall -Wextra main.cpp
./main
另请参阅:C++ multiline string literal
GCC 还添加了与 C 扩展相同的语法,您只需使用 -std=gnu99 而不是 -std=c99:
main.c
#include <assert.h>
#include <inttypes.h>
int main(void) {
uint64_t io = 0;
__asm__ (
R"(
incq %0
incq %0
)"
: "+m" (io)
:
:
);
assert(io == 2);
}
编译运行:
gcc -o main -pedantic -std=gnu99 -Wall -Wextra main.c
./main
另见:How to split a string literal across multiple lines in C / Objective-C?
这种方法的一个缺点是我看不到如何在程序集中添加 C 预处理器宏,因为它们没有在字符串内部展开,另请参阅:Multi line inline assembly macro with strings
在 Ubuntu 16.04、GCC 6.4.0、binutils 2.26.1 上测试。
.incbin
如果您要使用大量程序集,则该 GNU GAS 指令是您应该关注的另一件事:Embedding resources in executable using GCC
程序集将在一个单独的文件中,因此不是直接答案,但仍然值得了解。
【讨论】: