提问人:RTC222 提问时间:2/8/2018 最后编辑:Michael PetchRTC222 更新时间:5/21/2021 访问量:3688
如何在 64 位 NASM 中使用 malloc 和 free?
How to use malloc and free in 64-bit NASM?
问:
在 64 位 NASM 中,我使用 C 库中的 malloc() 分配一个 8000 字节的内存块,完成后,我通过调用 free() 来解除分配它。
我的研究提出了许多关于如何在 64 位 NASM 中执行此操作的相互矛盾的信息,其中大部分信息是 32 位的,其中调用约定不同,或者它是 C 或 C++,而不是 NASM。
我认为我有 malloc 部分,但我不确定免费部分。我发布这个问题是因为我不想测试它并分配内存块但未释放。
所以我的两个问题很简单:
(1)我是否拥有 64 位 NASM 的这个权利?
(2) Windows 和 Linux 的语法是否相同?
我只显示程序的 malloc 和 free 部分:
extern malloc
extern free
push rdi
; Allocate the memory buffer
mov rdi,8000
call malloc
mov [array_pointer],rax ;array_pointer is initialized in .data
; Code that uses the buffer goes here.
; Free the memory buffer
push rdi
call free
add rsp,8
pop rdi
ret
答:
汇编语言没有标准库。所以这不是一个汇编语言问题,一定是我有一组符合这个调用约定的库,或者由 X 编译器和版本制作的,具有这样那样的设置。我想链接并使用汇编语言中的这些库。首先,只需用该语言编写它,然后编译并保存临时或编译为汇编,然后从该代码开始。或者反汇编此类代码以发现调用约定,并将其与使用此编译器读取此目标平台的调用约定时发现的内容进行比较。
If it is a system call and you want to do that directly, and not a library call then you need to read up on the system call interface for this platform and operating system, no reason to assume any two are the same (Linux, BSD, Windows, etc). Nor that major versions of each are the same although they probably are...
then write your code to conform to whichever you found.
Let's start with Windows x64. A single integer-sized parameter (as given to both and ) is passed in the register and an integer return value is put into the register.malloc
free
rcx
rax
The basic rule is to use , , , and for the first four integer parameters and the stack for any others. Non-integer parameters complicate things a little but, since there are none of those in the or calls, I won't cover it here. If you need more information, Microsoft has a good article over at X64 Calling Convention
.rcx
rdx
r8
r9
malloc
free
Hence simple code for allocating and immediately freeing a block would be something like, with AT&T syntax given in parentheses after comment, if different:
mov rcx, 1000 ; Allocate a block (mov $1000, %rcx).
call malloc ; Allocate, address returned in rax.
mov rcx, rax ; Address needed in rcx (mov %rax, %rcx).
call free ; And free it.
Note that this example, and the one below, simply illustrate register usage, there's other things you need to consider as well, such as shadow space and alignment requirements.
Linux uses a different approach (though still with registers for efficiency). It uses the System V AMD64 ABI and, for this case, you'll find still used for the return value but used for the argument.rax
rdi
This ABI draws its integer register set from with any extra parameters passed on the stack.{ rdi, rsi, rdx, rcx, r8, r9 }
So the code change for Linux would be fairly simple, using instaed of :rdi
rcx
mov rdi, 1000 ; Allocate a block (mov $1000, %rdi).
call malloc ; Allocate, address returned in rax.
mov rdi, rax ; Address needed in rdi (mov %rax, %rdi).
call free ; And free it.
Raymond Chen (of The Old New Thing fame) has a series on calling conventions that you may find interesting, starting here.
评论
sub rsp, 32
add rsp, 32
评论
malloc
返回 RAX 中的指针。您需要将 RAX 移动到 RDI(或将存储在 RDI 的地址移动到 RDI)以释放它(因为第一个参数是通过 RDI 传递的,就像符合 64 位 System V ABI 的每个函数一样)。您也不需要 和 周围 .这样做会扰乱堆栈对齐。array_pointer
free
push rdi
add rsp, 8
call free
free
malloc
malloc
malloc
free