C语言用于编写UNIX以实现可移植性 - 使用不同编译器编译的相同C语言程序生成不同的机器指令.为什么Windows操作系统能够在Intel和AMD处理器上运行?
说我有以下C代码:
int32_t foo(int32_t x) {
return x + 1;
}
Run Code Online (Sandbox Code Playgroud)
这是未定义的行为时x == INT_MAX.现在说我用内联汇编代替了:
int32_t foo(int32_t x) {
asm("incl %0" : "+g"(x));
return x;
}
Run Code Online (Sandbox Code Playgroud)
问题:内联汇编版本何时仍会调用未定义的行为x == INT_MAX?或者未定义的行为仅适用于C代码?
我对这两个指令都有点困惑.首先,让我们丢弃的特殊情况下,当扫描的值是0和未定义/ BSR或bitsize/lzcnt结果 - 这种差异是明显的,而不是我的问题的一部分.
我们来看二进制值 0001 1111 1111 1111 1111 1111 1111 1111
根据英特尔的规格,结果为lzcnt3
根据英特尔的规格,结果为bsr28
lzcntcount,bsr从位0返回索引或距离(即lsb).
两个指令如何相同,如何在CPU上没有可用的BMI的情况下lzcnt进行仿真bsr?或者bsr在msb的情况下是0位?英特尔规范中的"代码操作"也不同,一个是左边的计数或索引,另一个来自右边.
也许有人可以提供一些线索这光,我没有CPU无BMI/lzcnt指令测试,如果退回到bsr同样的结果作品(如值为0的特殊情况下扫描从未发生过).
在学习x86-64汇编时,我遇到了我的第一个"x86-64"的Intel 64和AMD64实现之间的不兼容性:为什么syscall在NASM 32位输出中编译而popa不能在64位编译? syscall在一个而不是另一个的兼容模式下有效.
除了仔细阅读这两本手册并进行比较之外,还有更好的方法可以找出这些不兼容性吗?这样会容易出错,并且在针对可移植性时会重复我的手动阅读工作吗?
例如,如果有以下任何一种情况会更容易:
此处的 GCC 文档指定了 _buitin_prefetch 的用法。
第三个论点是完美的。若为0,编译器产生prefetchtnta(%rax)指令 若为1,编译器产生prefetcht2(%rax)指令 若为2,编译器产生prefetcht1(%rax)指令 若为3(默认),编译器产生prefetcht0 (%rax) 指令。
如果我们改变第三个参数,操作码已经相应地改变了。
但是第二个参数似乎没有任何效果。
__builtin_prefetch(&x,1,2);
__builtin_prefetch(&x,0,2);
__builtin_prefetch(&x,0,1);
__builtin_prefetch(&x,0,0);
Run Code Online (Sandbox Code Playgroud)
以上是生成的示例代码:
以下是组装:
27: 0f 18 10 prefetcht1 (%rax)
2a: 48 8d 45 fc lea -0x4(%rbp),%rax
2e: 0f 18 10 prefetcht1 (%rax)
31: 48 8d 45 fc lea -0x4(%rbp),%rax
35: 0f 18 18 prefetcht2 (%rax)
38: 48 8d 45 fc lea -0x4(%rbp),%rax
3c: 0f 18 00 prefetchnta (%rax)
Run Code Online (Sandbox Code Playgroud)
可以观察到第三个参数的操作码的变化。但即使我更改了第二个参数(指定读或写),汇编代码也保持不变。<27,2a> 和 <2e,31>。所以它不会向机器提供任何信息。那么第二个论点的目的是什么?