我正试图编写一些代码,以便进一步了解程序集和jit编译器之类的东西。到目前为止,我已经能够想出一个xor函数,理论上,它应该在windows和linux环境下的x86或x64机器上工作。
假设我正确地理解了事情,
[RE]AX
寄存器用于保存整数返回值,而
[RE]DX
是用于在函数之间传递整数的可用寄存器之一。我选择不严格遵循abi并使用
斧头
因为它节省了
MOV
不影响结果的指令。
是否有更好(更优雅或更高效)的方法来发出跨平台程序集,或者我在开发这个程序时犯了什么错误?
#include
#include
template
static auto Xor(TInput const highPart, TInput const lowPart) {
constexpr bool is16Bit = (std::is_same::value || std::is_same::value);
constexpr bool is32Bit = (std::is_same::value || std::is_same::value);
static_assert(is16Bit || is32Bit, "type must be a member of the type family: [u]int{16, 32}_t");
if constexpr (is16Bit) {
uint16_t result;
#if (defined(__linux__) || defined(__unix__) || defined(_WIN32))
asm volatile ("xorw %%dx, %%ax;" : "=a" (result) : "a" (highPart), "d" (lowPart));
#else
#error "Unsupported platform detected."
#endif
return result;
}
else if constexpr (is32Bit) {
uint32_t result;
#if (defined(__linux__) || defined(__unix__) || defined(_WIN32))
asm volatile ("xorl %%edx, %%eax;" : "=a" (result) : "a" (highPart), "d" (lowPart));
#else
#error "Unsupported platform detected."
#endif
return result;
}
}
#define HIGH_PART 4;
#define LOW_PART 8;
int main() {
int16_t const a = HIGH_PART;
int16_t const b = LOW_PART;
int16_t const c = Xor(a, b);
uint32_t const x = HIGH_PART;
uint32_t const y = LOW_PART;
uint32_t const z = Xor(x, y);
std::cout << c << "\n";
std::cout << z << "\n";
getchar();
return 0;
}
下面是一个如何改进的例子;通过“提升”
result
变量和
if defined(...)
支票高于
constexpr
检查我们可以使事情更一般。
template
static auto Xor(T const highPart, T const lowPart) {
constexpr bool is16Bit = (std::is_same::value || std::is_same::value);
constexpr bool is32Bit = (std::is_same::value || std::is_same::value);
static_assert(is16Bit || is32Bit, "type must be a member of the type family: [u]int{16, 32}_t");
#if !(defined(__linux__) || defined(__unix__) || defined(_WIN32))
#error "Unsupported platform detected."
#endif
T result;
if constexpr (is16Bit) {
asm volatile ("xorw %%dx, %%ax;" : "=a" (result) : "a" (highPart), "d" (lowPart));
}
else if constexpr (is32Bit) {
asm volatile ("xorl %%edx, %%eax;" : "=a" (result) : "a" (highPart), "d" (lowPart));
}
return result;
}