Take notes on the command line: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) (Rename Perl 6 -> Raku, alphabetize, minor clean-up) |
Not a robot (talk | contribs) (Add 8086 assembly version) |
||
Line 9: | Line 9: | ||
Then all the arguments, joined with spaces, prepended with a tab, and appended with a trailing newline, are written to NOTES.TXT. |
Then all the arguments, joined with spaces, prepended with a tab, and appended with a trailing newline, are written to NOTES.TXT. |
||
If NOTES.TXT doesn't already exist in the current directory then a new NOTES.TXT file should be created. |
If NOTES.TXT doesn't already exist in the current directory then a new NOTES.TXT file should be created. |
||
=={{header|8086 Assembly}}== |
|||
This code assembles into a .COM file that runs under MS-DOS. |
|||
<lang asm> bits 16 |
|||
cpu 8086 |
|||
;;; MS-DOS PSP locations |
|||
cmdlen: equ 80h ; Amount of characters on cmdline |
|||
cmdtail: equ 82h ; Command line tail |
|||
;;; MS-DOS system calls |
|||
puts: equ 9h ; Print string to console |
|||
date: equ 2Ah ; Get system date |
|||
time: equ 2Ch ; Get system time |
|||
creat: equ 3Ch ; Create file |
|||
open: equ 3Dh ; Open file |
|||
close: equ 3Eh ; Close file |
|||
read: equ 3Fh ; Read from file |
|||
write: equ 40h ; Write to file |
|||
lseek: equ 42h ; Set current file position |
|||
exit: equ 4ch ; Exit |
|||
;;; File modes |
|||
O_RDONLY: equ 0 |
|||
O_WRONLY: equ 1 |
|||
;;; Error codes (well, we only need the one) |
|||
ENOTFOUND: equ 2 |
|||
;;; File positions (again we need only the one) |
|||
FP_END: equ 2 |
|||
;;; File buffer size |
|||
BUFSZ: equ 4096 |
|||
section .text |
|||
org 100h |
|||
cmp byte [cmdlen],0 ; Is the command line empty? |
|||
je printnotes ; Then, go print current notes |
|||
;;; Retrieve and format current date and time |
|||
mov ah,date ; Retrieve date |
|||
int 21h |
|||
mov di,datefmt ; Fill in date string |
|||
xor ah,ah |
|||
mov al,dh ; Write month |
|||
mov bl,2 ; Two digits |
|||
call asciinum |
|||
add di,3 ; Onwards three positions |
|||
mov al,dl ; Write day |
|||
mov bl,2 ; Two digits |
|||
call asciinum |
|||
add di,3 ; Onwards three positions |
|||
mov ax,cx ; Write year |
|||
mov bl,4 ; Four digits |
|||
call asciinum |
|||
mov ah,time ; Get system time |
|||
int 21h |
|||
mov di,timefmt+6 ; Fill in time string |
|||
xor ah,ah |
|||
mov al,dh ; Write seconds |
|||
mov bl,2 ; Two digits |
|||
call asciinum |
|||
sub di,3 ; Back three positions |
|||
mov al,cl ; Write minutes |
|||
mov bl,2 ; Two digits |
|||
call asciinum |
|||
cmp ch,12 ; AM or PM? |
|||
jbe houram ; <=12, AM |
|||
sub ch,12 ; PM - subtract 12 hours, |
|||
mov byte [ampm],'P' ; And set the AM/PM to 'P'(M) |
|||
jmp wrhours |
|||
houram: and ch,ch ; Hour 0 is 12:XX:XX AM. |
|||
jnz wrhours |
|||
mov ch,12 |
|||
wrhours: sub di,3 ; Back three positions |
|||
mov al,ch ; Write hours |
|||
mov bl,2 ; Two digits |
|||
call asciinum |
|||
;;; Open or create the NOTES.TXT file |
|||
mov dx,filnam |
|||
mov ax,open<<8|O_WRONLY |
|||
int 21h ; Try to open the file |
|||
jnc writenote ; If successful, go write the note |
|||
cmp al,ENOTFOUND ; File not found? |
|||
jne diefile ; Some other error = print error msg |
|||
mov ah,creat ; No notes file, try to create it |
|||
xor cx,cx ; Normal file (no attributes set) |
|||
int 21h |
|||
jc diefile ; If that fails too, print error msg |
|||
;;; Write the note to the file |
|||
writenote: mov bx,ax ; File handle in BX |
|||
mov ax,lseek<<8|FP_END ; Seek to end of file |
|||
xor cx,cx ; Offset 0 |
|||
xor dx,dx |
|||
int 21h |
|||
jc diefile ; Error if it fails |
|||
mov dx,datetime ; Write the date/time string first |
|||
mov cx,dtsize |
|||
mov ah,write |
|||
int 21h |
|||
jc diefile ; Error if it fails |
|||
mov cx,bx ; Store file handle in CX |
|||
;;; Terminate note with \r\n |
|||
xor bx,bx ; BX = length of command line |
|||
mov bl,[cmdlen] ; Find 2 bytes past cmd input |
|||
add bx,cmdlen+1 ; Note: this might overwrite the first |
|||
mov word [bx],0A0Dh ; instruction, but we don't need it |
|||
sub bx,cmdtail-2 ; Get length (add 2 for the 0D0A) |
|||
xchg bx,cx ; File handle in BX, length in CX |
|||
mov dx,cmdtail ; Write what's on the command line |
|||
mov ah,write |
|||
int 21h |
|||
jc diefile ; Error if it fails. |
|||
jmp closeexit ; Close file and exit if it succeeds. |
|||
;;; Print the contents of the NOTES.TXT file |
|||
printnotes: mov dx,filnam ; Open file for reading |
|||
mov ax,open<<8|O_RDONLY |
|||
int 21h |
|||
jnc readnotes ; Carry flag set = error. |
|||
cmp al,ENOTFOUND ; File not found? |
|||
jne diefile ; Some other error = print error msg |
|||
jmp exitok ; Not found = no notes = just exit |
|||
readnotes: mov di,ax ; Keep the file handle in DI. |
|||
.loop mov bx,di ; Get file handle for file |
|||
mov cx,BUFSZ ; Read as many bytes as will fit in the |
|||
mov ah,read ; buffer |
|||
int 21h |
|||
jc diefile ; Carry flag set = error |
|||
and ax,ax ; If 0 bytes read, we're done. |
|||
jz .done |
|||
xor bx,bx ; File handle 0 = standard output |
|||
mov cx,ax ; Write as many bytes as we read |
|||
mov ah,write |
|||
int 21h |
|||
jc diefile |
|||
jmp .loop ; Go get more bytes if there are any |
|||
.done mov bx,di ; Done: close the file |
|||
closeexit: mov ah,close |
|||
int 21h |
|||
exitok: mov ax,exit<<8|0 ; Exit with errorlevel 0 (success) |
|||
int 21h |
|||
;;; Print 'File error' and exit. |
|||
diefile: mov dx,fileerror |
|||
;;; Print error message in DX and exit |
|||
die: mov ah,puts ; Print error message |
|||
int 21h |
|||
mov ax,exit<<8|2 ; Exit with errorlevel 2. |
|||
int 21h |
|||
;;; Subroutine: write AX as BL-digit ASCII number at [DI] |
|||
asciinum: push dx ; Store DX and CX |
|||
push cx |
|||
mov cx,10 ; CX = divisor |
|||
xor bh,bh ; We never need >255. |
|||
.loop: xor dx,dx ; Set high word of division to 0. |
|||
div cx ; AX /= CX; DX = AX % CX |
|||
add dl,'0' ; Make digit ASCII |
|||
dec bl ; Move forward one digit |
|||
mov [di+bx],dl ; Store digit |
|||
jnz .loop ; Are we there yet? |
|||
pop cx ; Restore DX and CX |
|||
pop dx |
|||
ret |
|||
section .data |
|||
datetime: equ $ ; Start of date/time string. |
|||
datefmt: db '**/**/**** ' ; Date placeholder, |
|||
timefmt: db '**:**:** ' ; Time placeholder, |
|||
ampm: db 'AM' ; AM/PM placeholder. |
|||
db 13,10,9 ; \r\n\t |
|||
dtsize: equ $-datetime ; Size of date/time string. |
|||
fileerror: db 'File error.$' ; Printed on error |
|||
filnam: db 'NOTES.TXT',0 ; File name to use |
|||
section .bss |
|||
filebuf: resb BUFSZ ; 4K file buffer</lang> |
|||
{{out}} |
|||
<pre>A:\>dir/b notes.* |
|||
NOTES.COM |
|||
A:\>notes |
|||
A:\>notes This is a note. |
|||
A:\>notes This is another note. |
|||
A:\>notes |
|||
05/11/2020 07:52:34 PM |
|||
This is a note. |
|||
05/11/2020 07:52:38 PM |
|||
This is another note. |
|||
A:\>dir/b notes.* |
|||
NOTES.COM |
|||
NOTES.TXT |
|||
A:\></pre> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |