我正在寻找英特尔数据表:英特尔®64和IA-32架构软件开发人员手册 ,我找不到它们之间的区别
在英特尔数据表中,我可以找到两个指令:
该指令可用于从128位存储器位置加载XMM寄存器,将XMM寄存器的内容存储到128位存储器位置,或在两个XMM寄存器之间移动数据.
唯一的区别是:
要将双四字移入或移出未对齐的存储单元,请使用MOVDQU指令.
和
要将打包的单精度浮点值移入或移出未对齐的内存位置,请使用MOVUPS指令.
但是我找不到两个不同指令的原因?
那么有人可以解释这个区别吗?
有没有更快的方法在一个128位xmm寄存器中存储两个x86 32位寄存器?
movd xmm0, edx
movd xmm1, eax
pshufd xmm0, xmm0, $1
por xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)
因此,如果EAX为0x12345678且EDX为0x87654321,则xmm0中的结果必须为0x8765432112345678.
谢谢
我有以下代码,这是我的应用程序的一部分的瓶颈.我所做的就是从另一个数据中减去Array.这两个阵列都有大约100000个元素.我正试图找到一种方法来使这更高效.
var
Array1, Array2 : array of integer;
.....
// Code that fills the arrays
.....
for ix := 0 to length(array1)-1
Array1[ix] := Array1[ix] - Array2[ix];
end;
Run Code Online (Sandbox Code Playgroud)
有人有建议吗?
假设我想将两个32位寄存器EAX作为低32位字和EDX高32位字放入RAX.我找到了一种方法:
shl rdx, 32
or rax, rdx
Run Code Online (Sandbox Code Playgroud)
只有当我们确定从32到61的位RAX为0时,此方法才有效.如果我们不确定,那么我们必须首先清除高32位字,如:
mov eax, eax //This instruction should clear the high 32 bit word of RAX
Run Code Online (Sandbox Code Playgroud)
这是最短路吗?
是否有一个asm x86-64指令执行此操作?
什么是最快的x86汇编代码来同步访问内存中的数组?
更确切地说:我们在内存中有一个malloc'ed连续单页区域,操作系统在我们的实验期间不会将该区域分页.一个线程将写入数组,一个线程将从数组中读取.数组很小,但大于你的cpu的原子写能力(因此需要一个单独的锁)
"最快":有效速度:不要只假设字节码的长度很重要,而是考虑锁的缓存行为和与周围代码有关的分支行为.
它必须在x86-32和/或x86-64上运行
它必须在XP之后(或后代)Windows,Linux自内核2.2或MaxOs X(在用户模式下)工作.
请不要"它取决于" - 回应:如果它取决于我在这里没有指定的任何东西,只需编写你自己的例子,并说明那个/那些情况下最快的.
邮政编码!(这是为了防止模糊的描述)
不仅要发布你的2行LOCK+ CMPXCHG比较和交换,还要告诉我们如何将它与一个线程中的读取指令和另一个线程中的写入指令集成.
如果您愿意,请解释您对缓存最优性的调整,以及如果分支目标依赖于(1)是否获得锁定(2)更大读取的第一个字节是什么,如何避免分支错误预测.
如果你喜欢区分多处理和任务切换:如果线程没有在2个cpus上执行但只是抓住一个线程,你的代码将如何执行?
宣言...
const
n = 2 shl 33
Run Code Online (Sandbox Code Playgroud)
n在没有编译器投诉的情况下将常数设置为值4!
也...
Caption := IntToStr(2 shl 33);
Run Code Online (Sandbox Code Playgroud)
...返回4而不是8589934592.看起来编译器计算如下:
2 shl 33 = 2 shl(33和$ 1F)= 4
但没有任何警告或溢出.
如果我们声明:
const
n: int64 = 2 shl 33;
Run Code Online (Sandbox Code Playgroud)
常数中的数字仍然是4而不是8589934592.
任何合理的工作?
假设我想从gs:$3064位模式的绝对地址读取,所以asm代码看起来像:
asm
mov rax, gs:[$30]
end;
Run Code Online (Sandbox Code Playgroud)
...和编译器将此代码翻译为......
65 48 8B 05 30 00 00 00 mov rax,gs:[rel $00000030]
Run Code Online (Sandbox Code Playgroud)
但我不想使用相对地址(rip + $30).我希望编译器使用绝对地址并以这种方式编译:
65 48 8B 04 25 30 00 00 00 mov rax,gs:[+$0030]
Run Code Online (Sandbox Code Playgroud)
(如果我使用gs:前缀,它是一样的!)
我该怎么做呢?
编辑:
我知道解决方法.我问是否存在任何命令告诉编译器将位置称为绝对而非相对.
编辑
到现在为止还挺好... :)
drhirsch帮我找到了命令,现在编译器翻译:
mov rax, gs:[abs qword ptr $30]
or
mov rax, gs:[abs $30]
Run Code Online (Sandbox Code Playgroud)
对此:
6548A13000000000000000 mov rax,[qword $0000000000000030]
Run Code Online (Sandbox Code Playgroud)
这几乎是好的:)因为我想要短的32位操作码(看上面的操作码)更长的64位操作码.
有没有办法告诉编译器使用短32位地址操作码而不是长?
CharUpper有人知道 Delphi 10.3 中的声明与CharUpperWDelphi 10.4 中不同的原因吗?
Delphi 10.3 中的正确声明
var
chr :WideChar;
begin
chr := WideChar(CharUpperW(PWideChar('a'))); //chr = 'A'
// chr := WideChar(CharUpperW(WideChar('a'))); //raise exeption: "access violation...
Run Code Online (Sandbox Code Playgroud)
Delphi 10.4 中的正确声明
var
chr :WideChar;
begin
// chr := WideChar(CharUpperW(PWideChar('a'))); //raise exeption: "access violation...
chr := WideChar(CharUpperW(WideChar('a'))); //chr = 'A'
Run Code Online (Sandbox Code Playgroud)
编辑:Remy Lebeau 对 PWideChar 的解释是正确的,但 Delphi 10.4 版和更早版本仍然存在差异!
Lebeau解释代码示例在10.4版本及更早版本中编译,但函数的输出不同。10.4 之前的所有版本都得到正确的输出“A”!
var
char , chr : WideChar;
begin
chr := 'a';
char := WideChar(CharUpperW(PWideChar(chr)));
end;
Run Code Online (Sandbox Code Playgroud)
10.4 下的此示例无法正常工作,输出是随机字符。
当然...函数的声明 …
在Delphi 2010下(也可能在D2009下),默认字符串类型是UnicodeString.
但是,如果我们宣布......
const
s :string = 'Test';
ss :string[4] = 'Test';
Run Code Online (Sandbox Code Playgroud)
...然后第一个字符串s如果声明为UnicodeString,但第二个ss声明为AnsiString!
我们可以检查一下:SizeOf(s[1]);将返回大小2和SizeOf(ss[1]); 将返回大小1.
如果我宣布......
var
s :string;
ss :string[4];
Run Code Online (Sandbox Code Playgroud)
...比我想要的ss也是UnicodeString类型.
WideString[4]或UnicodeString[4].我想用在句子中的下D2010我的测试案例.
如果我想写Param.Value变量然后编译器报告错误2064,但允许从同一记录写入Param.Edit.text,为什么?
测试用例:
type
//
TparamSet = (param_A, param_B, param_C, param_D, param_E, param_F);
TParam = record
Edit :TEdit;
Value :integer;
end;
var
dtcp :array [TparamSet] of TParam;
procedure ResetParams;
var
Param :TParam;
A :Integer;
begin
for Param in dtcp do
begin
Param.Edit.text:= 'Test'; //No problem
A := Param.Value; //No problem
Param.Value := 0; //Error: E2064 Left side cannot be assigned to;
end;
end;
Run Code Online (Sandbox Code Playgroud) delphi ×6
assembly ×5
x86 ×5
sse ×3
delphi-2010 ×2
x86-64 ×2
64-bit ×1
basm ×1
bit-shift ×1
delphi-xe2 ×1
for-in-loop ×1
mov ×1
move ×1
performance ×1
simd ×1
widestring ×1