问题描述
我正在编写一个C ++程序,并决定由于使用进位标志,因此在x86汇编中编写特定功能会更有效。在反汇编中,我注意到某些指令已更改,导致我的程序引发异常:“访问冲突读取位置”。为什么更改说明,如何防止这种情况?
这是我的代码的片段:
variable "build_name" {
default = ["test3","new_build"]
}
反汇编程序显示如下:
Future<bool> checkIfUsernameExistsExcludingCurrentUid(
// Todo NOT DONE
String username,String uid) async {
print("searching db for: $username EXCLUDING SELF");
bool exists = true;
QuerySnapshot result = await _firestore
.collection(USERS_COLLECTION)
.where(
"username",isEqualTo: username,)
.getDocuments();
List _documents = result.documents;
_documents.forEach((element) {
if (element['uid'] == uid) {
exists = false;
} else {
return true;
}
});
return exists;
}
解决方法
您在16位模式下进行了组装,而在32位模式下进行了反汇编,因此一切都与应有的相反。 MASM并不是“更改”指令,只是按照您告诉它的组装方式组装它们。
例如在16位模式下,[ECX]
需要一个67
地址大小覆盖前缀才能对32位寻址模式进行编码。在32位模式下解码时,该前缀会将其覆盖为16位。 (并且该位模式意味着[bx+di]
; 16位寻址模式不能使用SIB字节,因此所有不同的寄存器组合都打包到ModRM字节中。[cx]
是不可编码的。)
此外,如果您认为xor + mov是将DH零扩展到EBX的最有效方法,请查看movzx
。在现代CPU上,这效率更高。 (请参见https://agner.org/optimize/和https://uops.info/)。
通常,您要避免编写像AH这样的高8位寄存器; Haswell / Skylake在读取完整寄存器时会受到合并处罚,而AMD CPU具有虚假的依赖关系。在使用之前,请仔细阅读Why doesn't GCC use partial registers?上的信息和链接。