nasm,宏打印不工作

时间:2015-05-29 13:50:24

标签: c assembly macros nasm

我正在调用一个用C文件在程序集中编写的函数。 c代码传递两个指向汇编函数的指针。我正在使用print宏进入程序集来检查地址和它们指向的元素的值。

这是C代码:

id_cnt = 1
def give_id(id_constant=1000):
    global id_cnt
    id_cnt += 1
    return id_constant * id_cnt
id = give_id()

这是汇编代码,它有点长。

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;
}

我有两个问题,使用这个版本的代码,当我尝试编译时,它说已经定义了.strm,每次我尝试在第一次调用后调用宏时都会这样做。

第二个问题。 我像这样更改宏:

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

我删除了.strm参数。格式字符串现在是:

 %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

对于这个版本,宏的第一次调用打印正确,第二次出错。例如,我调用宏来打印两个指针的地址:

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

这是输出(第一行是从C文件打印的):

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

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

正确打印t的地址,s为1,而不是。如果我反转这两个电话。

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

这是输出(第一行是从C文件打印的):

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

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

S打印正确,但t不打印。

我不知道出了什么问题,我使用了相同的宏模式,直到现在它还没有给我带来任何问题。我用来创建此宏的示例来自此处:http://www.csee.umbc.edu/portal/help/nasm/sample.shtml

很抱歉这个问题很长,并提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

根据标准调用约定,一些寄存器被调用者保存,即eaxecxedx。因此,您不应期望通过call printf保留其价值。这大概就是为什么你打印错误的价值。您可以在打印第一个之前将第二个推入堆栈,然后将其弹回以进行打印。实际上,因为那些已经在堆栈中,你可以从那里重新加载:

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

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

; reload since printing changed ecx and edx
mov ecx, [ebp + nnfs_t]     ; t
mov edx, [ebp + nnfs_s]     ; s