在 C 函数调用之前,以任何方式(跨编译器、平台、libc 实现等)PUSH 内联汇编中的额外参数是否安全或可移植?

Fab*_*184 1 c assembly gcc x86-64 inline-assembly

我写了一个函数来漂亮地打印一个数独,当然这个模式可以由一些循环生成,但我不想经历麻烦,所以这就是我想出的(前 5 个格式说明符只是参数) printf 本身被压入堆栈,并且在回车后将被覆盖)。

\n

虽然“它可以在我的机器上运行”,但我想知道这是否可以或可以移植到跨架构、编译器、libc 实现等工作?

\n

当然,根据目标平台,汇编代码可能需要进行一些调整,并且 printf 推送的参数数量取决于当前的 libc 实现。

\n
#define PUSH(x) asm volatile ("push %0" : : "m"(x) :)\n#define POP() asm volatile ("pop %%rax" : : : "rax")\n\nvoid print(void) {\n    for (uint8_t i = 1; i <= (9 * 9); ++i) {\n        PUSH(sudoku[(9 * 9) - i]);\n    }\n\n    printf("%hhd%hhd%hhd%hhd%hhd\\r\xe2\x95\x94\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x97\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\xa0\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa3\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\xa0\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa3\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\x9a\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa9\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa9\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x9d\\n");\n\n    for (uint8_t i = 0; i < (9 * 9); ++i) {\n        POP();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Bur*_*sBA 5

不。

没有定义内联汇编语义的 C 标准,因此不同的编译器可以并且确实以不同的方式处理它。这可能会导致代码在不同的编译器下编译时不会出现错误,但会产生略有不同的结果。

https://gcc.gnu.org/wiki/DontUseInlineAsm