AFAIK X86-64增加了大量的通用寄存器的那些从英特尔86(派生rax,rcx等),被称为r8- r15.
他们为什么要这样命名新的寄存器?为什么不遵循现有的命名规则,并呼吁他们一样rfx,rgx...?
我一直在研究关于x86-64的ABI,编写汇编以及研究堆栈和堆如何工作的问题.
给出以下代码:
#include <linux/seccomp.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
// execute the seccomp syscall (could be any syscall)
seccomp(...);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在Assembly for x86-64中,这将执行以下操作:
seccomp.call seccomp.seccomp返回时,它可能是一,在C将调用exit(0)据我所知.我想谈谈上面第三步和第四步之间发生的事情.
我目前拥有当前正在运行的进程的堆栈,它在寄存器和堆栈中有自己的数据.用户空间进程如何将执行转交给内核?内核只是在调用时接收,然后从同一堆栈中推送并弹出?
我相信我听说系统调用不会立即发生,而是在某些CPU滴答或中断时发生.这是真的?例如,在Linux上,这是怎么发生的?
一般来说,按照每个寄存器的用途编码x86汇编是否必要或更容易?
x86架构中的寄存器每个都是首先设计用于特殊目的,但现代编译器似乎并不关心它们的使用(除非在某些特殊条件下,例如REP MOV或MUL).
那么,取决于每个寄存器的用途,代码是更容易还是更优化?(不管与某些寄存器相同的特殊指令(或编码))
例如(我可以改用REP MOVSB或LODSB STOSB,但只是为了演示):
第一个代码:
LEA ESI,[AddressOfSomething]
LEA EDI,[AddressOfSomethingElse]
MOV ECX,NUMBER_OF_LOOP
LoopHere:
MOV AL,[ESI]
ADD AL,8
MOV [EDI],AL
ADD ESI,1
ADD EDI,1
CMP AL,0
JNZ LoopHere
TheEnd:
;...
Run Code Online (Sandbox Code Playgroud)
第二代码:
LEA ECX,[AddressOfSomething]
LEA EDX,[AddressOfSomethingElse]
MOV EBX,NUMBER_OF_LOOP
LoopHere:
MOV AL,[ECX]
ADD AL,8
MOV [EDX],AL
ADD ECX,1
ADD EDX,1
CMP AL,0
JNZ LoopHere
TheEnd:
;...
Run Code Online (Sandbox Code Playgroud)
我使用的编译器 - Visual Studio 2015在执行这样的任务时通常使用第二种方法,它不使用寄存器取决于它的用途,相反,编译器只根据其"volatile"选择使用哪个寄存器或"非易失性"特征(在调用函数后).因此,所有高级编程语言编程软件反汇编都使用第二种方法.
另一个有趣的事实是,在ARM语言中,GPR都具有相同的用途,并且被命名为R0-R7,这意味着当代码使用它时,代码将更类似于第二代码.
总而言之,我的观点是这两个代码使用相同的指令,因此无论我使用哪个寄存器,它都应该具有相同的速度.但我是对的吗?哪个代码更容易编码?
我目前正在学习本教程,但我不是该学校的学生。
GDB 给了我一个分段错误thread_start:
movq %rsp, (%rdi) # save sp in old thread's tcb
Run Code Online (Sandbox Code Playgroud)
当我回溯时,这是附加信息:
#0 thread_start () at thread_start.s:16
#1 0x0000000180219e83 in _cygtls::remove(unsigned int)::__PRETTY_FUNCTION__
() from /usr/bin/cygwin1.dll
#2 0x00000000ffffcc6b in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Run Code Online (Sandbox Code Playgroud)
作为一个新手,我一生都无法弄清楚为什么。这是我的主文件:
#define STACK_SIZE 1024*1024
//Thread TCB
struct thread {
unsigned char * stack_pointer;
void(*initial_function)(void *);
void * initial_argument;
};
struct thread * current_thread;
struct thread * inactive_thread;
void thread_switch(struct thread * old_t, struct thread …Run Code Online (Sandbox Code Playgroud) 这个问题让我想知道,当前的现代编译器是否曾经发出REP MOVSB/W/D指令。
基于此讨论,似乎REP MOVSB/W/D在当前 CPU 上使用可能是有益的。
但无论我如何尝试,我都无法让当前的任何编译器(GCC 8、Clang 7、MSVC 2017 和 ICC 18)发出这条指令。
对于这个简单的代码,emit 可能是合理的REP MOVSB:
void fn(char *dst, const char *src, int l) {
for (int i=0; i<l; i++) {
dst[i] = src[i];
}
}
Run Code Online (Sandbox Code Playgroud)
但是编译器会发出一个未优化的简单字节复制循环,或者一个巨大的展开循环(基本上是内联的memmove)。是否有任何编译器使用此指令?
您好,我是一名内核学习者,对 swapgs 有一些疑问。
根据 AMD 的文档,它交换了gs.base隐藏寄存器和 KernelGSBase MSR。
此外,“gs:XXXX”的寻址计算为“gs.base + base + (scale*index) +位移”
现在我的第一个问题是:
那么我应该在哪里存储“基础”和“比例”?
此外,我应该在哪里使用它,我当前的项目将虚拟内存空间的上半部分作为内核,并且编译器通常不会添加“gs:XXXX”作为寻址引用。
所以,特别是,我应该在哪里使用swapgs指令。
assembly operating-system kernel x86-64 thread-local-storage
我只是试图在x86汇编中进行非常快速的基于计算的程序,但我需要在调用程序之前推送累加器,计数器和数据寄存器.手动推动它们的速度更快:
push eax
push ecx
push edx
Run Code Online (Sandbox Code Playgroud)
或者只是使用,
pushad
Run Code Online (Sandbox Code Playgroud)
与弹出一样.谢谢
来自 Intel 对 x64 汇编的介绍https://software.intel.com/en-us/articles/introduction-to-x64-assemble,
虽然我了解如何将 RCX、RDX、R8、R9 用作函数参数,但我见过使用 4 个以上参数的函数会恢复为使用堆栈(如 32 位代码)。示例如下:
sub_18000BF10 proc near
lpDirectory = qword ptr -638h
nShowCmd = dword ptr -630h
Parameters = word ptr -628h
sub rsp, 658h
mov r9, rcx
mov r8, rdx
lea rdx, someCommand ; "echo "Hello""...
lea rcx, [rsp+658h+Parameters] ; LPWSTR
call cs:wsprintfW
xor r11d, r11d
lea r9, [rsp+658h+Parameters] ; lpParameters
mov [rsp+658h+nShowCmd], r11d ; nShowCmd
lea r8, …Run Code Online (Sandbox Code Playgroud) 在这篇关于寄存器保存的维基百科文章中,我读到调用者函数负责某些寄存器(以防止其先前的数据被更改),而被调用者则负责其他寄存器。
我的问题是为什么我们必须让事情复杂化?为什么不让所有寄存器成为调用者的责任,在调用函数之前备份现有值并在之后重新加载它们?
我没有看到执行这些步骤有任何性能提升,有人可以帮助我理解吗?
我为我正在制作的DSP /音频应用编写了这个基本代码:
double input = 0.0;
for (int i = 0; i < nChannels; i++) {
input = inputs[i];
Run Code Online (Sandbox Code Playgroud)
一些DSP工程专家告诉我:"你不应该在循环之外声明它,否则它会创建一个依赖项,编译器无法尽可能高效地处理它."
input我在想他正在谈论var .为什么这个?是不是更好地去掉一次并覆盖它?
也许有些事情与不同的内存位置有关?即注册而不是堆栈?
assembly ×9
x86 ×4
x86-64 ×4
c++ ×3
c ×2
kernel ×2
performance ×2
cygwin ×1
declaration ×1
isa ×1
linux-kernel ×1
loops ×1
memory ×1
optimization ×1
riscv ×1