当我在汇编中乘以一对4字节整数时,结果的下半部分在EAX中,而在EDX中则是较高部分.如果我使用的是C或C++并且我想获得更高的部分,是否有可能不使用内联汇编?
是否有可能从EAX获得整数除法结果和EDX的模数结果而不重复C或C++中的除法?我实际上只知道先做a/b,然后a%b在汇编程序中,两个结果都在同一个操作中给出.
chq*_*lie 10
您可以通过这种方式轻松完成:
#include <stdint.h>
uint32_t a, b; // input
uint64_t val = (uint64_t)a * b;
uint32_t high = val >> 32, low = val;
Run Code Online (Sandbox Code Playgroud)
将它留给编译器以产生最好的代码.现代优化者真的很擅长.手动编码组件通常看起来更好,但性能更差.
正如Pete Becker评论的那样,上面依赖于类型uint32_t和类型的可用性uint64_t.如果你坚持难改便携性(比如你正在编写一个DS9K),你可以改用类型uint_least32_t和uint_least64_t或uint_fast32_t和uint_fast64_t始终可用C99下,但你需要一个额外的面具,如果不需要的话,将被优化掉:
#include <stdint.h>
uint_fast32_t a, b; // input
uint_fast64_t val = (uint_fast64_t)a * b;
uint_fast32_t high = (val >> 32) & 0xFFFFFFFF, low = val & 0xFFFFFFFF;
Run Code Online (Sandbox Code Playgroud)
关于除法,您可以使用C99库函数div,ldiv或lldiv在一次调用中执行有符号除法和余数运算.如果可能,在特定操作数类型的目标体系结构上,将在一个操作中实现除法/模组合.
编写两个表达式并依赖编译器检测模式并生成使用单个IDIV操作码的代码可能更有效:
struct divmod_t { int quo, rem; };
struct divmod_t divmod(int num, int denom) {
struct divmod_t r = { num / denom, num % denom };
return r;
}
Run Code Online (Sandbox Code Playgroud)
在Matt上测试Godbolt的编译器浏览器显示clang和gcc都idiv为此代码生成一条指令-O3.
您可以将其中一个分区变为乘法:
struct divmod_t { int quo, rem; };
struct divmod_t divmod2(int num, int denom) {
struct divmod_t r;
r.quo = num / denom;
r.rem = num - r.quo * denom;
return r;
}
Run Code Online (Sandbox Code Playgroud)
请注意,上述函数不检查潜在的溢出,这会导致未定义的行为.如果denom = 0和如果num = INT_MIN和,则发生溢出denom = -1.
您不处理C或C++中的实现细节.这就是重点.如果您想要最重要的字节,只需使用该语言即可.右移>>旨在实现这一目标.就像是:
uint64_t i;
uint32_t a;
uint32_t b;
// input a, b and set i to a * b
// this should be done with (thanks to @nnn, pls see comment below):
// i = a; i *= b;
uint64_t msb = i >> 32;
Run Code Online (Sandbox Code Playgroud)