我在一个系统上观察到,当设置一个常数值0与一个常量值1或一个dynamic值相比时, std::fill在一个大的std::vector<int>上显着且一致地慢: 5.8 GiB / s vs 7.5 GiB / s 但是,对于更小的数据大小,结果是不同的,其中fill(0)更快: 使用多于一个线程,在4 GiB数据大小时, fill(1)显示的斜率更高,但达到比fill(0) (51 GiB / s vs 90 GiB / s)低得多的峰值: 这引起了第二个问题,为什么fill(1)的峰值带宽要低得多。 这个testing系统是双通道Intel Xeon CPU E5-2680 v3,设置为2.5 GHz(通过/sys/cpufreq ),带有8×16 GiB DDR4-2133。 我testing了GCC 6.1.0( -O3 )和Intel编译器17.0.1( -fast ),都得到了相同的结果。 GOMP_CPU_AFFINITY=0,12,1,13,2,14,3,15,4,16,5,17,6,18,7,19,8,20,9,21,10,22,11,23为组。 Strem / add / 24线程在系统上获得85 GiB / s。 我能够在不同的Haswell双套接字服务器系统上重现这种效果,但没有任何其他体系结构。 例如,在Sandy Bridge EP上,内存性能是相同的,而在caching中fill(0)要快得多。 这里是重现的代码: #include […]
有关x86 CPU权限环的一些问题: 为什么大多数操作系统不使用环1和环2? 只是维护与其他体系结构的代码兼容性,还是有更好的理由? 有没有实际使用这些戒指的操作系统? 还是完全没有使用?
我有兴趣编写一个x86拆信器作为一个教育项目。 我发现唯一真正的资源是Spiral Space的“ 如何编写反汇编程序 ”。 虽然这给出了反汇编器各个组件的高级描述,但我对一些更详细的资源感兴趣。 我也快速浏览了NASM的源代码,但是这是一个重量级的学习。 我意识到这个项目的主要挑战之一是我将不得不处理的相当大的x86指令集。 我也感兴趣的基本结构,基本的反汇编链接等。 任何人都可以指出我写的x86反汇编程序的任何详细的资源?
据说leave指令是一样的: mov esp,ebp pop ebp 但是什么是mov esp,ebp在这里? 这对我来说似乎并不合适
我在gdb的目标可执行文件之外,我甚至没有对应于该目标的堆栈。 无论如何,我想要单步执行,这样我就可以validation我的汇编代码中发生了什么,因为我不是x86汇编的专家。 不幸的是,gdb拒绝做这个简单的汇编级debugging。 它允许我在适当的断点处设置和停止,但是一旦我尝试单步启动,gdb会报告错误“无法find当前函数的边界”,EIP不会改变。 额外细节: 机器代码是由gcc asm语句生成的,我将它从objdump -d的输出复制到执行的内核内存位置。 我不介意使用加载器将对象代码加载到重定位地址的简单方法,但请记住加载必须在内核模块中完成。 我想另外一个select是产生一个假的内核模块或debugging信息文件给gdb,使它相信这个区域在程序代码中。 gdb在内核可执行文件本身上工作正常。 (对于那些真正想知道的人,我在运行时将代码插入到VMware VM内的Linux内核数据空间中,并通过gdb从gdb远程debugging内核,通过VMware Workstation的内置gdb存根对其进行debugging。注意我没有编写内核利用;我是一个安全研究生写一个原型。) (我可以在我的程序集里面的每条指令上设置一个断点,这样做可能会花费一些时间,因为x86汇编指令的大小会有所不同,并且每次重启时程序集的位置都会改变。
我的公司已经开始有很多客户打来电话了,因为我们的程序在他们的系统上发生访问冲突。 SQLite 3.6.23.1发生崩溃,我们将其作为应用程序的一部分发布。 (我们发布了一个自定义构build,以便使用与应用程序其余部分相同的VC ++库,但是这是股票SQLite代码。) 当pcache1Fetch执行call 00000000时发生崩溃,如WinDbg调用堆栈所示: 0b50e5c4 719f9fad 06fe35f0 00000000 000079ad 0x0 0b50e5d8 719f9216 058d1628 000079ad 00000001 SQLite_Interop!pcache1Fetch+0x2d [sqlite3.c @ 31530] 0b50e5f4 719fd581 000079ad 00000001 0b50e63c SQLite_Interop!sqlite3PcacheFetch+0x76 [sqlite3.c @ 30651] 0b50e61c 719fff0c 000079ad 0b50e63c 00000000 SQLite_Interop!sqlite3PagerAcquire+0x51 [sqlite3.c @ 36026] 0b50e644 71a029ba 0b50e65c 00000001 00000e00 SQLite_Interop!getAndInitPage+0x1c [sqlite3.c @ 40158] 0b50e65c 71a030f8 000079ad 0aecd680 071ce030 SQLite_Interop!moveToChild+0x2a […]
从Pentium Pro(P6微架构)开始,Intel重新devise了微处理器,并在旧的CISC指令下使用了内部RISC内核。 由于Pentium Pro的所有CISC指令被分成较小的部分(uops),然后由RISC内核执行。 在开始的时候,我很清楚Intel决定隐藏新的内部架构,并迫使程序员使用“CISC shell”。 由于这个决定,英特尔可以完全重新devise微处理器架构,而不会破坏兼容性,这是合理的。 不过我不明白一件事,为什么Intel这么多年来还隐藏着一套内部RISC指令? 为什么他们不让程序员像使用旧的x86 CISC指令集一样使用RISC指令? 如果英特尔长期保持向后兼容性(我们在64位模式旁仍然有虚拟8086模式),为什么不让我们编译程序,以便它们能够绕过CISC指令并直接使用RISC内核? 这会慢慢地放弃x86指令集的自然方式,现在已经废弃了(这是英特尔决定使用RISC内核的主要原因吧?)。 看看我看到的新的Intel Core i系列,他们只扩展了CISC指令集,添加了AVX,SSE4等等。
rep; nop什么? rep; nop意思? 这与pause指令是一样的吗? 它是否与rep nop (没有分号)相同? 简单的nop指令有什么区别? 它在AMD和Intel处理器上的performance有何不同? (奖金)这些说明的正式文件在哪里? 这个问题的动机 在对另一个问题的评论进行了一些讨论之后,我意识到我不知道是什么rep; nop; rep; nop; 是指在x86(或x86-64)程序集中。 而且我在网上找不到一个好的解释。 我知道rep是一个前缀,意思是“重复下一个指令cx次” (或者至less是在旧的16位x86汇编中)。 根据维基百科的这个汇总表 ,似乎rep只能用于movs , cmps , cmps , lods , scas (但是也许这个限制在更新的处理器上被删除了)。 因此,我认为rep nop (不用分号)会重复一次nop操作。 然而,经过进一步的search,我更加困惑。 rep; nop似乎是rep; nop rep; nop和pause 映射到完全相同的操作码 , pause有一点不同,只是nop行为。 2005年的一些旧邮件说了不同的事情: “尽量不要烧太多的权力” “这相当于只用2字节编码的”nop“。 “这是intel的魔法,它就像'但是让另一个HT兄弟运行'” “在intel和intel Athlon上快速填充是暂停的” 有了这些不同的意见,我不明白正确的意思。 它被用在Linux内核(在i386和x86_64上 )以及这个注释: /* REP NOP […]
可能重复: x86汇编 – 'testl'eax反对eax? 我对汇编语言编程非常新,而且我正在尝试读取二进制生成的汇编语言。 我跑过了 test %eax,%eax 或者test %rdi, %rdi等等。我很困惑这是干什么的。 %eax, %eax的值是不是相同? 什么是testing? 我读了一个地方,它正在做AND操作…..但由于它们是相同的价值,不是它只是返回%eax ? 以下是我发现这个用法的一个例子: 400e6e: 85 c0 test %eax,%eax 400e70: 74 05 je 400e77 <phase_1+0x23> 如果这两个值相比较的话,我认为是跳跃的……好吧,因为%eax本身是好的,在什么情况下我们不会跳跃? 我是一般的编程初学者,所以如果有人能向我解释这一点,我将非常感激。 谢谢!
我想反汇编我有一个可启动的x86磁盘的MBR(前512字节)。 我已经使用MBR复制到一个文件 dd if=/dev/my-device of=mbr bs=512 count=1 任何可以反汇编文件mbr的Linux实用程序的build议?