标签: calling-convention

为什么 strlen 的 REPNE SCASB 实现可以工作?

为什么这段代码有效?

http://www.int80h.org/strlen/说字符串地址必须在EDI寄存器中才能scasb工作,但这个汇编函数似乎没有这样做。

汇编代码mystrlen

global  mystrlen
mystrlen:
        sub             ecx, ecx
        not             ecx
        sub             al, al
        cld
        repne scasb
        neg             ecx
        dec             ecx
        dec             ecx
        mov             eax, ecx
        ret
Run Code Online (Sandbox Code Playgroud)

C主:

int mystrlen(const char *);
int main()
{
    return (mystrlen("1234"));
}
Run Code Online (Sandbox Code Playgroud)

汇编:

nasm -f elf64 test.asm
gcc -c main.c
gcc main.o test.o
Run Code Online (Sandbox Code Playgroud)

输出:

./a.out
echo $?
4
Run Code Online (Sandbox Code Playgroud)

c assembly x86-64 calling-convention strlen

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

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
查看次数

为什么参数分配在帧指针下方而不是上方?

我试图根据 godbolt.org 上 c++ 中的平方函数来理解这一点。显然,返回、参数和局部变量使用 \xe2\x80\x9crbp -alignment\xe2\x80\x9d 来实现此函数。\n有人可以解释一下这是如何实现的吗?\n在这种情况下 rbp +alignment 会做什么?

\n
int square(int num){\n    int n = 5;// just to test how locals are treated with frame pointer\n    return num * num;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

编译器(x86-64 gcc 11.1)

\n

生成的程序集:

\n
square(int):\n    push rbp\n    mov rbp, rsp \n    mov DWORD PTR [rbp-20], edi. ;\\\\Both param and local var use rbp-*\n    mov DWORD PTR[rbp-4], 5.     ;//\n    mov eax, DWORD PTR [rbp-20]\n    imul eax, eax\n    pop rbp\n    ret\n\n
Run Code Online (Sandbox Code Playgroud)\n

c++ assembly x86-64 calling-convention stack-frame

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

为什么使用向量寄存器而不是将 stdargs 保存在堆栈中?

所以我正在阅读 SYSTEM V AMD64 ABI,其中写道我们必须使用向量寄存器来保存 stdargs 并设置AL为用于放置参数的寄存器的数量。
为什么需要使用向量寄存器?我们不能将它们放入堆栈并将AL寄存器设置为堆栈中的参数数量吗?

assembly x86-64 calling-convention

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

ESP的值未正确保存

替代文字

从上面的图像中可以看到函数setAttribute从其调用返回时发生错误.

有谁知道如何解决图片中显示的错误?我知道调用约定之间存在错误,但是如何找出setAttribute的调用约定呢?

c++ calling-convention

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

非托管函数挂钩,堆栈/寄存器问题与调用约定?

这不是关于EasyHook的特定功能,而是关于一般的挂钩.我想用这个签名挂钩一个函数:

public: int __thiscall Connection_t::Send(unsigned int,unsigned int,void const *)
Run Code Online (Sandbox Code Playgroud)

这显然是非托管代码,我正在尝试使用EasyHook将其与我的托管c#代码挂钩.但我认为这不是EasyHook导致问题,但我知道调用约定等...
这就是我如何定义DllImport并删除:

    public static int Send_Hooked(uint connection, uint size, IntPtr pDataBlock)
    {
        return Send(connection, size, pDataBlock);
    }

    [DllImport("Connection.dll", EntryPoint = "?Send@Connection_t@@QAEHIIPBX@Z", CallingConvention = CallingConvention.ThisCall)]
    static extern int Send(uint connection, uint size, IntPtr pDataBlock);

    [UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Unicode, SetLastError = true)]
    delegate int DSend(uint connection, uint size, IntPtr pDataBlock);
Run Code Online (Sandbox Code Playgroud)

但是一旦我注入钩子,钩住的程序就会继续崩溃 - 没什么大惊喜.我认为它是调用约定的问题,并且我的钩子函数以某种方式干扰了钩子程序的堆栈.

所以我看看另一个项目谁挂钩相同的功能,但在c ++中弯路(挂钩部分):

Func =  (int (__stdcall *)(unsigned int, unsigned short, void const ))::GetProcAddress(::GetModuleHandle("Connection.dll"), "?Send@Connection_t@@QAEHIIPBX@Z");
PVOID DetourPtr;
PVOID TargetPtr;
DetourTransactionBegin();
DetourAttachEx(&Func, …
Run Code Online (Sandbox Code Playgroud)

c# assembly hook detours calling-convention

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

从程序集调用Win32的Sleep函数会产生访问冲突错误

我正在使用MASM和Visual C++,我正在使用x64进行编译.这是我的C++代码:

// include directive
#include "stdafx.h"
// external functions
extern "C" int Asm();
// main function
int main()
{

    // call asm
    Asm();
    // get char, return success
    _getch();
    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

和我的汇编代码:

extern Sleep : proc
; code segment
.code
    ; assembly procedure
    Asm proc
        ; sleep for 1 second
        mov ecx, 1000   ; ecx = sleep time
        sub rsp, 8      ; 8 bytes of shadow space
        call Sleep      ; call sleep
        add rsp, 8      ; get rid …
Run Code Online (Sandbox Code Playgroud)

c++ x86 assembly winapi calling-convention

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

在调用者的堆栈上分配内存

我使用MSVC++ 2012用C++编写,我的代码针对的是x86平台.我有一种情况,写一个函数(除其他外)可以在CALLING函数的堆栈上分配一些内存是有利的.我不打算在这篇文章中辩论这样做的智慧,而只是考虑技术可行性.

我的实现计划是将我的函数编写为裸函数,并在内联汇编中使用自定义prolog代码.在prolog中,我首先确定我需要多少内存,然后将返回地址,参数和此指针向下移动到该堆栈中.最后,我会根据该数量调整堆栈指针.如果我没有弄错,这将在调用函数的堆栈上创建一个区域.

有没有人看到该计划中有任何漏洞?

c++ stack memory-management calling-convention

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

被调用方如何知道参数是通过寄存器而不是堆栈传递的

假设我们得到一个简单的程序

#include <cstdio>

int main(int argc, char* argv[]) {
    int n = argc;
    if (n > 1) {
        n = 1;
    }else {
        n = -1;
    }
    printf("%d\n", n);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

g++ main.cpp -S -O1在ubuntu x64下使用Windows子系统生成的汇编代码和汇编代码段

subq    $8, %rsp
cmpl    $1, %edi
setg    %dl
movzbl  %dl, %edx
leal    -1(%rdx,%rdx), %edx
movl    $.LC0, %esi
movl    $1, %edi
movl    $0, %eax
call    __printf_chk
movl    $0, %eax
addq    $8, %rsp
ret
Run Code Online (Sandbox Code Playgroud)

push没有访问内存的指令,也没有访问内存的指令。因此,n必须通过传递参数%edx。现在,我想知道c库函数如何__printf_chk知道其中%edx …

c++ assembly g++ x86-64 calling-convention

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