[c -> asm]Umsetzung einer if-Verzweigung in Assembler



  • Hallo c-Community,

    ich versuche mich derzeit ein wenig in der Umsetzung von c in asm. Ich habe dazu ein Tutorial in welchem folgendes Beispiel verwendet wird:

    int number;
    ...
    if (number<0){
      ...
    }
    

    Die Umsetzung in asm sieht wie folgt aus:

    number dw 0
    ...
    mov eax, number
    or  eax,eax    #[s]ich kenne 'or reg, reg' -> reg=0[/s]# mit xor verwechselt
    jge label
    <no>
    ...
    label: <yes> ...
    

    So wie ich den Quellcode verstehe, wird durch die "or" Anweisung der Wert in eax auf Null gesetzt (was durch andere Operationen wie "mov eax, 0" glaube ich schöner wäre), egal welcher Wert in number ist. Die Funktion der or-Anweisung ist unklar. Außerdem fehlt mir der cmp-Befehl.

    Also nach meinen Überlegungen, sollte der Quellcode wie folgt aussehen:

    number dw 0
    ...
    mov eax, number
    mov ebx, 0
    cmp eax, ebx
    jge label
    <no>
    ...
    label: <yes>...
    

    Hoffe jemand mit fundierteren Kenntnissen in asm kann mir hier erklären, ob ich falsch liege.

    Vielen Dank
    mirrowwinger

    [Edit1] Anderung if-Schleife in if-Verzweigung und korrektur zu or [/Edit1]



  • mirrowwinger schrieb:

    So wie ich den Quellcode verstehe, wir durch die "or" Anweisung der Wert in eax auf Null gesetzt (was durch andere Operationen wie "mov eax, 0" glaube ich schöner wäre), egal welcher Wert in number ist. Außerdem fehlt mir der cmp-Befehl. außerdem wird

    Du scheinst hier optimierten Code zu betrachten. Optimierter Code ist für Menschen meist schwer nachzuvollziehen.

    "or eax,eax" wird hier letztlich als compare benutzt. Da der Befehl die Flags entsprechend setzt (kannst du in einer x86-Assembly Referenz nachschauen), kann er benutzt werden um mit 0 zu vergleichen. Dadurch kannst du auf "cmp" verzichten.

    mirrowwinger schrieb:

    Also nach meinen Überlegungen, sollte der Quellcode wie folgt aussehen

    Dein Code setzt ebx auf 0 und benutzt dann cmp. Der optimierte Code vergleicht auch mit 0, verbraucht aber 1 Register und einen Befehl weniger.





  • Es wird nicht mit 0 verglichen, sonder geprüft ob das Sign Flag (SF) gesetzt ist und somit ob der Wert keiner 0 ist (im 2er Komplement). JGE ist didaktisch ungeschickt gewählt, da geprüft wird ob SF == OF und letzteres von logischen Befehlen immer gelöscht wird - besser verständlich wäre hier JNS.

    mirrowwinger schrieb:

    Operationen wie "mov eax, 0" glaube ich schöner wäre

    XOR reg,reg ist der schönste weg ein Register auf 0 zu setzen. MOV verwendet man nur wenn die Flags nicht modifiziert werden sollen.

    Hier eine Variante die nur die Flags modifiziert:

    test number,-1
    jns label
    


  • Danke an alle für die Beiträge, glaube habe jetzt schon mehr verstanden.

    mirrowwinger



  • Im Falle ein Register durch den DEC-Befehl auf Null gesetzt wird, dann wird auch das Zero-Flag gesetzt:

    dec eax
    jz Adresse
    
    number dd 0       ; für einen 32 bit Zugriff sollten auch 4 bytes reserviert werden
    ...
    mov eax, [number] ; verwende eckige Klammern, um Missverständnisse zu vermeiden
    

    Dirk



  • MinMaxMean schrieb:

    Hier eine Variante die nur die Flags modifiziert:

    test number,-1
    jns label
    

    Auf wieviele Bytes soll zugegriffen werden:

    test dword[number],-1
    jns label
    

    Dirk



  • Da Zahlen, die kleiner als Null sind, üblicherweise eine 1 vorne (also ganz links) haben, könnte man auch mit dem Befehl BT http://en.wikipedia.org/wiki/Bit_Test rummachen. Das wäre dann bei Zahlen, die größer als die Registerbreite sind, ganz praktisch.

    Aber man kann es erstmal ganz einfach übersetzen:

    cmp eax,0; Int im eax-Register
    JL Adresse; JB für vorzeichenlose Werte
    

    der Befehl "OR eax,eax" wird u.a. dafür benutzt, um zu schauen, ob ein Register schon auf 0 steht. Denn OR 0000 vs 0000 ergibt 0000. In diesem Fall kann man auch direkt mit JNZ bzw. JZ im Anschluß arbeiten.

    Bei Übersetzungen nach Assembler scheint es sinnvoll zu sein, sich zuerst an einer guten Lesbarkeit zu orientieren. Das ist nämlich etwas, das kann man mit Sicherheit immer noch etwas besser, als ein "optimierender" Compiler.


Anmelden zum Antworten