Linux malloc和免费x86 NASM+;编撰

Linux malloc和免费x86 NASM+;编撰,linux,assembly,x86,nasm,Linux,Assembly,X86,Nasm,我一直在自学x86汇编,并一直在研究如何进行基本的malloc()和free()调用。我花了相当多的时间搜索,但大多数示例都是针对64位的,或者只显示malloc调用而不显示free,等等。我甚至用c编写了这篇文章,然后对它进行编译和反汇编,这很有帮助,但gcc添加了许多其他指令 以下是我所做的一个基本示例,说明了我能够理解的内容,请告诉我这是否正确,或者我是否应该做其他事情: global _start ; glibc stuff extern _malloc, _free section

我一直在自学x86汇编,并一直在研究如何进行基本的malloc()和free()调用。我花了相当多的时间搜索,但大多数示例都是针对64位的,或者只显示malloc调用而不显示free,等等。我甚至用c编写了这篇文章,然后对它进行编译和反汇编,这很有帮助,但gcc添加了许多其他指令

以下是我所做的一个基本示例,说明了我能够理解的内容,请告诉我这是否正确,或者我是否应该做其他事情:

global _start
; glibc stuff
extern _malloc, _free

section .data
  err: db "malloc failed!", 10, 0
    .len: equ $ - err

section .bss
  mptr resd 1   ;pointer to begining of malloc'd memory

section .text
_start:

  push 20       ;allocate 20 bytes
  call _malloc  ;call malloc
  add esp, 4    ;clean pushed imm

  test eax, eax ;check for malloc error
  jz merror

  mov [mptr], eax ;store address

  mov byte [eax], 0
  mov byte [eax + 1], 1

  push mptr     ;push address
  call _free    ;call free
  add esp, 4    ;clean push

exit:
  mov eax, 0x1
  int 80h

merror:
  mov eax, 0x4
  mov ebx, 0x1
  mov ecx, err
  mov edx, err.len
  int 80h
  jmp exit
问题的第二部分是汇编。根据我所能找到的,我需要链接
/lib/ld linux.so.2
。因此,在我的makefile中,我有以下内容,但它出错了:

mem: mem.asm
    nasm -f elf mem.asm
    ld -melf_i386 -lc -I /lib/ld-linux.so.2 mem.o -o mem
这是我在尝试编译时遇到的错误:

正如我所说,我是x86的noob,因此,如果您对更好的做事方式有任何意见,我也将不胜感激!:)

更新

因此,我继续使用gcc并使其正常工作(至少没有错误):

然而,当我去运行它时,它崩溃了:


我显然对
free
做了一些错误的事情,但正如我所提到的,我对使用
malloc
free
并不乐观,因为我找不到任何可靠的例子。有什么线索吗?

谢谢大家的帮助!因此,首先,我能够通过使用
gcc
链接而不是
ld
来修复链接错误:

mem: mem.asm
    nasm -f elf mem.asm
    gcc -m32 mem.o -o mem
为了使其正常工作,我需要将函数名从
\u malloc
\u free
更改为
malloc
free
。我还必须将标准的
global _start
更改为
global main
,以使gcc满意。这让它编译和链接没有错误,但正如您在更新中看到的那样,程序在释放内存时崩溃得很厉害

这是因为我在堆栈中推错了地址。我最初的指令是
push-mptr
,但这是将
mptr
的地址推送到堆栈,而不是它所指向的地址,因此出现了错误。为了将正确的地址推送到堆栈,只需对指令进行简单更新,我的简单程序就可以无误运行:

push dword [mptr]
最终结果是:

global main
; glibc stuff
extern malloc, free

section .data
  err: db "malloc failed!", 10, 0
    .len: equ $ - err

section .bss
  mptr resd 1   ;pointer to begining of malloc'd memory

section .text
main:

  push 20       ;allocate 20 bytes
  call malloc   ;call malloc
  add esp, 4    ;clean pushed imm

  test eax, eax ;check for malloc error
  jz merror

  mov [mptr], eax ;store address

  mov byte [eax], 0     ;store 0 at index 0
  mov byte [eax + 1], 1 ;store 1 at index 1

  push dword [mptr]     ;push address
  call free             ;call free
  add esp, 4            ;clean push

exit:
  mov eax, 0x1
  int 80h

merror:
  mov eax, 0x4
  mov ebx, 0x1
  mov ecx, err
  mov edx, err.len
  int 80h
  jmp exit
再次感谢大家的帮助,感谢你们给我一个机会提供正确的答案!:)


我相信,随着旅程的继续,我会带着更多的noob x86问题回来

然后从
main
开始(让clib初始化)。不同之处在于,您不是在调用将完全分配新内存的magic
malloc
,而是调用名为
malloc
的普通C函数。它不是完整的内存管理器,而是它的一个子部分,它将从底层内存管理器代码已经分配的内部堆中为您提供一些内存块。因此,很可能实现已经期望初始化。如果您提供了
main
,那么当C跳转到
main
时,它已经被初始化了。实际上,除了初始化之外,您的问题是,您可能可以使用
gcc
包装器将其与更简单的行链接,因为您希望使用clib,在linux中,C符号不需要下划线IIRC,例如,
外部malloc
调用malloc
。我在这里找到了一些从asm调用C函数的老例子:(看起来你的
ld
调用实际上可能还可以)
push-mptr;推送地址
将推送地址,但mptr的地址,而不是存储在内存中的值。尝试推送dword[mptr]。您需要调试器,如果您使用调试器,您将看到
free
调用前面的堆栈包含的地址与
malloc
返回的地址不同。。。是否也在Q中更新asm?或者您还没有使用
main
?然后,我很惊讶
malloc
返回了一些可用的东西,可能它有lazy init并检测到它第一次被调用,并正确地执行init操作。即使是
strace
也可能会显示参数值的差异。您似乎在遵循Windows教程。请注意,在Linux上,符号不是用下划线修饰的!此外,如果不先让C编译器为您插入适当的起始存根,您就不应该使用C库。最简单和最安全的方法是编写
main()
函数,并让gcc包含crt起始文件,这些文件在调用
main()之前通常都会执行
由C编译器生成。如果您坚持编写自己的
\u start
,请参阅必须调用哪些glibc init函数(从静态二进制文件)。或者使用不需要初始化的其他libc(如MUSL):
global main
; glibc stuff
extern malloc, free

section .data
  err: db "malloc failed!", 10, 0
    .len: equ $ - err

section .bss
  mptr resd 1   ;pointer to begining of malloc'd memory

section .text
main:

  push 20       ;allocate 20 bytes
  call malloc   ;call malloc
  add esp, 4    ;clean pushed imm

  test eax, eax ;check for malloc error
  jz merror

  mov [mptr], eax ;store address

  mov byte [eax], 0     ;store 0 at index 0
  mov byte [eax + 1], 1 ;store 1 at index 1

  push dword [mptr]     ;push address
  call free             ;call free
  add esp, 4            ;clean push

exit:
  mov eax, 0x1
  int 80h

merror:
  mov eax, 0x4
  mov ebx, 0x1
  mov ecx, err
  mov edx, err.len
  int 80h
  jmp exit