x86-64是Intel x86架构的64位扩展
用户模式 x64 中是否有任何方案可以让硬件自动对每个内存加载和存储应用边界检查,而无需编译器的显式检测?我也不想...
考虑以下由 clang 生成的 x64 代码: mov rax, qword ptr [rsi] ; 1 mov rdx, qword ptr [rip + hash_mult] ; 1 imul rdx,qword pt...
x86-64 上的 C++:结构/类何时在寄存器中传递和返回?
假设 Linux 上的 x86-64 ABI,在 C++ 中的什么条件下,结构体会传递给寄存器中的函数,还是传递给堆栈上的函数?在什么条件下它们会返回到寄存器中?答案是吗
编写汇编程序:处理 x64 REX 和 VEX 编码的干净高效的方法?
我正在开发一个 x64 汇编器(只有 64 位,至少现在是这样),而且我已经取得了相当大的进展(我支持几乎所有指令,包括大多数扩展),但我有一些相当...
我们正在使用 Windows 和 Mac M1 机器使用 Docker 进行本地开发,并且需要在我们的 docker 环境中获取并安装 .deb 包。 该软件包需要 amd64/arm64,具体取决于...
我想知道是否可以对如下指令进行编码: 添加 rax,[地址] 其中 是指向 64 位值的完整 64 位地址。 NASM 似乎只是截断了地址... 我想知道是否可以对如下指令进行编码: 添加rax,[地址] 其中 是指向 64 位值的完整 64 位地址。 NASM 似乎只是截断地址并将其编码为 32 位地址。唯一有效的 64 位寻址(使用直接地址)形式是: mov rax,[qword 地址] 由 NASM 使用 REX.W=1 和 MOV 的特殊操作码进行直接寻址编码。将 REX.W 与 add 指令一起使用只会使其将目标地址解释为包含 64 位值,但不允许指定 64 位地址。但我很好奇是否还有其他方法。 (顺便说一句,由于这个问题,我现在使用 RIP 相对寻址)。 谁能确认直接 64 位寻址形式是不可能的? 除某些特殊情况外,amd64架构没有64位位移的寻址模式。相反,使用 rip 相对寻址,如果您的二进制文件大小小于 2 GB,这应该没问题。 请记住,64 位模式是 AMD 的天才之作。 1980 年,英特尔团队坚持认为 INC REG16(2 字节指令)太长,并浪费了 256 个首页操作码中的 16 个来用 1 字节创建别名。 AMD 将其重新用作具有 4 位可用的前缀,在编译器愿意节省一个字节的极少数情况下浪费了一个字节。 对于 64 位操作,第一位表示 1。 剩下的三位用于指定是否是 32 位或 64 位寄存器 故意的。幸运的是,sib 中最复杂的指令有一个主寄存器、一个指针和一个索引,总共三个。 这些被用作开关,因此简单而友善。 在所有其他方面,i386/pentium 指令集均未更改。 所以这回答了你的问题,没有偏离 32 位,没有 64 位地址。批准的答案解释了如何在需要 64 位值的情况下解释 32 位常量。
为什么像 BOUND 或 PUSHA 这样的 x86 传统指令在 64 位模式下不可用?
某些旧版 x86 指令(BOUND、PUSHA、AAA 等)无法在 64 位模式下使用是否有原因?是的,我知道,此类说明仅适用于兼容性问题,并且应该......
根据英特尔® 64 和 IA-32 架构优化参考手册,B.4 节(“英特尔® 微架构代号 Sandy Bridge 的性能调优技术”),亚秒...
为什么该程序的 32 位和 64 位编译版本以这种方式填充内存?
我试图更好地理解堆栈和堆的工作原理。 在比较同一程序的 32 位和 64 位编译版本时,我遇到了一个障碍。 在这两种情况下,我都使用了嘉宾 Fedor...
为什么我会收到“** stack crashing detector **”错误?
我正在尝试将此汇编函数与此 C++ 代码链接: 。文本 .global _Z7scambiaRiS_ _Z7scambiaRiS_: 推q%rbp 移动%rsp,%rbp 移动 (%rdi), %rax 移动 (%rsi), %rcx 移动%...
免责声明:我是初学者,这是我见过的最糟糕的语言 目标是解码消息。 每个字符由 8 个字节编码 7-8字节无关紧要,假设0 3-6字节索引 第二
我正在 Hack The Box Academy 上学习“汇编语言简介”模块,目前在“Shellcoding 工具”部分遇到问题。提示是:'上面的服务器模拟了一个
我正在使用 nasm 在汇编 x64 中创建一个简单的代码,但在我的算法中,我的函数内需要许多 while 和 for 循环。因此,我的代码充满了诸如loop1、loop2、loop3之类的标签......
我正在使用 QEMU 在 macOS 环境中的 x86_64 NASM 中为我的 64 位操作系统开发自定义引导加载程序。引导加载程序是两阶段的,旨在从磁盘加载操作系统。我有经验...
对于学校作业,我必须编写 x86 汇编代码,但我不能使用 gcc 来编译它,因为我的计算机是 x64 机器,而 gcc 只支持 x86 代码。 有没有一个命令可以...
我正在用C语言制作一个64位内存扫描库,我需要“扫描”共享对象所在的内存区域。为此,我需要获取模块的地址和大小,类似...
我一直在研究分页和访问控制如何在 x86-64 上工作,并且我正在尝试了解用于页面条目的 USER 标志与用户模式进程的内存访问之间的交互......
在BIOS将引导扇区加载到内存后,尝试通过预先计算引导扇区的地址来打印引导扇区中的字符
我对装配以及与之相关的一切都很陌生。我只知道寄存器如何工作以及如何对其进行基本操作的基础知识。我正在关注 cfenollosa/os-tutorial (githu...
我正在用 Rust 编写一个 x86_64 操作系统并在 qemu 电脑上测试它。我已经实现了 ELF 文件加载,并且我 100% 确定文件已正确加载和映射,因为我已经手动检查了内存。 我的问题...
我在 Windows 10 上使用 Visual Studio 2022。我的处理器:Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz 1.80 GHz。 这是代码: #包括 #包括 #包括 我在 Windows 10 上使用 Visual Studio 2022。我的处理器:Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz 1.80 GHz。 这是代码: #include <vector> #include <iostream> #include <time.h> using namespace std; void func(int* A, int na) { for (int k = 0; k < na; k++) for (int i = 0; i < na; i++) for (int j = 0; j < na; j++) A[j] = A[j] + 1; } int main() { int na = 5000; int* aint = new int[na]; func(aint, na); cout << aint[rand() % na]; delete[] aint; } MSVC 选项: cl /c /Zi /W3 /WX- /诊断:列 /sdl /O2 /Oi /GL /D NDEBUG /D _CONSOLE /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /Gy /arch:AVX2 / Zc:wchar_t /Zc:forScope /Zc:inline /permissive- /Fo"x64\Release\" /Fd"x64\Release c143.pdb" /external:W3 /Gd /TP /FC /errorReport:prompt /Qvec-report :2 源码.cpp MSVC 不对 j 循环进行矢量化。由于代码 1300:“循环体包含很少或没有计算”,循环的日志未矢量化。 MSVC CPU 时间为 17 秒,由于 Intel Advisor 诊断,j 循环未矢量化。 Intel 2024 C/C++ 编译器 CPU 时间为 7 秒,由于 Intel Advisor 诊断,j-loop 通过使用 AVX2 指令进行矢量化。我是否遗漏了应该在 MSVC 选项中设置的内容,或者 MSVC 2022 在自动矢量化方面就是那么愚蠢?您能举一个 MSVC 使用自动矢量化的例子吗?对于我尝试过的所有示例,MSVC 不会矢量化。 我尝试指定不同的增强指令集,但都不起作用。 你的循环很奇怪;最好的优化是展开外部循环,这样就有一个循环可以完成 A[j] += na*na; 的任务。 如果您以这种方式编写源代码,我希望编译器能够自动矢量化。 使用当前源,Clang 会自动矢量化,无需重新排列循环,并且一次仅添加 1。 GCC 将两者混合用于独立的 func,其中 na 是运行时变量。 将 func 内联到 main 中时,GCC 不会自动矢量化,其中 na = 5000 是编译时常量。 但它交换了一些循环,因此它在内循环中执行 add edx, 4,以 sub eax, 2 / jnz 作为循环条件,以 eax=2500 作为内循环计数器开始。 它仅在中间循环中从数组加载和存储,加载提升/存储沉入内部循环。 (中间循环像源一样运行 5000 次迭代)。只有外部循环实际递增指针,因此在指针递增之间有 5000 次加载/存储同一数组元素。 (外部循环条件是一个指针与指向数组末尾一位的指针进行比较,来自 lea rdi, [rax+20000]) 在 func 的独立非内联版本中,GCC 将 k 或 i 展开 2 并在 j 上进行矢量化,而不交换任何循环,因此它在嵌套循环中执行 A[j + 0..7] += 2;,循环遍历每次通过内循环时 std::vector。 GCC 给 main 一个隐式的 __attribute__((cold)),但是当内联到 void foo() 时,我们得到与 int main() 相同的代码,所以关键的区别似乎是 na 是一个编译时常量,而不是cold 属性(减少优化和/或偏爱大小而不是速度)。 MSVC 确实使用 size_t j(使用 -O2 -arch:AVX2)进行自动矢量化,所以也许它无法证明 32 位 j 符号扩展到 64 位指针宽度? 希望 MSVC 确实知道 j < na 条件使循环绝对是非无限的,这样它就可以避免内部循环内的符号扩展。 在带有 MSVC 19.40 的 Godbolt 上 movsxd 中唯一的 func 指令位于函数顶部以进行符号扩展 na,内部循环使用 64 位 rcx 作为计数器(无缘无故) ;计数不能高于 2^31 - 1,这样 REX 前缀就会浪费代码大小)。 我链接了int版本;取消注释 size_t 行即可查看 asm。 (滚动到底部;由于包含 <iostream>,MSVC 吐出了很多东西。我还包含了 GCC 和 Clang -O2 -march=x86-64-v3,这相当于您的 MSVC 命令:使用 AVX2+FMA3+BMI1/2 进行全面优化) 其他编译器不关心 int 与 size_t j,除非在汇编中有我没有注意到的差异。