2015-04-29 7 views
5

Ich versuche, dieses C-Code zu erhalten:Konvertieren von C NASM Montage mit Segmentierung Ausgabe

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

seiner NASM Äquivalent, die ich habe dies bisher:

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 

Ich halte eine immer Segmentierungsfehler und ich verstehe nicht, warum es so weitergeht. Ich habe versucht, überall Druckanweisungen hinzuzufügen und kann nicht finden, wo der Fehler liegt. Jeder Rat wäre großartig! Vielen Dank!

+0

Ihr asm mir in Ordnung zu sein scheint. – peterh

+0

Haben Sie eine 'ret' Anweisung nach den' printf's? – Diego

+0

Ja, ich habe es satt, dass es sich nicht um das Segmentierungsproblem gekümmert hat :( – mm19

Antwort

0

Ich denke, Sie folgen nicht der Aufrufkonvention für printf (es ist cdecl IIRC).

  1. der Anrufer muss reinigen Sie den Stapel nach dem Aufruf
  2. und EAX von dem ersten Aufruf von printf verprügelt wird damit Rückgabewert ist

Nummer eins wird zu Problemen führen, wenn sie von main zurückkehrt. Eigentlich gibt es keine ret Anweisung nach den printf s ist, die die Ausführung verursacht zu gehen, bis etwas schief geht :)

Fügen Sie den folgenden nach dem Druck:

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 

Obwohl dies nicht kümmern Problem nicht nehmen Nummer zwei.

+0

Danke, das hat ziemlich geholfen, ich werde sehen, ob es funktioniert. – mm19

+0

Diego, da dies ein eigenständiges Assembly-Programm ist, gibt es Keine 'main' und keine Notwendigkeit, zurückzukehren.Was benötigt wird, ist ein syscall zum Beenden auf Cleanup bei Programmbeendigung zu machen. Der Exit-Code ist in' ebx', der ** x86 ** syscall für den Ausgang ist '1' (siehe: '/ usr/include/asm/unistd_32.h') und geht in' eax', dann wird der Kernel aufgerufen, um den Befehl 'int 0x80' oder' int 80h' auszuführen. –

+0

@ DavidC.Rankin: Einen Exit machen Systemaufruf statt Rückkehr ist offensichtlich in Ordnung, aber dieses Programm hat eindeutig eine "Hauptfunktion". Die meisten Assemblierungsprogramme, die mit der Standard-C-Bibliothek verbunden sind, haben einen. –

0

aktualisiert und vollständiges Beispiel:

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

ja, so soll es sein :) – Diego

+0

ich bekomme immer noch die Segmentierung Fehler mit den Änderungen – mm19

0

Wenn Sie nicht haben es noch aussortiert, das Problem ist aufgrund eax auf Ihrem printf Anruf verprügelt zu werden. Wie repariert man? Speichern Sie es in einem Puffer vor dem ersten printf Aufruf und laden Sie eax vor dem zweiten. Z.B. hinzufügen:

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 

Verwendung/Output

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

Ich bin mir nicht sicher, ich würde Zeit und Mühe Codierung verschwenden Wenn du einen perfekten Stack hast, der nur darauf wartet, benutzt zu werden, musst du einen Puffer dafür einbauen :-) "Push eax", "pop eax". – paxdiablo

Verwandte Themen