1

I am trying to mexify a C program which links with an object assembled with nasm which uses the sys_newstat system call to get the size of a file. The program returns the correct file size when compiled with gcc, but only returns a file size of 0 when mexified.

Here is the assembly program:

    default rel
    global getSize
    sys_newstat     equ 106

    struc STAT
        .st_dev:        resd 1
        .st_ino:        resd 1
        .st_mode:       resw 1
        .st_nlink:      resw 1
        .st_uid:        resw 1
        .st_gid:        resw 1
        .st_rdev:       resd 1
        .st_size:       resd 1
        .st_blksize:    resd 1
        .st_blocks:     resd 1
        .st_atime:      resd 1
        .st_atime_nsec: resd 1
        .st_mtime:      resd 1
        .st_mtime_nsec: resd 1
        .st_ctime:      resd 1
        .st_ctime_nsec: resd 1
        .unused4:       resd 1
        .unused5:       resd 1
    endstruc

    %define sizeof(x) x %+ _size

    section .data
        fileName: db "input.xml",0

    section .bss
        stat: resb sizeof(STAT)

    section .text
    getSize:
;; Get the size of the file
            mov rbx, fileName
            mov rcx, stat
            mov rax, sys_newstat
            int 80H
            mov rax, [stat + STAT.st_size]
        ret

Here is the C program:

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

    extern int getSize();

    void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])  {
        int size = getSize();
        printf("%d \n", size);
    }

Here is the command I use to compile the assembly program:

    nasm -felf64 -o getSize.o getSize.asm

Here is the command I use to mexify my C program:

    mex main.c getSize.o

All help will be greatly appreciated. Thank You

OshaMan
  • 111
  • 6
  • googling for the the [`stat`](http://linux.die.net/man/2/stat) struct which resides in ``, it appears that the size of the fields are platform dependent. So on 64-bit Linux, these might be 2 bytes and 4 bytes, rather than 1 and 2 byte as you defined them above.. Maybe that's the problem? – Amro Aug 27 '13 at 23:04
  • It works fine with gcc, though. – OshaMan Aug 27 '13 at 23:14
  • 1
    Under 64-bit Linux system calls are normally done using the "syscall" instruction instead of "int 80h". The meaning of the registers is different in this case. If you compile the program using GCC all addresses are typically below 2GB however in the MEX file the addresses may be above 2GB. "int 80h" might work for adresses below 2GB only. To test this behavior you should create a dynamic library (.so) that contains your assembler code and a test C program that uses this dynamic library. – Martin Rosenau Aug 28 '13 at 06:20
  • Here is a relevant question about making system calls on various platforms: http://stackoverflow.com/q/2535989/97160. This question talks about the `stat` struct layout: http://stackoverflow.com/q/14355466/97160 – Amro Aug 28 '13 at 12:46
  • Thank You. I probably wouldn't have figured it out without your help. – OshaMan Aug 28 '13 at 21:31

1 Answers1

1

I figured it out. Here is what I did.

    default rel
    global getSize
    sys_newstat     equ 4

    struc STAT
        .st_dev:        resq 1
        .st_ino:        resq 1
        .st_nlink:      resq 1
        .st_mode:       resd 1
        .st_uid:        resd 1
        .st_gid:        resd 1
        .pad0:          resd 1
        .st_rdev:       resq 1
        .st_size:       resq 1
        .st_blksize:    resq 1
        .st_blocks:     resq 1
        .st_atime:      resq 1
        .st_atime_nsec: resq 1
        .st_mtime:      resq 1
        .st_mtime_nsec: resd 1
        .st_ctime:      resq 1
        .st_ctime_nsec: resq 1
        .unused:        resq 3
    endstruc

    %define sizeof(x) x %+ _size

    section .data
        fileName: db "input.xml",0

    section .bss
        stat: resb sizeof(STAT)

    section .text
    getSize:
        ;; Get the size of the file
        mov rax, sys_newstat
            mov rdi, fileName
            mov rsi, stat
            syscall
            mov rax, [stat + STAT.st_size]
        ret

Everything else is the same.

I got my system call information from /usr/include/asm/unistd_64.h. I got my struct stat information from /usr/include/asm/stat.h.

OshaMan
  • 111
  • 6