vendredi 29 mai 2015

nasm, macro print not working

I'm calling a function written in assembly from a C file. The c code passes two pointers to the assembly function. I'm using the print macro into the assembly to check the value of the addresses and of the elements pointed by them.

Here is the C code:

extern int nn_from_set(float *q, float *t, int q_length, int *s, int s_length);

int main()
{
    float *matrix_dyn = malloc(6*4*sizeof(float));
    int *s = malloc( 3 * sizeof(int))
    //the vectors are filled here
    //print their address, no problem here
    printf("t: %p, s: %p, sizeof int*: %u\n", matrix_dyn, s,  sizeof(matrix_dyn));
    //assembly function called
    printf("Prova: %d\n", nn_from_set(matrix_dyn, matrix_dyn, 3, s, 3));
    return 0;
}

Here is the assembly code, it's a bit long.

extern printf

%macro pabc 1           ; a "simple" print macro
section .data       
.strm db %1,0            ; %1 is first actual macro call

section .text

    ; push onto stack bacwards
    push dword [nnfs_int]                ; int a
    push dword .strm
    push dword nnfs_fmt_int              ; users string
    call printf                          ; call C function
    add esp, 12                           ; pop stack 3 * 4 bytes

%endmacro

    section .data
fmt: db "%s, dist: %e",10,0         ; format string for printf
nnfs_fmt: db "%s",10,0              ; format string for printf
nnfs_fmt_int:   db "%s %p",10,0     ; format string for int debug


    section .bss

nnfs_dst:   resd 1                  ; reserve 32-bit word
nnfs_tmp:   resd 1                  ; int tmp;
nnfs_index: resd 1                  ; reserve 32-bit, int index;  
nnfs_int:   resd 1

    section .text

; function to be translated is 
; int nearest_neighbor_from_set(float* q, float* t, int q_length, int* s, int s_length)

global nn_from_set

nnfs_q           equ     8
nnfs_t           equ     12
nnfs_q_length    equ     16
nnfs_s           equ     20
nnfs_s_length    equ     24

nn_from_set:
            ; -------------------------------------------
            ; Entrace sequence
            ; -------------------------------------------
            push    ebp         ; save base pointer
            mov     ebp, esp    ; point to current stack frame
            push    ebx         ; save general registers
            push    esi         
            push    edi

            mov ecx, [ebp + nnfs_t]     ; t
            mov edx, [ebp + nnfs_s]     ; s

            mov [nnfs_int], ecx         ; print t
            pabc "ecx, t: " 

            mov [nnfs_int], edx        ; print s 
            ;pabc "edx, s: "

            mov esi, [edx]              ; *s

            mov [nnfs_int], esi         ; print *s
            ;pabc "edx"

            add edx, 4
            mov esi, [edx]

            mov [nnfs_int], esi
            ;pabc "esi"

            ; fine di nn_from_set
            mov eax, 50         ; for test purpose

            ; ------------------------------------------
            ; Exit sequence
            ; ------------------------------------------

            pop     edi
            pop     esi
            pop     ebx
            mov     esp, ebp
            pop     ebp
            ret

I have two problems, with this version of the code, when I try to compile, it says that .strm is already defined, it does each time I try to call the macro after the first call.

Second problem. I change the macro like this:

 %macro pabc 1           ; a "simple" print macro

section .text

    ; push onto stack bacwards
    push dword [nnfs_int]                ; int a
    push dword nnfs_fmt_int              ; users string
    call printf                          ; call C function
    add esp, 8                           ; pop stack 2 * 4 bytes

%endmacro

I've removed the .strm argument. The format string is now:

nnfs_fmt_int:   db " reg %p",10,0

With this version, the first call of the macro prints correctly, the second goes wrong. For example, I call the macro to print the addresses of the two pointers:

mov [nnfs_int], ecx         ; print t
pabc "ecx, t: " 

mov [nnfs_int], edx        ; print s 
pabc "edx, s: "

Here is the output (the first line is printed from the C file):

t: 0x8500008, s: 0x8500070, sizeof int*: 4
 reg 0x8500008
 reg 0xf7778898

Address of t is printed correctly, s's one, not. If I invert the two calls.

mov [nnfs_int], edx         ; print s
pabc "ecx, t: " 

mov [nnfs_int], ecx        ; print t
pabc "edx, s: "

This is the output (the first line is printed from the C file):

t: 0x93a0008, s: 0x93a0070, sizeof int*: 4
 reg 0x93a0070
 reg (nil)

S is printed right, but t isn't.

I have no idea what is going wrong, I have used the same macro pattern and it hasn't created me any problem until now. The examples tha I used to create this macro are from here: http://ift.tt/1SGA5bO

Sorry for the long question, and thank you in advance for any help.

Aucun commentaire:

Enregistrer un commentaire