2016-04-08 10 views
0

Das ist mein x86-Assembler-Code:Warum ist Segmention-Fehler beim Drucken?

section .data 
    output db '%d',10,0 
section .text 
    global main 
    extern printf 
main : 
    xor ecx,ecx 
    xor eax,eax 
    mov eax,1 
    mov ecx,5 
lable1: 
    push ecx 
    push eax 
    cmp eax,0 
    jg print 
    pop eax 
    pop ecx 
    inc eax 
loop lable1 
    ret 
print: 
    push eax 
    push output 
    call printf 
    add esp,8 
    ret 

Dieses Programm alle Zahlen zwischen 1 bis 5. gedruckt werden soll Warum erhalte ich einen Segmentation Fault immer nach ‚1‘ Druck?

+0

Sehen Sie sich die Aufrufkonvention/ABI-Links im [x86-Tag-Wiki] (http://stackoverflow.com/tags/x86/info) an. Sie könnten Ihre Zähler in Call-Conserved-Registern behalten, anstatt sie über printf zu verschieben. –

Antwort

4

print endet mit einer ret Anweisung, was bedeutet, dass es etwas ist, das Sie sollten call. So sollte jg printjng skip/call print/ sein (oder einfach call print, weil die > 0 Prüfung unnötig scheint).
call platziert die Rücksprungadresse auf dem Stapel, jg nicht.

+0

Ich weiß Check ist nicht notwendig. Ich will nur wissen, warum es nicht nach dem Drucken 1 zurück und Haupt gehen, um zu drucken und 1 bis 5 drucken. @Michael – jasonjpq

+0

Wie ich schon sagte, müssen Sie 'call' verwenden, wenn Sie' ret' erwarten zu arbeiten. – Michael

+0

Was kann ich tun, wenn ich den jg-Befehl verwenden und ihn erneut an main senden möchte? Ich möchte Nummer drucken, wenn es größer als 0 ist. (P.S. Dies ist nur Beispielcode, den ich für JG-Fehler geschrieben habe.) @Michael – jasonjpq

1

Der Grund, warum Sie immer Fehler bekommen, ist: Sie ignorieren den Stapel!

Ihre Unterroutine lable1 ist korrekt eingerichtet, aber mit Ihrer jg Sie auswerfen den Stack ignorieren - den Stapel beschädigt.

lable1: 
    push ecx 
    push eax 
    cmp eax,0 
    jg print 
    pop eax 
    pop ecx 
    inc eax 

Sie

xor eax,eax  ; EAX = 0 - breaking pipeline 
mov eax,1  ; EAX = 1 - which is redundant 

aber wegen Ihrer

cmp eax,0 
jg print 

im lable1 Unterprogramm, springen Sie in die print: Routine, wenn EAX größer als 0 ist (und es ist in der ersten Iteration mit EAX = 1) mit einem Stack - Offset von -8 verursacht durch

push ecx 
push eax 

am Anfang von lable1:. Die ret ting von print:, die den Stapel am Ende sauber aufräumt, bewirkt, dass Ihr Programm an die Adresse des ersten Eintrags des Stapels zurückkehrt, den Sie [ESP] = (früher EAX = 1) zugewiesen haben. im Wesentlichen: mov eax,1.

Daher erhalten Sie eine SegFault, weil Sie versuchen, auf die Adresse [00000001] (= EAX = 1,32bit) zu springen/zurückzukehren.

Verwandte Themen