(如果是这样的话,我会自己做的.)
我的问题:
为方便起见,我倾向于避免间接/索引寻址模式.
作为替代,我经常使用立即,绝对或寄存器寻址.
代码:
; %esi has the array address. Say we iterate a doubleword (4bytes) array.
; %ecx is the array elements count
(0x98767) myloop:
... ;do whatever with %esi
add $4, %esi
dec %ecx
jnz 0x98767;
Run Code Online (Sandbox Code Playgroud)
在这里,我们有一个序列化的组合(dec和jnz),它可以防止正常的乱序执行(依赖).
有没有办法避免/破坏dep?(我不是装配专家).
我目前正在学习汇编语言,我有一个输出"Hello World!"的程序.:
section .text
global _start
_start:
mov ebx, 1
mov ecx, string
mov edx, string_len
mov eax, 4
int 0x80
mov eax, 1
int 0x80
section .data
string db "Hello World!", 10, 0
string_len equ $ - string
Run Code Online (Sandbox Code Playgroud)
我理解这段代码的工作原理.但是,现在,我希望显示10倍的线.我在互联网上看到的代码循环如下:
mov ecx, 5
start_loop:
; the code here would be executed 5 times
loop start_loop
Run Code Online (Sandbox Code Playgroud)
问题:我试图在我的代码上实现循环,但它输出一个无限循环.我还注意到循环需要ECX和写入功能也需要ECX.显示10次"Hello World!"的正确方法是什么??
这是我当前的代码(产生无限循环):
section .text
global _start
_start:
mov ecx, 10
myloop:
mov ebx, 1 ;file descriptor
mov ecx, string
mov …Run Code Online (Sandbox Code Playgroud) 在汇编程序和处理程序的研究中,有一件事把我带出来,如何完成指令:
add mem, 1
Run Code Online (Sandbox Code Playgroud)
在我的脑海中,处理器无法加载内存值并在同一指令期间处理算术运算.所以我觉得它发生在:
mov reg, mem
add reg, 1
mov mem, reg
Run Code Online (Sandbox Code Playgroud)
如果我考虑使用RISC Pipeline的处理器,我们可以观察一些停顿.对于简单的指令来说,这是令人惊讶的i++:
| Fetch | Decode | Exec | Memory | WriteB |
| Fetch | | | Decode | Exec | Memory | WriteB |
| Fetch | | | | Decode | Exec | Memory | WriteB |
Run Code Online (Sandbox Code Playgroud)
(正如我在Patterson的书" 计算机体系结构:定量方法"中所读到的,寄存器在解码 uOp,存储/加载到存储器uOp中读取,我们允许自己在存储器uOp中获取寄存器的值.)
我对吗?还是现代处理器有更具效的方法来做到这一点?
我正在尝试找到无符号 64 位 int 的前导位。我正在使用 BSR,因为我的处理器没有 LZCNT 指令。我的问题是,一旦输入正好是 2^32,它就会返回 2^64 作为前导位值,然后循环返回输出,直到 2^64。
这是我的代码:
unsigned long int LeadingBit(unsigned long int a) {
if(a==0)
return 0;
unsigned long int nlb;
asm (
"BSR %1, %0 \n"
: "=r" (nlb)
: "mr" (a)
: "cc"
);
return 1<<nlb;
}
Run Code Online (Sandbox Code Playgroud)
这段代码的目的是能够输入一个64位整数,并让它返回前导1的位置的值。例如:a = 65(1000001)返回1000000。
我有两个问题.第一个:'或'与'cmp'有什么区别?我已经看过了两个,看起来他们做了同样的事情.我的第二个问题:做什么
or al, al
Run Code Online (Sandbox Code Playgroud)
意思?它不应该一直返回真(如x == x)吗?
在我毕业的计算机架构上,教授谈到了 MIPS 中的流水线,但也说由于 x86 指令集的某些情况(我不太记得了),x86 处理器需要有一个额外的逻辑来预处理组装指令和管道。
我不是在寻找直接的数字答案,而不是寻找有关该主题的文档或提示:正在做什么来翻译 x86 指令以允许流水线操作,此逻辑如何工作等。
谢谢一堆。
我读过这个,我的问题很相似但有点不同.
注意,我知道C++ 0x并不能保证这一点,但我特别要求像x86-64这样的多核机器.
假设我们有2个线程(固定到2个物理内核)运行以下代码:
// I know people may delcare volatile useless, but here I do NOT care memory reordering nor synchronization/
// I just want to suppress complier optimization of using register.
volatile int n;
void thread1() {
for (;;)
n = 0xABCD1234;
// NOTE, I know ++n is not atomic,
// but I do NOT care here.
// what I cares is whether n can be 0x00001234, i.e. in the middle of the update from core-1's …Run Code Online (Sandbox Code Playgroud) 当我在https://godbolt.org上使用不同的编译器时,我注意到编译器生成这样的代码是很常见的:
push rax
push rbx
push rcx
call rdx
pop rcx
pop rbx
pop rax
Run Code Online (Sandbox Code Playgroud)
我理解每个push或pop做两件事:
所以在我们上面的例子中,我假设 CPU 实际上在做 12 次操作(6 次移动,6 次加/减),不包括call. 组合添加/订阅不是更有效吗?例如:
sub rsp, 24
mov [rsp-24], rax
mov [rsp-16], rbx
mov [rsp-8], rcx
call rdx
mov rcx, [rsp-8]
mov rbx, [rsp-16]
mov rax, [rsp-24]
add rsp, 24
Run Code Online (Sandbox Code Playgroud)
现在只有 8 次操作(6 次移动,2 次加/减),不包括call. 为什么编译器不使用这种方法?
什么更快:
add DWORD PTR [rbp-0x4],1
Run Code Online (Sandbox Code Playgroud)
或者
mov eax,DWORD PTR [rbp-0x4]
add eax,1
mov DWORD PTR [rbp-0x4],eax
Run Code Online (Sandbox Code Playgroud)
我已经看到编译器生成的第二个代码,所以也许调用add寄存器要快得多?
是x>>2不是更快x>>31?换句话说,sar x, 2比sar x, 31? 我做了一些简单的测试,它们似乎具有相同的速度。我将不胜感激任何确凿的证据。