我正在用汇编语言做一些练习,我发现了一个关于优化的问题,我无法弄清楚.任何人都可以帮助我
所以问题是优化以下汇编代码:
----------------------------例1 --------------------- ----
mov dx, 0 ---> this one I know-> xor dx,dx
Run Code Online (Sandbox Code Playgroud)
----------------------------例题--------------------- ---
cmp ax, 0
je label
Run Code Online (Sandbox Code Playgroud)
----------------------------示例3 --------------------- ----
mov ax, x
cwd
mov si, 16
idiv si
Run Code Online (Sandbox Code Playgroud)
---->在这个例子中我能想到的最多的是idiv 16的最后两行,但我不确定
----------------------------范例4 --------------------- ----
mov ax, x
mov bx, 7
mul bx
mov t, ax
Run Code Online (Sandbox Code Playgroud)
----------------------------例5 --------------------- ------
mov si, offset array1
mov di, offset array2
; for i = 0; i < n; ++i
do:
mov bx, [si]
mov [di], bx
add si, 2 …
Run Code Online (Sandbox Code Playgroud) 如果我想将 2 个无符号字节从内存移动到 32 位寄存器中,我可以用MOV
指令而不用模式切换来做到这一点吗?
我注意到您可以使用MOVSE
和MOVZE
说明来做到这一点。例如,通过MOVSE
编码0F B7
将 16 位移动到 32 位寄存器。不过,它是一个 3 周期指令。
或者,我想我可以将 4 个字节移动到寄存器中,然后以某种方式仅 CMP 中的两个。
在 32 位 x86 上检索和比较 16 位数据的最快策略是什么?请注意,我主要进行 32 位操作,因此我无法切换到 16 位模式并留在那里。
仅供初学者参考:这里的问题是 32 位 Intel x86 处理器可以处理MOV
8 位数据和 16 位 OR 32 位数据,具体取决于它们所处的模式。这种模式称为“D 位”设置。您可以使用特殊前缀 0x66 和 0x67 来使用非默认模式。例如,如果您处于 32 位模式,并且您使用 0x66 作为指令前缀,这将导致操作数被视为 16 位。唯一的问题是这样做会导致性能下降。
基于对维基百科条目以及英特尔手册,rdpmc
应提供给只要用户模式进程bit 8
的CR4
设置.但是,即使设置了该位general protection
,尝试rdpmc
从用户空间运行时仍然会遇到错误.
我Intel X3470
在内核上运行8 核2.6.32-279.el6.x86_64
.
这是我试图执行的用户模式程序:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sched.h>
#include <assert.h>
uint64_t
read_pmc(int ecx)
{
unsigned int a, d;
__asm __volatile("rdpmc" : "=a"(a), "=d"(d) : "c"(ecx));
return ((uint64_t)a) | (((uint64_t)d) << 32);
}
int main(int ac, char **av)
{
uint64_t start, end;
cpu_set_t cpuset;
unsigned int c;
int i;
if (ac != 3) {
fprintf(stderr, "usage: …
Run Code Online (Sandbox Code Playgroud) 您好,我有以下 x86-Assembly:
8048062: 31 c0 xor eax,eax
8048064: 89 d8 mov eax,ebx
8048066: b8 01 00 00 00 mov eax,0x1
804806B: cd 80 int 0x80
Run Code Online (Sandbox Code Playgroud)
我想了解十六进制操作码。我在这里读到,b8
并且89
是 mov-instructions。但我不明白第二部分是89 d8
什么d8
?是d8
eax 和ebx 吗?所以 d 是 eax 而 8 是 ebx?但为什么在第一行 eax 和eax == c0
?b8 01 00 00 00
寄存器的第三行在哪里?
为什么以下行是正确的?
8048066: b8 01 00 00 00 mov eax,0x1
Run Code Online (Sandbox Code Playgroud)
为什么不:
b8 00 00 00 01 ?
Run Code Online (Sandbox Code Playgroud)
eax 分为:
eax …
Run Code Online (Sandbox Code Playgroud) 我浏览了与此事有关的不同答案,但我仍然没有得到它.我尝试了以下解决方案:1."我很抱歉,我忘了回答这个问题.经过几天谷歌搜索我发现,这个问题是由超线程(或超级v)引起的.我决定编辑我的启动. ini文件,可选择启动超线程启动窗口.我按照本教程:http://blogs.msdn.com/b/virtual_pc_guy/archive/2008/04/14/creating-a-no-hypervisor-boot- entry.aspx,现在一切都很完美"
转到控制面板→程序和功能.单击"打开和关闭窗口功能".一个窗口打开.取消选中Hyper-V选项并重新启动系统.现在,您可以毫无错误地启动HAXM安装."
以下是与这些解决方案相关的问题:1.对于此解决方案,在我的命令提示符中,没有"hypervisorlaunchtype"行.
顺便说一句,我的电脑支持虚拟化技术.我使用英特尔(R)处理器识别实用程序来了解这一点.有人,请帮帮我.
我不知道任何真正的汇编,但可以读取GCC -S
输出来评估给定C代码的实际成本.
这个问题并不是关于分析和基准的问题,而是教育问题.我需要有人来解释为什么[1]片段不比第二片段快.
嗯,过去常常这样想:"是的,像MUL这样的操作非常昂贵,但是如果一个组件比另一个组件大X倍,它应该更慢".
在我遇到这两个之前,这是真的:
unsigned char bytes[4] = {0, 0, 0, 5};
// 1
int32_t val = *((int32_t*)bytes);
/* produces:
leaq -16(%rbp), %rax
movl (%rax), %eax
movl %eax, -4(%rbp)
movl $0, %eax
*/
// 2
val = bytes[3] |
(bytes[2] << 8) |
(bytes[1] << 16) |
(bytes[0] << 24);
/* produces:
movzbl -13(%rbp), %eax
movzbl %al, %eax
movzbl -14(%rbp), %edx
movzbl %dl, %edx
sall $8, %edx
orl %eax, %edx
movzbl -15(%rbp), %eax
movzbl %al, %eax
sall $16, …
Run Code Online (Sandbox Code Playgroud) 我试图了解D flag
在 x86-64 代码中使用时代码段描述符中的工作原理。它设置在D/B
代码段描述符的第 22 位,如下图所示:
D/B(默认操作大小/默认堆栈指针大小和/或上限)标志
根据段描述符是可执行代码段、向下扩展数据段还是堆栈段执行不同的功能。(对于 32 位代码和数据段,此标志应始终设置为 1,对于 16 位代码和数据段,应始终设置为 0。)
• 可执行代码段。该标志称为 D 标志,它表示段中指令引用的有效地址和操作数的默认长度。如果设置了标志,则假定为 32 位地址和 32 位或 8 位操作数;如果清楚,则假定为 16 位地址和 16 位或 8 位操作数。指令前缀 66H 可用于选择默认值以外的操作数大小,前缀 67H 可用于选择默认值以外的地址大小。
所以我试图了解它影响哪些 x86-64 指令以及如何影响?
附注。当我尝试通过设置该位来运行一些测试(在 Windows 内核中)时,操作系统立即出现三重故障。
我创建了一个 python 脚本,它从文件中读取数据并从中提取所需的数据,问题是脚本在我的 i5 (Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz) 笔记本电脑上耗时 37 秒但是在具有 CPU(Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz)的服务器上需要 70 秒。
服务器的 CPU 有 40 个内核,因此它执行任务的速度应该比我的笔记本电脑快。两个系统都运行 ubuntu 18.04 操作系统。
该脚本正在使用多处理,服务器是我的另一个系统,它没有承受更高的负载。我的笔记本电脑都有 SSD 和 HHD(操作系统安装在 SSD 中),但我已将文件放在 HDD 驱动器中,脚本从中读取数据,而服务器只有 HDD。文件大小约为 1 GB,我用 1000 条记录测试了性能。
1) https://www.youtube.com/watch?v=0Q2wv6saL3Q - 在我的 40 核服务器上测试脚本。
2) https://www.youtube.com/watch?v=hSInldq1uRY - 在她的 8 核计算机上测试相同的脚本
以下代码在 for 循环中运行,同时从 1GB 文件中读取数据,目标方法使用漂亮的汤从我从文件中获取的 doc 中提取数据。
t0 = multiprocessing.Process(target=get_domain, args=(record.url, processedData))
t1 = multiprocessing.Process(target=getTLD, args=(record.url, processedData))
t2 = multiprocessing.Process(target=geturlscheme, args=(record.url, processedData))
t3 = multiprocessing.Process(target=getAllemails, …
Run Code Online (Sandbox Code Playgroud) 如何监控进程的 SIMD(SSE、AVX、AVX2、AVX-512)指令使用量?例如,htop
可用于监控一般的 CPU 使用情况,但不是专门的 SIMD 指令使用情况。
我正在编写一个用户模式工具,用于监视 CPU 标志的更改,例如来自 CR0 的 WP 和来自 CR4 的 SMEP。我可以使用读取 WP 位,smsw %rax
但没有用于读取 CR4(或其 SMEP 位)的类似操作码。
有没有办法从用户模式获取 SMEP 的状态?
intel ×10
assembly ×7
x86 ×6
performance ×4
linux ×2
linux-kernel ×2
cpu-usage ×1
haxm ×1
optimization ×1
python ×1
windows ×1
x86-64 ×1