相关疑难解决方法(0)

在堆栈帧创建之前或之后推送寄存器之间有什么区别吗?

假设我有一个名为 func 的函数:

PROC func:
    ;Bla bla
    ret
ENDP func
Run Code Online (Sandbox Code Playgroud)

现在,假设我使用 register axbx例如,为了保存它们的初始值,我将它们推送到函数内部的堆栈中。

现在的问题是:在创建堆栈帧之前推送寄存器之间是否有很大的不同:

PROC func:
    push bp
    push ax
    push bx
    mov bp, sp
    ;Bla bla
    ret
ENDP func
Run Code Online (Sandbox Code Playgroud)

还是之后?

PROC func:
    push bp
    mov bp, sp
    push ax
    push bx
    ;Bla bla
    ret
ENDP func
Run Code Online (Sandbox Code Playgroud)

我应该在我的程序中使用什么?一种方法比另一种更好或更“正确”吗?因为我目前使用第一种方法。

x86 assembly callstack stack-frame

3
推荐指数
1
解决办法
351
查看次数

x86_64程序集约定保存参数寄存器

我正在编写一些x86_64程序集来调用C函数.我的C函数接受1个参数,因此程序集将参数放入%rdi.ABI pdf(下面链接)表示其他6个参数寄存器(rsi,rdx,rcx,r8,r9)不会在函数调用中保留.但是,由于我的C函数只接受一个long参数,我是否可以保证C函数是否会破坏其他5个寄存器?我的假设是,如果参数的值发生了变化,那么参数寄存器只会被破坏:

void foo(int a, int b) {
    a++; /* %rdi will be changed, but %rsi won't be changed when control returns. */
}
Run Code Online (Sandbox Code Playgroud)

我问,因为我想在我的C函数调用中保留其他5个参数寄存器的值(无需手动显式地从堆栈中推送/弹出它们).

x86_64 ABI - http://www.x86-64.org/documentation/abi-0.99.pdf

c assembly x86-64

2
推荐指数
2
解决办法
3788
查看次数

X64 Fastcall 叶函数是否需要保留 RCX?

我有一个用 MASM64/ML64 组装的 X64 ASM 例程。它是一个独立的叶函数,而不是内联汇编。它用于 Visual Studio 解决方案中的 C/C++ 程序。

我在 MSDN 上找到了两篇关于保存寄存器的参考资料:

第一个是内联汇编,但它特别指出在使用__fastcall. 它似乎也缺乏对 X64 的处理,因为它引用 32 位寄存器。

第二个告诉我们“RAX、RCX、RDX、R8、R9、R10、R11 被认为是易失性的,必须在函数调用时被认为是销毁的”。不幸的是,它没有明确说明是否需要保留它们。(如果你仔细观察,你会发现它使用的是误导,而不是说明要采取的行动)。

我认为第二篇文章在这种情况下是控制性的,但我想澄清以避免混淆......是否需要为 X64 Fastcall Leaf Functions 保留 CX/ECX/RCX?

assembly x86-64 masm cpu-registers calling-convention

2
推荐指数
1
解决办法
521
查看次数

为什么在子例程调用中没有完整的上下文保存?

在子例程调用中,我们保存了PC的内容,以便重新启动我们的调用例程。但是,如果被调用的子例程更改了通用寄存器的值,会发生什么?如果必须访问存储在寄存器中的旧值,它不会对调用子例程造成任何问题吗?

assembly call cpu-registers context-switch subroutine

2
推荐指数
1
解决办法
321
查看次数

x86汇编pushad/popad,它的速度有多快?

我只是试图在x86汇编中进行非常快速的基于计算的程序,但我需要在调用程序之前推送累加器,计数器和数据寄存器.手动推动它们的速度更快:

push eax
push ecx
push edx
Run Code Online (Sandbox Code Playgroud)

或者只是使用,

pushad
Run Code Online (Sandbox Code Playgroud)

与弹出一样.谢谢

performance x86 assembly inline-assembly micro-optimization

2
推荐指数
1
解决办法
1193
查看次数

Windows x64 调用约定中 R10-R15 寄存器的用途是什么?

来自 Intel 对 x64 汇编的介绍https://software.intel.com/en-us/articles/introduction-to-x64-assemble

  • RCX、RDX、R8、R9 按从左到右的顺序用于整数和指针参数。
  • 寄存器 RAX、RCX、RDX、R8、R9、R10 和 R11 被视为易失性寄存器,必须在函数调用时被视为已销毁。
  • RBX、RBP、RDI、RSI、R12、R14、R14 和 R15 必须保存在使用它们的任何函数中。

虽然我了解如何将 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)

assembly x86-64 calling-convention

2
推荐指数
1
解决办法
8809
查看次数

为什么要让一些寄存器由调用者保存而另一些寄存器由被调用者保存?为什么不让调用者保存它想要保存的所有内容?

在这篇关于寄存器保存的维基百科文章中,我读到调用者函数负责某些寄存器(以防止其先前的数据被更改),而被调用者则负责其他寄存器。

我的问题是为什么我们必须让事情复杂化?为什么不让所有寄存器成为调用者的责任,在调用函数之前备份现有值并在之后重新加载它们?

我没有看到执行这些步骤有任何性能提升,有人可以帮助我理解吗?

assembly cpu-registers calling-convention riscv

2
推荐指数
1
解决办法
2073
查看次数

MIPS寄存器保存

所以我现在正在学习MIPS,我在MIPS绿板上看到,总共有12个寄存器(包括s寄存器)在调用中保留.在我对此的理解中,必须堆叠所有这些寄存器并在我们想要再次访问它们时检索它们.

不过我的问题是,如果遇到这个麻烦,为什么还要使用这些寄存器呢?是否有可能使用这些寄存器而不是可能耗尽寄存器?

mips preserve

1
推荐指数
1
解决办法
2761
查看次数

为什么被调用者不首先使用调用者保存的寄存器?

我们知道,根据 x86-64 约定,寄存器%rbx%rbp%r12%r15被归类为被调用者保存的寄存器。While%r10%r111是调用者保存的寄存器。但是当我在大多数情况下编译 C 代码时,例如函数P调用Q,我看到以下函数的汇编代码Q

Q:
   push %rbx
   movq %rdx, %rbx
   ...
   popq %rbx
   ret
Run Code Online (Sandbox Code Playgroud)

我们知道,由于%rbx是一个被调用者保存的寄存器,我们必须将它存储在堆栈中,并在P以后为调用者恢复它。

但它不会更简洁并通过使用调用者保存的寄存器来保存堆栈操作%r10

Q:
   movq %rdx, %r10
   ...
   ret
Run Code Online (Sandbox Code Playgroud)

所以被调用者不需要担心保存和恢复调用者的寄存器,因为调用者在调用被调用者之前已经把它推到了堆栈?

c assembly x86-64 calling-convention compiler-optimization

0
推荐指数
1
解决办法
167
查看次数

调用库函数是否仍然会使它们成为非叶函数?x86 汇编如何处理库函数?

因此,当我们的 C 程序(或其他语言)的函数 (funcA) 调用同一程序中的另一个函数 (funcB) 时,funcA 被认为是非叶函数,因为它调用其他函数。因此,设置了堆栈框架和所有内容,而不是使用 redzone。

然而,比如说在 funcB 中,我们不会调用在程序本身中显式编写的任何函数,但我们确实调用了一两个库函数,例如 fscanf()、fopen() (但我认为这并不重要,只要它是库函数)。那么 funcB 是否会不是叶函数,因为它仍在调用另一个函数?x86 中如何处理库函数?

分析一些 x86 很明显没有发生明显的跳转,但我可以看到它的执行方式类似于,call __isoc99_fscanf@PLT #call perror@PLT #

c x86 assembly

0
推荐指数
1
解决办法
115
查看次数