c - 在扩展 asm 输出参数中使用“+”修饰符时输入参数索引?
问题描述
扩展 asm给出了关于"+"
修饰符的以下描述:
使用 '+' 约束修饰符的操作数算作两个操作数(即,作为输入和输出),每个 asm 语句最多可有 30 个操作数。
所以我假设没有必要在输入部分再次提到带有“+”修饰符的输出操作数,但没有指定如何确定它们的索引。我写了以下示例Godbolt:
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
void asm_add(uint64_t o1, uint64_t o2, uint64_t o3){
__asm__ volatile (
"addq %2, %3\n\
addq %2, %4":
"+r" (o2), "+r" (o3):
"r" (o1):
"cc"
);
printf("o2 = %" PRIu64 "\n", o2);
printf("o3 = %" PRIu64 "\n", o3);
}
int main(void){
asm_add(20, 30, 40);
}
哪个印刷
o2 = 50
o3 = 60
模板是否使用+
__asm__ volatile (
"addq %2, %3\n\
addq %2, %4":
"+r" (o2), "+r" (o3):
"r" (o1):
"cc"
);
完全一样
__asm__ volatile (
"addq %2, %3\n\
addq %2, %4":
"+r" (o2), "+r" (o3):
"r" (o1), "0" (o2), "1" (o3):
"cc"
);
明确指定所有输入的地方?因此,在第一个示例中,附加了“隐式”输入。
解决方案
通过使用"+r" (o2)
,您是说此参数在进入 asm 块时需要包含 o2,并且在退出时将包含更新的值。
换句话说,%0 描述了输入和输出。您可以(显然?)引用大于参数数量的索引这一事实是一个未记录的怪癖。不要依赖它。
您也可以考虑使用符号名称,(我发现)它更易于阅读,尤其是当 asm 行数增加时。当您第一次创建 asm 并且有可能添加/删除参数时,名称特别有用。必须对所有内容重新编号是痛苦且容易出错的:
__asm__ volatile (
"addq %[o1], %[o2]\n\
addq %[o1], %[o3]":
[o2] "+r" (o2), [o3] "+r" (o3):
[o1] "r" (o1):
"cc"
);
最后,考虑不要将内联汇编用于教育目的之外的任何事情。即便如此,内联汇编是学习汇编最难的方法。
推荐阅读
- javascript - 如何在 React 中删除列表项 - 控制台中不显示错误
- scala - Akka Streams - 流大表
- backend - 清晰设计编程
- c++ - 在c ++中找到从1到50的随机数的平均值
- swift - 使用 NSPersistentCloudKitContainer 时预填充核心数据存储的最佳方法是什么?
- c# - 如何使用 selenium 在不和谐的网站版本上按“进入寒冷区域按钮”?
- c# - Protobuf 序列化对象到 json
- python - 为什么 random.sample 有时与 multiprocessing.Pool 一起使用死锁?
- ios - SwiftUI 和组合 - 当另一个更改时更新视图模型中的变量
- django - Django 将外键更改为 BigInt