; ; CPASM04S.ASM ; written by Keith Fenske ; Sunday, 10 March 2002 ; Copyright (c) 2002 by Keith Fenske. All rights reserved. ; ; This is an Intel 80x86 assembly language program to read a line of input ; from the user (keyboard), and then to print the same line three different ; ways: ; ; (1) left aligned with fill characters on the right ; (2) center aligned with fill characters on the left and the right ; (3) right aligned with fill characters on the left ; ; The chosen fill character is "*". The assumed line length is 72 bytes, ; to keep it smaller than the regular MS-DOS screen width of 80 characters, ; and thereby avoid any wraparound effects. Input is read in a loop, until ; the input is empty: no characters, only the Enter key. ; ; This program would be an obvious place to start using subroutines, because ; all three alignments need exactly the same code for writing their output. ; ; This program uses underscore (_) characters to break up the words in long ; labels and variable names. ; ; To do this assignment properly, you must read the INT 21H documentation for ; DOS function code AH=0Ah (buffered input). ; [BITS 16] ; set 16-bit code generation [ORG 0100H] ; set address of first instruction in COM file CR equ 0Dh ; carriage return character FILLCHAR equ '*' ; fill character for alignment LF equ 0Ah ; line feed character MARKER equ '|' ; marker character for left and right sides MAXINPUT equ 72 ; maximum number of bytes to read from user [SECTION .text] ; start code (instruction) section start: ; ; Put a marker on the left and right sides of the output buffer to show: ; ; (1) that the alignment routines are using the whole buffer ; (2) but not going over the ends of the buffer. ; mov [output_left],byte MARKER ; marker for left side mov [output_right],byte MARKER ; marker for right side ; ; Prompt the user and then read a line of input. Quit this program if the ; input line is null (empty = zero bytes of input). ; get_input: mov bx,1 ; DOS file handle 1 is standard output mov cx,prompt_size ; length of string in bytes mov dx,prompt ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; mov [input],byte MAXINPUT+1 ; maximum number of bytes to read, including the ; CR (or new line) character mov [input+1],byte 0 ; clear number of bytes read mov dx,input ; address of input buffer (two sizes + text) mov ah,0Ah ; DOS function code for buffered input int 21h ; call DOS ; cmp [input+1],byte 0 ; was there any input? jle near done ; no, quit ; ; To print the input string left aligned with fill characters on the right, ; first copy the input string to the output buffer. ; mov cl,byte [input+1] ; how many bytes to copy mov ch,0 ; clear high-order byte of CX register mov si,input+2 ; source: where to copy from mov di,output_text ; destination: where to copy to left_copy: mov al,[si] ; get source byte mov [di],al ; put in destination inc si ; address of next source byte inc di ; address of next destination byte loop left_copy ; repeat until we copy all of source ; ; Now fill the remainder of the output buffer with the fill character. ; The DX register points to the next byte in the output buffer. ; mov cl,MAXINPUT ; compute fill count as maximum input size ... sub cl,byte [input+1] ; ... minus the actual input size jle left_print ; nothing to do if input is maximum size mov ch,0 ; clear high-order byte of CX register left_fill: mov [di],byte FILLCHAR ; put in one fill character inc di ; address of next destination byte loop left_fill ; repeat until we fill right side ; ; Print the left aligned text in three parts: a string to explain, the ; created output buffer, and the new line characters. ; left_print: mov bx,1 ; DOS file handle 1 is standard output mov cx,left_size ; length of string in bytes mov dx,left ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; mov bx,1 ; DOS file handle 1 is standard output mov cx,output_size ; length of string in bytes mov dx,output ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; mov bx,1 ; DOS file handle 1 is standard output mov cx,newline_size ; length of string in bytes mov dx,newline ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; ; Print the same input string center aligned with fill characters on the ; left and right. The copy operation is similar to the left aligned text ; above. The fill operations are split into a left and right side. If ; the number of fill bytes is odd, then the left side will have one less ; fill byte than the right side. ; ; As mentioned in the comments at the beginning of this program, all three ; alignments do many similar operations, and using subroutines would be a ; good idea. ; mov di,output_text ; destination: where to copy to ; mov cl,MAXINPUT ; compute left fill count as maximum input size ... sub cl,byte [input+1] ; ... minus the actual input size ... shr cl,1 ; ... divided by two jle center_fill_1_done ; nothing to do if input is maximum size mov ch,0 ; clear high-order byte of CX register center_fill_1: mov [di],byte FILLCHAR ; put in one fill character inc di ; address of next destination byte loop center_fill_1 ; repeat until we fill left side center_fill_1_done: ; mov cl,byte [input+1] ; how many bytes to copy mov ch,0 ; clear high-order byte of CX register mov si,input+2 ; source: where to copy from center_copy: mov al,[si] ; get source byte mov [di],al ; put in destination inc si ; address of next source byte inc di ; address of next destination byte loop center_copy ; repeat until we copy all of source ; mov cl,MAXINPUT ; compute right fill count as maximum input size ... sub cl,byte [input+1] ; ... minus the actual input size ... inc cl ; ... plus one (in case total fill size is odd) ... shr cl,1 ; ... divided by two jle center_fill_2_done ; nothing to do if input is maximum size mov ch,0 ; clear high-order byte of CX register center_fill_2: mov [di],byte FILLCHAR ; put in one fill character inc di ; address of next destination byte loop center_fill_2 ; repeat until we fill right side center_fill_2_done: ; mov bx,1 ; DOS file handle 1 is standard output mov cx,center_size ; length of string in bytes mov dx,center ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; mov bx,1 ; DOS file handle 1 is standard output mov cx,output_size ; length of string in bytes mov dx,output ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; mov bx,1 ; DOS file handle 1 is standard output mov cx,newline_size ; length of string in bytes mov dx,newline ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; ; Print the same input string right aligned with fill characters on the ; left. Most of the code from the left alignment is repeated here in a ; different order, so subroutines would have been a better idea. ; mov di,output_text ; destination: where to copy to ; mov cl,MAXINPUT ; compute fill count as maximum input size ... sub cl,byte [input+1] ; ... minus the actual input size jle right_fill_done ; nothing to do if input is maximum size mov ch,0 ; clear high-order byte of CX register right_fill: mov [di],byte FILLCHAR ; put in one fill character inc di ; address of next destination byte loop right_fill ; repeat until we fill left side right_fill_done: ; mov cl,byte [input+1] ; how many bytes to copy mov ch,0 ; clear high-order byte of CX register mov si,input+2 ; source: where to copy from right_copy: mov al,[si] ; get source byte mov [di],al ; put in destination inc si ; address of next source byte inc di ; address of next destination byte loop right_copy ; repeat until we copy all of source ; mov bx,1 ; DOS file handle 1 is standard output mov cx,right_size ; length of string in bytes mov dx,right ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; mov bx,1 ; DOS file handle 1 is standard output mov cx,output_size ; length of string in bytes mov dx,output ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; mov bx,1 ; DOS file handle 1 is standard output mov cx,newline_size ; length of string in bytes mov dx,newline ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; ; Now go get the next line of input from the user. ; jmp get_input ; repeat until input is null (empty) ; ; The user gave us an empty input line, so exit from this program after ; printing a goodbye message. ; done: mov bx,1 ; DOS file handle 1 is standard output mov cx,goodbye_size ; length of string in bytes mov dx,goodbye ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS ; mov ah,4Ch ; DOS function code to exit program mov al,0 ; pass this value back as ERRORLEVEL int 21h ; call DOS (does not return) [SECTION .data] ; start initalized data section ; ; The following data section contains only those data regions that have ; initial values. ; center db "Center aligned text with left/right fill:", CR, LF center_size equ $ - center goodbye db CR, LF, "Thank you for typing to me!", CR, LF goodbye_size equ $ - goodbye ; length of goodbye string in bytes left db CR, LF, "Left aligned text with right fill:", CR, LF left_size equ $ - left newline db CR, LF newline_size equ $ - newline prompt db CR, LF, "Please type a line of text,", CR, LF db "or an empty line (Enter key only) to quit:", CR, LF prompt_size equ $ - prompt ; length of prompt string in bytes right db "Right aligned text with left fill:", CR, LF right_size equ $ - right [SECTION .bss] ; start uninitialized data section ; ; The following data sections contains buffers (etc) that do not have ; initial values. The data must be created while the program is running. ; ; Note that the following three lines must be kept together to make a valid ; description of a DOS input buffer. ; input resb 1 ; maximum number of bytes to read from user resb 1 ; gets set to actual bytes read resb MAXINPUT+1 ; where to put bytes from user, plus CR output: ; output buffer has several parts output_left resb 1 ; first byte is a marker for the left side output_text resb MAXINPUT ; buffer for aligned output text output_right resb 1 ; last byte is a marker for the right side output_size equ $ - output ; length of output string in bytes ; ; End of CPASM04S.ASM ;