Montage-A86 - Anzeige Zeit
Arbeite ich an ein Assembler-Programm, um das system Zeit und Datum, wandle in ASCII und zeigt Sie auf dem monitor. Ich habe Mühe, es korrekt angezeigt werden und Sie nicht finden, wo ich schief gegangen ist. Dies ist für einen Auftrag, und ich würde eher Erklärungen als nur Lösungen, wenn möglich.
Hier ist mein code:
TITLE GETDTTM
PAGE 60, 132
; This program retrieve the system date and time,
; converts it to ASCII, and displays it to the screen
; Define constants
;
CR EQU 0DH ;define carriage return
LF EQU 0AH ;define line feed
EOM EQU '$' ;define end of message marker
NULL EQU 00H ;define NULL byte
;
; Define variables
;
JMP START
PROMPT DB CR, LF, "The current time is: ",EOM
PROMPT2 DB CR, LF, "The date is: ",EOM
TIME DB "00:00:00", CR, LF, EOM
DATE DB "00/00/0000", CR, LF, EOM
;
; Program code
;
START:
CALL GET_TIME ;call function to get system time
CALL GET_DATE ;call function to get system date
LEA DX, PROMPT ;print time prompt to screen
MOV AH, 09H
INT 21H
LEA DX, TIME ;print time
MOV AH, 09H
INT 21H
LEA DX, PROMPT2 ;print date prompt to screen
MOV AH, 09H
INT 21H
LEA DX, DATE ;print date
MOV AH, 09H
INT 21H
CVT_TIME: ;converts the time to ASCII
CALL CVT_HR
CALL CVT_MIN
CALL CVT_SEC
RET
CVT_HR:
MOV BH, CH ;copy contents of hours to BH
SHR CH,4 ;convert high char to low order bits
ADD CH, 30H ;add 30H to convert to ASCII
MOV [TIME], CH ;save it
AND BH, 0FH ;isolate lower 4 bits
ADD BH, 30H ;convert to ASCII
MOV [TIME+1], BH ;save it
RET
CVT_MIN:
MOV BH, CL ;copy contents of minutes to BH
SHR CL, 4 ;convert high char to low order bits
ADD CL, 30H ;add 30H to convert to ASCII
MOV [TIME+3], CL ;save it
AND BH, 0FH ;isolate lower 4 bits
ADD BH, 30H ; convert to ASCII
MOV[TIME+4], BH ;save it
CVT_SEC:
MOV BH, DH ;copy contents of seconds to BH
SHR DH, 4 ;convert high char to low order bits
ADD DH, 30H ;add 30H to convert to ASCII
MOV [TIME+6], DH ;save it
AND BH, 0FH ;isolate lower 4 bits
ADD BH, 30H ;convert to ASCII
MOV[TIME+7], BH ;save it
GET_DATE: ;get date from the system
MOV AH, 04H ;BIOS function to read date
INT 1AH ;call to BIOS, run 04H
CALL CVT_DATE
RET
;CH = Century
;CL = Year
;DH = Month
;DL = Day
;CF = 0 if clock is running, otherwise 1
CVT_DATE:
CALL CVT_MO
CALL CVT_DAY
CALL CVT_YR
CALL CVT_CT
RET
CVT_MO: ;convert the month to ASCII
MOV BH, DH ;copy month to BH
SHR BH, 4 ;convert high char to low order bits
ADD BH, 30H ;add 30H to convert to ASCII
MOV [DATE], BH ;save in DATE string
MOV BH, DH ;copy month to BH
AND BH, 0FH ;isolate lower 4 bits
ADD BH, 30H ;convert lower bits to ASCII
MOV [DATE+1], BH;save in DATE string
RET
CVT_DAY: ;convert the day to ASCII
MOV BH, DL ;copy days to BH
SHR BH, 4 ;convert high char to low order bits
ADD BH, 30H ;add 30H to convert to ASCII
MOV [DATE+3], BH ;save in DATE string
MOV BH, DL ;copy days to BH
AND BH, 0FH ;isolate lower 4 bits
ADD BH, 30H ;convert lower bits to ASCII
MOV [DATE+4], BH;save in DATE string
RET
CVT_YR: ;convert the year to ASCII
MOV BH, CL ;copy year to BH
SHR BH, 4 ;convert high char to low order bits
ADD BH, 30H ;convert to ASCII
MOV [DATE+8], BH ;save it
MOV BH, CL ;copy year to BH
AND BH, 0FH ;isolate low order bits
ADD BH, 30H ;convert to ASCII
MOV [DATE+9], BH ;save in DATE string
RET
CVT_CT: ;convert the century to ASCII
MOV BH, CH ;copy century to BH
SHR BH, 4 ;convert high char to low order bits
ADD BH, 30H ;convert to ASCII
MOV [DATE+6], BH ;save it
MOV BH, CH ;copy century to BH
AND BH, 0FH ;isolate low order bits
ADD BH, 30H ;convert to ASCII
MOV [DATE+7], BH ;save it
RET
;
;Program End
;
End
Und hier ist, was ich bekomme, wenn ich es um 9:11 Uhr am 2/19/2015:
The current time is: 09:00:00
The date is: 02/09/0005
Habe ich versucht, um viele Kommentare von meinen Absichten, so dass Sie können erhalten eine Idee von, was ich versuche zu tun, und einfacher sehen, ob es irgendeine Art von Logik-Fehler. Ich denke, es ist ziemlich klar, von der Ausgabe, die fehlt mir immer meine Minuten und Sekunden in der ZEIT und haben einige Ideen, wie Sie zu beheben, aber nach Mittag, ich bekomme einige seltsame Zeiten, und ich bin verwirrt, was passiert mit meinem Termin. Jede Hilfe wird sehr geschätzt.
Edit: Hab mal auf der Arbeit durch die Spaltung von es und tatsächlich Umgang mit Minuten und Sekunden... Hoppla. Nun meine Ausgabe ist wie folgt:
Run at 9:23AM auf 02/19/2015
The current time is: 09:23:02
The date is: 02/09/0005
EDIT2: Immer näher! Vielen Dank für den [DATUM] fangen - ich behoben, und bin immer richtige Monat und Tag Werte, und näher auf Jahreswerte. Herausgefunden ich war nicht Verschiebung weit genug, da Jahr ist 4 Zeichen lang - 16-bit, nicht 8! - also ich konnte nicht die ganze Sache von nur SHR 4 bits! Meine Ausgabe sieht nun folgendermaßen aus:
The current time is: 09:43:02
The date is: 02/19/0015
EDIT 3: Hinzugefügt CVT_CT zum konvertieren des Jahrhunderts zu ASCII und zu den [DATUM] string, aber bin noch immer die gleiche Ausgabe...
The current time is: 10:06:02
The date is: 02/19/0015
EDIT 4: ich vergaß hinzuzufügen, einen Anruf auf meine neue Funktion... Wow. Jetzt arbeiten!!! Danke Euch allen für Eure Hilfe!!!
The current time is: 10:09:02
The date is: 02/19/2015
Seite Frage: Irgendeine Idee, warum die Sekunden würden immer sein 02?
- Ein dickes Lob für eine Frage richtig. Wenn Sie lernen wollen, sollten Sie Schritt in einen debugger und sehen, wo Sie es nicht tun, was Sie wollen. In der aktuellen form, die Sie natürlich gar nichts mit
CL
undDH
so offensichtlich Sie don ' T erhalten jede Ausgabe für Minuten oder Sekunden. Die gleiche Logik, die Sie für die Stunden sollte den trick tun. Möchten Sie vielleicht passieren in dem Ort, wo Sie wollen, dass die Ausgabe an denCVT_TIME
- Funktion, so können Sie es wiederverwenden für alle 3 Teile. - Danke, ich habe es aufgeteilt und es funktioniert jetzt, irgendwie ganz übersehen die Tatsache, dass ich war nicht etwas zu tun mit Ihnen, bis ich dies geschrieben, haha. Leider, ich habe keinen debugger. Ich bin mit A86 emuliert auf DosBox unter Mac OSX - geschehen, zu wissen, jeder Debugger, der für mich arbeiten würde?
- Sie sind mit
DH
in IhremCVT_MO
Funktion und so verlieren Sie die Monats-Daten (Verwendungpush
undpop
zu bewahren-Register). Sie schreiben auch mehr als einmal zu[date]
-- ohne index-wo Sie wahrscheinlich wollen, um Zeichen einzufügen, die im weiteren string. - Danke für den Fang, dass ich Schreibe, um [Datum] zweimal. Behoben, und bin immer, was richtig zu sein scheint Tage und Monate. Jahr ist immer noch schlecht benehmen, trotz mittlerweile Rechnungswesen für alle 16 bits. Sorry, aber ich verstehe nicht die DH-Kommentar - können Sie mir sagen, welche Zeile der CVT_MO Funktion, die Sie sehen es auf?
- Könnte es sein, verlieren die oberen beiden Zeichen des Datums, denn ich bin bewegt, es zu BH - ein 8-bit register? Nevermind - ich Ignoriere Jahrhundert! Testen Sie jetzt!!
- (.. am 2. Gedanke: vielleicht die umgekehrte notation von Quelle und Ziel hat mich verwirrt. Dennoch -- das speichern und wiederherstellen der verwendeten Register nie geschadet niemand.)
- dosbox selbst hat einen eingebauten debugger, aber Sie müssen eine version mit aktiviert. Alternativ können Sie alle dos-debugger innerhalb von dosbox, wie turbo-debugger.
- Könnten Sie bitte fügen Sie den gesamten code, und wir werden haben Sie einen Blick auf, warum die Sekunden werden immer als 02? Ich war auf der Suche für die GET_TIME routine, aber ich kann es nicht sehen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
All die individuellen (aber sehr ähnliche) Funktionen für die Umwandlung von BCD-in Zeichen, sind etwas chaotisch und in der Nähe garantiere, Sie werden Durcheinander bringen, einige kleinere Sache, wie dem vergessen zu bewahren, meldet, wenn Sie möglicherweise nicht die Werte in der Sie später auf.
Wenn du daran interessiert bist, dies zu vermeiden, schauen Sie in die DRY (don ' T repeat yourself) Prinzip (im Gegensatz zu NASS (alles doppelt schreiben). Die Wikipedia-Seite zum TROCKNEN ist ein guter Anfang.
Wenn Sie verbringen einige Zeit darüber nachzudenken, was bewegt werden kann, um gemeinsamen code (d.h., refactoring), werden Sie am Ende mit weit weniger - code zu kümmern, und daher weit weniger Möglichkeiten für Fehler einschleichen.
Prime z.B. in deinem Fall ist der code, der nimmt jedes BCD-Wert und schafft zwei Zeichen. Dieser verbraucht etwa vierzig Zeilen code (und das ist nur für das Datum etwas, ich nehme an, es hätte eine andere dreißig-ungerade Linien für die Zeit, die Sie hatten gezeigt, dass).
Wenn du Blick auf den code unten, du wirst sehen, ich habe umgestaltet, mit in
put_bcd2
für insgesamt dreizehn Zeilen Quelltext - auch wenn Sie bump, dass bis zu zwanzig-sieben wegen der zusätzlichen Linien benötigt, es zu nennen, das ist immer noch eine massive Reduktion. Diese stark simplifyies sowohl der Programmcode, der die Konvertierung und den code, der es verwendet.mov ah, al
/shr ah, 4
können Sie entpacken Sie beide nibbles in parallel.and ax, 0f0fh
/add ax, '00'
/mov [bx], ax
/add bx, 2
. Ich Schätze, Sie schreiben diese für den menschlichen Lesbarkeit, nicht für Effizienz, obwohl? Oder waren Sie die Optimierung für die code-Größe durch die Nutzunginc bx
zweimal, statt 3-byte -add bx, 2
und ein[bx+1]
addressing mode (+1 byte)? Wahrscheinlich nicht, sonst würden Sie verwendet habenal
stattax
für das 2-byte -add/and al, imm8
Codierungen.