2016-04-28 4 views
0

Ich habe derzeit eine Aufgabe, wo ich in Assemblersprache programmieren muss, wo Sie Benutzereingabe nehmen, um einen 4-stelligen hexadezimalen Wert zu erhalten und in binär zu konvertieren und dann, nachdem Sie den Binärwert erhalten haben wandeln Sie es in einen Monat Tag und Jahr um, wobei die ersten 7 Ziffern das Jahr sind, die nächsten vier sind der Monat und die letzten 5 sind der Tag.Assembly Language Shift in Carry Flags

Ich habe alles in Binär umgewandelt und habe eine Idee, wie man es von binären in normale ganzzahlige Werte für Jahr, Monat und Tag bekommt. Wenn ich meinen Code ausführe, ist die Ausgabe 0/0/0. Ich bin mir nicht sicher, ob es dort ist, wo ich meine Verschiebung oder etwas anderes vermasselt habe. Kannst du einen Blick darauf werfen und mir eine Eingabe geben, wo du korrigieren sollst? In dem Code, den ich anlege, stelle ich nur calcYear auf und rechne damit, dass ich das herausfinden kann und arbeite dann an dem Rest von dort.

Mein Code:

firstLine: 

    call crlf 
    mov si, offset programOne 
    mov cx, programOneLen 
    call putStrng  ;displays 'Program by Joe Remaklus' 

    call crlf 
    call crlf 

    call inputVal ;prompt for hex input 
    call putBin ;display the value in AX as binary 
    call crlf 
    call calcYear ;display the year of the first 7 binary digits. 
    mov si, offset slash 
    mov cx, slashLen 
    call putStrng 
    call calcMonth ;display the month of the next 4 binary digits. 
    mov si, offset slash 
    mov cx, slashLen 
    call putStrng 
    call calcDay ;display the day of the next 5 binary digits. 
    call crlf 

    call inputVal 
    call putBin 






    mov ah,04c 
    int 021 




prompt db 'Enter a 4-digit hex value' 

lenPrompt = $-prompt 


inputVal: 

    push si, cx 

    mov si, offset prompt 

    mov cx, lenPrompt 

    call putStrng 

    call crlf 

    call getHex 

    call crlf 

    pop cx, si 

    ret 
;--------------------------------------------------------------- 

putBin: 

    push ax, cx, dx 

    mov cx, 16  ;number of bits to display 

    putBinLoopTop: 

    mov dl, '0'  ;assume bit to display is zero 

    shl ax, 1  ;shift bit to display into Carry Flag 

    jnc putBinSkipInc ;if the top bit was zero skip the inc 

    inc dl   ;else inc DL to '1' 

    putBinSkipInc: 

    call putChar  ;display the character in DL 

    loop putBinLoopTop ;continue until 16 bits are displayed 

    pop dx, cx, ax 

    ret 
;--------------------------------------------------------------- 

calcYear: 

    mov year, 0 

    mov si, 0 

    shl ax, 1 
    adc si, 0 
    iMul onetwoeight 
    add year, si 
    mov si, 0 

    shl ax, 1 
    adc si, 0 
    iMul sixfour 
    add year, si 
    mov si, 0 

    shl ax, 1 
    adc si, 0 
    iMul threetwo 
    add year, si 
    mov si, 0 

    shl ax, 1 
    adc si, 0 
    iMul sixteen 
    add year, si 
    mov si, 0 

    shl ax, 1 
    adc si, 0 
    iMul eight 
    add year, si 
    mov si, 0 


    shl ax, 1 
    adc si, 0 
    iMul four 
    add year, si 
    mov si, 0 


    shl ax, 1 
    adc si, 0 
    iMul two 
    add year, si 
    mov si, 0 


    shl ax, 1 
    adc si, 0 
    iMul one 
    add year, si 
    mov si, year 
    add si, 1980 
    call putPos 
ret 
+0

Haben Sie dies in einem Debugger in einem Schritt ausgeführt, um sicherzustellen, dass Werte in Regs Ihren Erwartungen entsprechen? Du hast Recht, dass 'shl ax' /' adc si, 0' gleichbedeutend damit ist, ein bisschen in ax zu testen und dann 'setcc' zu verwenden. (z. B. 'xor dx, dx' /' bt ax, 3'/'setc dl', außer dass dies' ax' nicht ändert) Ich bin überhaupt nicht überzeugt, dass Ihre 'imul's sinnvoll sind. Vielleicht ist es eine wirklich runde Sache, etwas zu tun, aber ich habe nicht herausgefunden, was. Sie wissen, dass das Multiplizieren mit Potenzen von 2 das Gleiche wie das Verschieben ist, oder? Außerdem könnten Sie 'year' in' si' die ganze Zeit behalten, anstatt ständig ein Speicherziel zu verwenden. –

+0

downvoted für das Fehlen von Kommentaren im Code oder die Beschreibung von welchem ​​Algorithmus genau das Jahr calc soll implementiert werden. Es sieht aus wie eine Art von seltsamen Hinzufügen der Bits zu mir (popcnt). Auch wenn Sie kein minimales Beispiel haben, das nur das Problem zeigt, das Sie haben. Das ist immer noch viel Code. Wenn du die Frage verbesserst, hinterlasse eine Antwort und entferne meinen Downvote. –

+1

Nein. Verwenden Sie einen Debugger, um festzustellen, wo Ihr Code falsch läuft, und wenn Sie nicht sehen können, warum dieses bestimmte Verhalten auftritt, fragen Sie erneut nach etwas genauerem als "... Eingabe auf, wo zu korrigieren." –

Antwort

1

Wenn ich Sie richtig verstehe, bei Eintritt von calcYear Ihre "Axt", wie dies in binärer aussieht: yyyy yyym mmmd dddd

Und Sie wollen die Werte extrahieren zurück zu gewöhnlichen Zahlen. Ich denke, ich kann Ihre Idee von "calcYear" verstehen, aber es tut mir leid, nicht zu versuchen, es vollständig zu verstehen und zu beheben. Wenn Sie immer noch neugierig sind, verwenden Sie einfach den Debugger, um einen Schritt über jede Anweisung zu gehen und zu sehen, wo sie in den Süden geht.

Ich werde Ihnen stattdessen zeigen, wie Sie über dieses Problem anders denken.

Lassen Sie uns versuchen Trog zu graben und diese verstehen:

; ax is encoded as this: yyyy yyym mmmd dddd 
    push ax 
    push ax ; store the encoded value at stack twice 
    ; extract "day" value 
    and ax,01Fh ;only "d" bits will survive 
    mov [day],ax 
    ; extract "month" value 
    pop ax ; restore encoded input 
    shr ax,5 ; shift ax by number of "d" bits 
    and ax,0Fh ; only shifted "m" bits 
    mov [month],ax 
    ; extract "year" value 
    pop ax ; restore encoded input 
    shr ax,5+4 ; shift ax by number of "d" and "m" bits 
    ; no need to "and", as "shr" did fill upper bits by zeroes 
    add ax,1980 ; so "0" encoded year is 1980? (deducted from OP source) 
    mov [year],ax 
    ret 

Ich hoffe, das Ihnen einige neue Ideen geben, wie mit bestimmten Bits in der Zahl zu arbeiten. Denken Sie daran, and/or sind gut, um Dinge auszublenden, die Sie interessiert sind und shr/sar/sal/shl/ror/rol/rcr/... sind gut, um es in die gewünschte Position zu bringen. xor kann verwendet werden, um das Ergebnis etwas zu patchen (wenn nötig), test ist wie and, aber nur Flags Register Update erhalten, und dann gibt es einige Bit orientierte x386 + (oder 486?) Anweisungen, die etwas "fortgeschritten" sind und speichern können Sie einige 2-3 Befehlskombinationen jener Grundlagen, die ich vorher erwähnte. So können Sie sie gefahrlos ignorieren, solange Sie diese Grundlegenden vollständig verstehen und alles mit ihnen nach Belieben biegen können.

+0

Und falls du neugierig bist, wie ich über das Problem nachgedacht habe ... leider habe ich dir nur die Hälfte der Magie gezeigt, das ist die allererste Zeile: '; ax ist wie folgt kodiert: yyyy yyym mmmd dddd' = 1) stelle sicher, dass du verstehst, was deine Eingabedaten sind.Die versteckte zweite Hälfte der Magie ist 2), um die gewünschten Ausgabedaten vollständig zu kennen, in diesem Fall wollte ich "Jahr = 0yyyyyyy, Monat = 0000mmmm, Tag = 000ddddd" bekommen ... dann fing ich an zu überlegen, wie um diese Bits zu verschieben und sie durch Maskieren zu extrahieren, um die gewünschte Ausgabe zu erhalten. Stellen Sie sicher, dass Sie sich des Ziels ** voll bewusst sind, und suchen Sie dann einen Algorithmus, um es zu tun. – Ped7g

+0

Und letzte Anmerkung ... Wenn Sie Student sind, fragen Sie sich vielleicht, warum 'und ax, 01F' (warum ich Hex-Weg von 31 verwenden) ... weil nach Jahren der ASM-Programmierung kann ich fast die Bits in den Hex-Zahlen sehen , also zum Beispiel ist AA ein schönes "1010 1010" -Muster ... Denken Sie daran, dass alle 4 Bits (manchmal als "Nibble" bezeichnet) eine einzelne Hexadezimalzahl bilden, daher ist die Berechnung des Hexadezimalwerts von der langen Binärzahl für den Menschen tatsächlich einfacher, als zu versuchen, den Dezimalwert zu berechnen, der viele Multiplikationen und Additionen beinhaltet. Wenn ich "und reg, MASK" schreibe, und ich den Wert von MASK in binärem Zustand kenne, schreibe ich es einfach in hex vom Kopf. – Ped7g

+0

Keine Upvoting wegen Ihrer verrückten Vorschlag zu "Push Axt" zweimal. Wie wäre es, einmal zu pushen, dann einfach zu laden statt Pop? Oder noch besser, kopieren Sie es in ein anderes Register. Ansonsten, ziemlich gute Antwort, aber diese Code-Dump-Fragen fügen SO für zukünftige Leser keinen großen Wert hinzu. –