2015-04-29 18 views
5

Sto cercando di ottenere questo codice C:Conversione C a NASM montaggio con problema di segmentazione

main() 

{int x, y, count ; 

    count = 0 ; 
    x = 10 ; 
    y = 2 ; 
    while (y < x) 
    { x = x + 1 ; 
     y = y + 2 ; 
     count = count + 1 ; 
    } 

    printf(“ It took %d iterations to complete loop. That seems like a  lot\n”,count) ; 
} 

al suo equivalente NASM che ho questo finora:

segment .data 

out1 db "It took ", 0 
out2 db "%i ", 0 
out3 db "iterations to complete the loop. That seems like a lot.", 10, 0 

segment .bss 

segment .text 

global  main 
extern printf 

main: 

    mov eax, 0  ;count 
    mov ebx, 10  ;x 
    mov ecx, 2  ;y 

    jmp  lp 

    mov eax, 0 
    ret 

lp: 
    cmp ecx, ebx ;compare y to x 
    jge end  ;jump to end if y >= x 
    add eax, 1 
    add ebx, 1 
    add ecx, 2 
    jmp lp 

end: 

    push out1 
    call printf 

    push eax 
    push out2 
    call printf 

    push out3 
    call printf 

Continuo a ricevere un segmentation fault e non capisco perché continua a succedere. Ho provato ad aggiungere dichiarazioni di stampa ovunque e non riesco a trovare dove si trova l'errore. Qualsiasi consiglio sarebbe grande! Grazie!

+0

tuo asm sembra a posto per me. – peterh

+0

Avete un'istruzione 'ret' dopo' printf's? – Diego

+0

sì, mi sono stancato che non si occupasse del problema di segmentazione :( – mm19

risposta

0

Penso che non si stia seguendo la convenzione di chiamata per printfcdecl IIRC).

  1. il chiamante deve pulire lo stack dopo la chiamata
  2. e EAX è rovinati dalla prima chiamata a printf con il suo valore di ritorno

Numero uno causerà problemi al ritorno dalla main. In realtà, non v'è alcuna ret istruzioni dopo le printf s che causa l'esecuzione di andare avanti fino a quando qualcosa va storto :)

Aggiungere il seguente dopo la stampa:

add  esp, 16 ; Fix stack, usually it's done after each call 
        ; with the appropiate values. 
        ; In this way (one fixup for many calls) stack 
        ; grows unnecessarily 
    xor  eax, eax ; set return value to 0 
    ret    ; Return from main 

Anche se, questo non si prende cura di emissione numero due.

+0

Grazie per avermi aiutato un bel po 'vedrò se funziona. – mm19

+0

Diego, dato che questo è un programma di assemblaggio indipendente, c'è no 'main' e non è necessario tornare.È necessario effettuare un syscall per uscire dalla pulizia al termine del programma.Il codice di uscita è impostato in' ebx', il ** x86 ** syscall per exit è '1' (vedi:/usr/include/asm/unistd_32.h') e va in 'eax', quindi il kernel viene chiamato per eseguire il comando' int 0x80' o 'int 80h'. –

+0

@ DavidC.Rankin: fare un'uscita la chiamata di sistema invece di ritornare è ovviamente soddisfacente, ma questo programma ha chiaramente una funzione 'main'. La maggior parte dei programmi di assemblaggio che collegano alla libreria C standard ne avrà uno –

0

aggiornato e completo esempio:

segment .data 
out1 db  "It took %d iterations to complete loop. That seems like " 
     db  "a lot.", 0aH, 00H 
segment .bss 
segment .text 
     global main 
     extern printf 
main: xor  eax, eax 
     mov  ebx, 10 
     mov  ecx, 2 
loop0: inc  ebx 
     add  ecx, 2 
     inc  eax 
     cmp  ecx, ebx 
     jl  loop0 
     push eax 
     push offset out1 
     call printf 
     add  esp, 8 
     xor  eax, eax 
     ret 
     end 
+0

sì, è così che dovrebbe essere fatto :) – Diego

+0

sto ancora ottenendo l'errore di segmentazione con le modifiche – mm19

0

Se non avete capito ancora risolto, il problema è dovuto alla eax sempre battuto sul printf chiamata. Come risolvere? Salvalo in un buffer prima della prima chiamata printf e carica eax prima del secondo. Per esempio. aggiungere:

segment .bss 

buffer resd 1   ; reserve 32 bit buffer 
... 
mov  [buffer], eax ; save eax in the buffer 

push out1 
call printf 

mov  eax, [buffer] ; load eax from the buffer 

push eax 
push out2 
call printf 

push out3 
call printf 

xor  ebx, ebx   ; exit nicely 
mov  eax, 1 
int  0x80 

Usa/Output

$ ./bin/pt 
It took 8 iterations to complete the loop. That seems like a lot. 
+0

Non sono sicuro che avrei sprecato tempo e fatica la codifica prendi un buffer per questo quando hai una pila perfettamente in ordine, in attesa di essere usata :-) In altre parole, 'push eax',' pop eax'. – paxdiablo