0

I'm writing a small library in nasm for linux and I'm implementing malloc atm.

The C representation of the code would look like

void * malloc(int size) {
    return mmap(0, size, 3, 34, -1, 0);
}

Now I have to convert that to assembly, but I'm stuck at loading the arguments.

mov eax, 90
; load args (help)
int 0x80
; move adress to eax

I'd like to know how to convert the C code into asm. In most cases the arguments of a syscall are mapped in the same order as in assembly, but mmap takes 6 arguments, and the kernel takes a maximum of 5 arguments.

I'd also like to know where the returned value is stored.

So, how should I implement it.

Update:

code:

section .data
mmap_arg:  ; ugly
  .addr:   dq 0
  .len:    dq 512
  .prot:   dq 3
  .flags:  dq 34
  .fd:     dq -1
  .offset: dq 0

mmap_test:
  mov eax, 90
  mov ebx, mmap_arg
  int 0x80

It seems like its working, but when I load something at the address of eax, I get a segfault. When I replace eax with ebx, it runs without errors. Can someone confirm that the returned address is in ebx, or that I'm writing in the .data section when using ebx.

Gdb shows that only eax gets modified after int 0x80. I'm stuck again. It's gettting late, I'll have a look again at it tomorrow.

Lennart
  • 345
  • 4
  • 17
  • Code your "mmap()" call in C, then compile with "gcc -S". This will dump assembly output, and show you exactly how the routine is called. NOTE: not all platforms make Linux syscalls the same way (as you probably already know). The assembly for one Linux platform might *not* be correct for a different platform. – paulsm4 May 04 '13 at 22:14
  • Yes, it shows how it calls the mmap function in the library, but in the environment I'm working for (empty initramfs) doesn't have a standard library. – Lennart May 04 '13 at 22:20
  • 1
    basically you push a [`mmap_arg_struct`](http://lxr.free-electrons.com/source/mm/mmap.c#L1356) on the stack, palce it's address into ebx and execute the syscall. (http://syscalls.kernelgrok.com/) – mata May 04 '13 at 23:15
  • Tnx, I'll try it. However it seems a bit strange that I need a struct to allocate memory for a struct. – Lennart May 04 '13 at 23:19
  • well, mmap takes more arguments then fit into the registers, so the arguments must be passed some other way. – mata May 04 '13 at 23:27
  • It seems like it's working, but I after int 0x80 I get a value of 0xfffffff7 in eax when allocating 512 bytes. Seems a bit too high. (still debugging) – Lennart May 04 '13 at 23:38
  • Could be, but according to the man pages the address returned on error is -1, and the value of eax changes when I change mmap_arg.len . Edit: Oh you edited your post already. – Lennart May 05 '13 at 00:23

1 Answers1

3

One change, the args definition must be dd, not dq on ia32. The mallocSample function below will return the recently allocated memory into eax.

        global  main
        extern  printf

        section .data
mmap_arg:  ; ugly
  .addr:   dd 0
  .len:    dd 512
  .prot:   dd 3
  .flags:  dd 34
  .fd:     dd -1
  .offset: dd 0

        section .text

mallocSample:
        ;old_mmap
        mov eax, 90
        lea ebx, [mmap_arg]

        int $80

        ret

main:
        ;malloc sample
        call mallocSample
        push eax
        push    message
        call    printf
        add     esp, 8
        ret
message:
        db      'our malloc gives address: 0x%x', 10, 0
elvena
  • 411
  • 3
  • 5
  • Thanx, it makes much more sense to store adresses and such in a dword. What is the big difference between `lea a, [b]` and `mov a,b` (except speed)? – Lennart May 05 '13 at 05:41
  • 1
    None in this case. You could read about lea/mov differences at http://stackoverflow.com/questions/1658294/whats-the-purpose-of-the-lea-instruction - I'll edit the above answer to leave that clear. – elvena May 05 '13 at 06:01
  • What if, I want len to be a variable rather than hard-coded constant value. Which instruction to use? – Sourav Kannantha B Jul 05 '21 at 18:39