刚开始学习x64程序集,我对函数,参数和堆栈有疑问.据我所知,函数中的前四个参数传递给Windows中的rcx,rdx,r8和r9寄存器(以及浮点数的xmm0-xmm3).所以带有四个参数的简单加法函数如下所示:
add:
mov r10, rcx
add r10, rdx
add r10, r8
add r10, r9
mov rax, r10
ret
Run Code Online (Sandbox Code Playgroud)
但是,我遇到的文档提到了这一点:
每个函数至少必须在堆栈上保留32个字节(4个64位值).该空间允许将传递到函数中的寄存器轻松复制到众所周知的堆栈位置.不需要被调用函数将输入寄存器参数溢出到堆栈,但堆栈空间预留确保它可以在需要时使用.
所以,我必须预留堆栈空间,即使我做的功能需要四个参数或更低,或者是它只是一个建议?
注册变量是一种众所周知的快速访问(register int i)方式.但为什么寄存器位于层次结构的顶层(寄存器,缓存,主存储器,辅助存储器)?访问寄存器如此之快的所有事情是什么?
我知道堆栈是每个线程,但寄存器是有限的,就像在IA32上一样,只有8个寄存器.
那么线程之间如何共享寄存器呢?
我目前正在学习英特尔处理器的组装.由于堆栈"渐渐减少",为什么我们必须添加才能访问特定元素
[ebp + 8] ;; This will access the first param
Run Code Online (Sandbox Code Playgroud)
我知道我们必须跳过旧的ebp值和返回地址,这就是我们使用8的原因(因为每个都是4个字节长).这有点奇怪.
另外,如果ebp是esp的备份副本,那么主函数Ex中的ebp值是多少:
_start:
;; what's ebp value here ?
push eax
push ebx
call someFunction ;; this will create a stack frame
+-----------+
| param1 |
+-----------+
| param0 | <--- this is [ebp + 8] ( assuming mov ebp, esp )
+-----------+
|ret_address|
+-----------+
| ebp |
+-----------+ <--- esp
Run Code Online (Sandbox Code Playgroud)
而且当我们为本地人分配内存时,我们必须从ebp中减去...请给出一个非模棱两可的答案.谢谢!
任何人都可以告诉我纯粹的汇编代码以十进制格式显示寄存器中的值吗?请不要建议使用printf hack,然后使用gcc进行编译.
描述:
好吧,我做了一些研究和NASM的一些实验,并认为我可以使用c库中的printf函数来打印整数.我是通过使用GCC编译器编译目标文件来完成的,所有工作都很公平.
但是,我想要实现的是以十进制形式打印存储在任何寄存器中的值.
我做了一些研究,发现DOS命令行的中断向量021h可以显示字符串和字符,而2或9位于ah寄存器中,数据在dx中.
结论:
我找到的所有示例都没有显示如何在不使用C库的printf的情况下以十进制形式显示寄存器的内容值.有没有人知道如何在装配中这样做?
我知道rdtsc将处理器的时间戳计数器的当前值加载到两个寄存器中:EDX和EAX.为了在x86上获取它,我需要这样做(假设使用Linux):
unsigned long lo, hi;
asm( "rdtsc" : "=a" (lo), "=d" (hi));
return lo;
Run Code Online (Sandbox Code Playgroud)
对于x86_x64:
unsigned long lo, hi;
asm( "rdtsc" : "=a" (lo), "=d" (hi) );
return( lo | (hi << 32) );
Run Code Online (Sandbox Code Playgroud)
这是为什么?任何人都可以向我解释一下吗?
在8086汇编编程中,我们只能将数据加载到段寄存器中,首先将其加载到通用寄存器中,然后我们必须将它从这个通用寄存器移到段寄存器中.
为什么我们不能直接加载它?有没有被允许的特殊原因?
mov ax,5000H和之间有什么区别mov ax,[5000H]?[5000h]内存位置5000h的含义是什么意思?
我有一个关于装配的基本问题.
如果它们也可以在内存上工作,为什么我们只在寄存器上进行算术运算呢?
例如,以下两个原因(基本上)都将相同的值计算为答案:
片段1
.data
var dd 00000400h
.code
Start:
add var,0000000Bh
mov eax,var
;breakpoint: var = 00000B04
End Start
Run Code Online (Sandbox Code Playgroud)
片段2
.code
Start:
mov eax,00000400h
add eax,0000000bh
;breakpoint: eax = 0000040B
End Start
Run Code Online (Sandbox Code Playgroud)
从我所看到的,大多数文本和教程主要在寄存器上进行算术运算.使用寄存器只是更快吗?
编辑:那很快:)
给出了一些很好的答案; 根据第一个好的答案选择了最佳答案.
为什么orig_eax列入成员sys/user.h的struct user_regs_struct?
cpu-registers ×10
assembly ×6
x86 ×3
c ×2
64-bit ×1
intel ×1
linux ×1
linux-kernel ×1
math ×1
nasm ×1
performance ×1
rdtsc ×1
stack ×1
x86-16 ×1