我开始学习汇编程序,这对我来说并不合乎逻辑.
为什么我不能在寄存器中使用多个更高的字节?
我理解rax- > eax- > 的历史原因ax,所以让我们关注新的 64位寄存器.例如,我可以使用r8和r8d,但为什么不r8dl和r8dh?同样适用于r8w和r8b.
我最初的想法是,我可以使用8个r8b在同一时间寄存器(就像我可以做的al,并ah在同一时间).但我不能.并且使用r8b使完整的r8寄存器"忙".
这提出了一个问题 - 为什么?如果您不能同时使用其他部件,为什么还只需要使用寄存器的一部分?为什么不保持只r8忘记下部?
我试图分配变量来注册这里是代码:
ORG 100h
var1 DB 10 ;
var2 DB 20 ;
MOV BX,var1 ; error : operands do not match: 16 bit register and 8 bit address
RET
END
Run Code Online (Sandbox Code Playgroud)
但如果换掉第4行:
MOV BL, var1;
Run Code Online (Sandbox Code Playgroud)
有用.所以我的问题是为什么我不能将8位变量移动到更大的16位寄存器中?
注意:
我是汇编的新手,想知道如何在EMU8086中编写一个程序,在每次运行时打印一个不同的随机数.是否可以在不使用中断的情况下完成?
我想知道是否有任何指令序列,而不使用任何其他寄存器将RAX的低32位复制到其高32位.当然,我也希望EAX完好无损.
先感谢您.
考虑一个简单的指令,例如
mov RCX, RDI # 48 89 f9
Run Code Online (Sandbox Code Playgroud)
48 是 x86_64 的 REX 前缀。它不是LCP。但请考虑添加 LCP(用于对齐目的):
.byte 0x67
mov RCX, RDI # 67 48 89 f9
Run Code Online (Sandbox Code Playgroud)
67 是地址大小前缀,在本例中用于没有地址的指令。该指令也没有立即数,并且不使用 F7 操作码(假 LCP 停止;F7 将是 TEST、NOT、NEG、MUL、IMUL、DIV + IDIV)。假设它也不跨越 16 字节边界。这些是 Intel优化参考手册中提到的 LCP 停顿情况。
该指令是否会导致 LCP 停顿(在 Skylake、Haswell 等上)?两个 LCP 怎么样?
我日常驾驶的是 MacBook。所以我无法访问 VTune,也无法查看 ILD_STALL 事件。还有其他方法可以知道吗?
performance assembly x86-64 cpu-architecture micro-optimization
示例:0xAABBCCDD将变为0xDDCCBBAA
由于第一次XOR操作中的访问冲突异常,我的程序崩溃了.
似乎有一个更好的天真解决方案,使用移位或旋转,但无论如何,这里是代码:
;; #########################################################################
.486
.model flat, stdcall
option casemap :none ; case sensitive
;; #########################################################################
include \masm32\include\masm32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
.code
;; The following program will flip the sequence of the bytes in the eax
;; example : 0xAABBCCDD will turn into 0xDDCCBBAA
start:
MOV eax, 0AABBCCDDh
XOR BYTE PTR [eax], al ;; Swap first byte and last byte
XOR al, BYTE PTR [eax]
XOR BYTE PTR [eax], al
XOR BYTE PTR …Run Code Online (Sandbox Code Playgroud) 我想用AVX2指令加快以下操作,但我无法找到一种方法.
我得到了uint64_t data[100000]一大堆uint64_t和一个unsigned char indices[100000]字节数组.我想输出一个数组uint64_t Out[256],其中第i个值是所有data[j]这样的xor index[j]=i.
我想要的直接实现是这样的:
uint64_t Out[256] = {0}; // initialize output array
for (i = 0; i < 100000 ; i++) {
Out[Indices[i]] ^= data[i];
}
Run Code Online (Sandbox Code Playgroud)
我们可以使用AVX2指令更有效地实现这一点吗?
编辑:这是我的代码现在的样子
uint64_t Out[256][4] = {0}; // initialize output array
for (i = 0; i < 100000 ; i+=4) {
Out[Indices[i ]][0] ^= data[i];
Out[Indices[i+1]][1] ^= data[i+1];
Out[Indices[i+2]][2] ^= data[i+2];
Out[Indices[i+3]][3] ^= data[i+3];
}
Run Code Online (Sandbox Code Playgroud) 是否有任何整数2操作数x86-64指令仅将其第一个操作用作目标,而不用作源+目标1或仅源2,并且p0156在Intel Haswell和/或更高版本的CPU上运行?
对mov指令不感兴趣,即mov名称中的任何内容。
例如,BMI1 blsi eax, edx是2操作数,目标为只写,但只能在Skylake的端口1或端口5上执行。
1大多数指令都属于此类,例如,add eax, ebx代表eax = eax + ebx。
2少数2个操作数整数指令仅将其第一个操作数用作源,例如cmp eax, ebx。
如果我编译以下 C++ 程序:
int baz(int x) { return x * x; }
Run Code Online (Sandbox Code Playgroud)
在 clang 15 中,我得到:
baz(int):
mov eax, edi
imul eax, edi
ret
Run Code Online (Sandbox Code Playgroud)
而 gcc 12.2 给了我:
baz(int):
imul edi, edi
mov eax, edi
ret
Run Code Online (Sandbox Code Playgroud)
(请参阅GodBolt)
这两种实现是否完全等同,而只是任意选择的问题?如果它们不等价,它们的差异如何体现或影响我的程序?我的意思是,就 CPU 状态副作用、其他指令的延迟、内联期间的行为等而言。
我很难将数据从内存移动到的另一个内存中bss。我的实现有些起作用,但是当移动一些奇怪的字符出现在前几个字节中时,我的字符串的一半也丢失了,而另一半还不错。
这是我打印输出时获得的值message==?F@elcome to the new life
我需要所有帮助,我想念什么?我检查了一百遍代码。
section .data
hello: db "Hello, Welcome to the new life! Lets begin the journey.",10
hello_len: equ $ - hello
section .bss
message: resb 255
section .text
mov rdi, hello
mov rsi, message
msg_into_message:
cmp byte [rdi], 10 ; hello ends with a new line char
je end_count
mov al, byte [rdi]
mov byte [rsi], al
inc rsi
inc rdi
jmp msg_into_message
end_count:
mov [message], rsi
ret
; Prints …Run Code Online (Sandbox Code Playgroud)