标签: calling-convention

为什么函数参数占用x86上至少4个字节的堆栈?

如果函数参数push/pop在x86上的堆栈中分配,则至少分配4个字节.如果每个函数调用的参数大小小于4个字节,则会浪费内存.一个原因可能是推送和弹出工作最少4个字节,但为什么不esp直接操作以节省堆栈空间,可以将1个字节中的4个参数打包到一个4字节内存,如下所示?

sub esp, 4
mov byte ptr [esp], para1
mov byte ptr [esp+1], para2
mov byte ptr [esp+2], para3
mov byte ptr [esp+3], para4
call func
Run Code Online (Sandbox Code Playgroud)

x86 assembly calling-convention

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

ARM AArch64 堆栈管理

ARMv8 没有 64 位堆栈的能力吗?我知道 AArch64 上没有推送和弹出指令,因此堆栈管理是否留给 AArch32 进行参数传递等?我们如何传递 48 位地址?我对在 AArch64 中运行时函数调用的工作方式感到困惑。

64-bit assembly arm calling-convention arm64

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

函数参数求值顺序

我对调用 C++ 函数时函数参数的计算顺序感到困惑。我可能解释错了,所以请解释是否是这种情况。

例如,Charles Petzold 的传奇著作“Programming Windows”包含如下代码:

// hdc = handle to device context
// x, y = coordinates of where to output text
char szBuffer[64];
TextOut(hdc, x, y, szBuffer, snprintf(szBuffer, 64, "My text goes here"));
Run Code Online (Sandbox Code Playgroud)

现在,最后一个参数是

snprintf(szBuffer, 64, "My text goes here")
Run Code Online (Sandbox Code Playgroud)

它返回写入 char[] szBuffer 的字符数。它还将文本“My text go here”写入 char[] szBuffer。第四个参数是 szBuffer,它包含要写入的文本。但是,我们可以看到 szBuffer 填充在第五个参数中,告诉我们不知何故是表达式

// argument 5
snprintf(szBuffer, 64, "My text goes here")
Run Code Online (Sandbox Code Playgroud)

之前评估过

// argument 4
szBuffer
Run Code Online (Sandbox Code Playgroud)

好的。总是这样吗?评估总是从右到左进行?查看默认调用约定__cdecl

__cdecl 调用约定的主要特点是:

参数从右向左传递,并放置在堆栈中。

堆栈清理由调用者执行。

函数名称通过在其前面加上下划线字符 '_' 来修饰。

(来源: …

c++ winapi calling-convention argument-passing

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

当名称可能被修饰时使用 GetProcAddress

GetProcAddress()在 32 位 DLL 上使用的正确方法是什么?在 win32 上,共有三种调用约定,cdecl、stdcall 和 fastcall。如果 DLL 中的函数是foo他们将通过以下方式修饰名称_foo_foo@N并且@foo@N

但是如果 dll 的作者使用了 .def 文件,那么导出的名称将更改为“foo”,没有任何修饰。

这给我带来了麻烦,因为如果我想foo从使用 stdcall 的 dll加载,我应该使用装饰名称:

void *h = LoadLibraryEx(L"foo.dll", NULL, 0);
GetProcAddres((HMODULE)h, L"_foo@16");
Run Code Online (Sandbox Code Playgroud)

或未装饰的:

void *h = LoadLibraryEx(L"foo.dll", NULL, 0);
GetProcAddres((HMODULE)h, L"foo");
Run Code Online (Sandbox Code Playgroud)

? 我应该猜吗?我查看了很多 32 位 DLL 文件(stdcall 和 cdecl),它们似乎都导出了未修饰的名称。但是你能假设情况总是如此吗?

winapi calling-convention stdcall getprocaddress name-decoration

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

在x86_64汇编中调用约定差异

所以,我有3个参数的汇编程序ASM_Method(void*, void*, int)init_method(float, int*).感兴趣的是前者的无效指针.

当我从C++文件中调用方法时,参数为:

float src[64];
float dest[64];
int radius[3];

init_method(1.5, radius);
ASM_Method(src, dest, 64);
Run Code Online (Sandbox Code Playgroud)

反汇编这个调用过程:

mov         r8d,100h  
lea         rdx,[rbp+0A0h]  
lea         rcx,[rbp-60h]  
call        ASM_Method 
Run Code Online (Sandbox Code Playgroud)

是否已初始化,程序运行正常.但是,当我这样做时:

float* src = new float[64];
float* dest = new float[64];
int radius[3];

init_method(1.5, radius);
ASM_Method(src, dest, 64);
Run Code Online (Sandbox Code Playgroud)

调用时,RCX设置为非正确地址的值,但RDX是正确的.程序崩溃了.

反汇编这个调用过程:

mov         r8d,100h  
mov         rdx,rbx  
mov         rcx,rdi  
call        ASM_Method
Run Code Online (Sandbox Code Playgroud)

除非我将src初始化为某些值,否则RCX在调用时会更改为无效地址(在本例中为1).

ASM_Method的汇编代码:

mov rax, rdx
add rax, r8
shr r8, 4
inc r8
xor r9, r9
movdqu xmm1, [rax]

MainLoop:
movdqu xmm0, [rcx …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 masm calling-convention

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

在函数调用中“使用严格”和命名参数

一位同事建议我添加"use strict";到我的 JS 代码的顶部,以突出我的定义中的任何差距和潜在的引用错误等。我对此非常满意,因为它已经确定了几段可能存在问题的代码.

但是,另一位同事告诉我,在调用带有多个参数的函数时,按照指定的方式命名参数会很有帮助,尤其是当它是一堆布尔值时。为了说明,这里有几个函数调用:

logData(data, target, preserveLog=true, changeClass=false, wrapLine=false);
Run Code Online (Sandbox Code Playgroud)

...比:

logData(data, target, true, false, false);
Run Code Online (Sandbox Code Playgroud)

但是"use strict";讨厌这个。在我执行此操作的任何地方,我都会在控制台中收到参考错误。正如预期的那样,它仍然运行良好,但控制台现在被所有这些明显未定义的引用弄得乱七八糟。

有谁知道是否有办法解决这个问题,以便我可以保留我的同事欣赏的编码约定,或者我将不得不停止使用"use strict";或检查我的所有代码并删除参数名称?

谢谢。

javascript calling-convention use-strict

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

在 CMake 项目中从 C++ 调用 C 代码。未定义的符号。有外部C

我正在尝试构建一个从 C++ 调用 C 代码的 CMake 项目,尽管我(据我所知)正确使用了“extern C”,但我得到了未定义的符号。

CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)
project(CTest LANGUAGES CXX)
add_executable(test main.cpp lib.c)
Run Code Online (Sandbox Code Playgroud)

主要.cpp:

#include "lib.h"

int main()
{
    printit();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

库.c:

#include <stdio.h>
#include "lib.h"

int printit()
{
    printf("Hello world\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

库.h:

extern "C" int printit();
Run Code Online (Sandbox Code Playgroud)

这给了我一个“未定义的 printit 引用”错误。

如果我只是从命令行构建它,它就可以正常工作:

g++ main.cpp lib.c
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

c++ linker cmake calling-convention extern

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

为什么生成的程序集将 edi 移动到堆栈上的变量?

我是汇编的新手,试图了解以下函数的 objdump:

int nothing(int num) {
    return num;
}
Run Code Online (Sandbox Code Playgroud)

这是结果(linux,x86-64,gcc 8):

push   rbp
mov    rbp,rsp
mov    DWORD PTR [rbp-0x4],edi
mov    eax,DWORD PTR [rbp-0x4]
pop    rbp
ret    
Run Code Online (Sandbox Code Playgroud)

我的问题是: 1.edi从哪里来?阅读一些介绍文档,我的印象是[rbp-0x4]将包含num. 2. 从上面可以看出,edi 显然包含了这个论点。但是,它[rbp-0x4]扮演什么角色呢?为什么不只是mov eax, edi

谢谢!

assembly gcc x86-64 calling-convention

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

组装中的“对齐堆栈”是什么意思?

堆栈对齐在 ASMx64 中是如何工作的?什么时候需要在函数调用前对齐堆栈,需要减去多少?

我不明白这样做的目的是什么。我知道还有其他关于这个的帖子,但对我来说还不够清楚。例如:

extern foo
global bar

section .text
bar:
  ;some code...
  sub  rsp, 8     ; Why 8 (I saw this on some posts) ? Can it be another value ? Why do we need to substract?
  call foo        ; Do we need to align stack everytime we call a function?
  add  rsp, 8
  ;some code...
  ret
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 calling-convention memory-alignment stack-pointer

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

为什么并非所有 C 程序都使用调用约定

我是编程新手,在阅读 Charles Petzold 的书Programming Windows 时,我偶然发现了 WINAPI(实际上,除了返回类型之外,函数名称之前还存在另一个词让我感到惊讶),发现它是一个调用约定,并且是最好的我的理解是函数如何将变量压入堆栈并获取返回值的一种方式,我想知道为什么我们不在每个 C 程序中都使用它们?它们只是操作系统编程所独有的吗?

c winapi calling-convention

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