We begin with this simple example. We want to clear the screen in text mode and we will use a direct acces to the screen. The screen begins at B800:0000h and has 80 columns and 25 rows (in basic text mode) each cell two bytes long. The first byte is the ASCII code of the character, the second is the character's color.
MOV AX,0B800H ;a hexadecimal number has to begin with a cipher so this won't be confound with a name of a label, so that's why we have to write it as 0B800h and not B800h
MOV ES,AX ;segment register ES can be filled with a number only using AX register
MOV AX,7*256+' ' ;using color 7 (white) "clear" the screen with spaces
The next example will print a fixed chosen number in a fixed chosen number system (in range from 2 - binary - to 16 - hexadecimal). We'll use a DOS function for printing the number.
MOV AX,12345 ;chosen number in range from 0 to 65535
MOV BL,16 ;the basis of chosen number system in range from 2 to 16
MOV DI,16 ;we will print the number from the end - beginning with the lowest cipher
DEC DI ;next cipher
XOR DX,DX ;DX<-0
DIV BX ;next cipher into DX
MOV DL,[SI+ciphers] ;find out the right character for this cipher...
MOV [DI+prnt],DL ;...and print it
JNZ next ;continue until AX=0, i.e. until all ciphers are printed
MOV DX,text ;address of first text into DX
MOV AH,09h ;service number...
INT 21h ;...used for text output
ADD DX,DI ;we will print the number beginning with the first - most valuable (significant) cipher, so the very last printed cipher
[SECTION .data] ;this way is variable section defined
ciphers DB '0123456789ABCDEF' ;list of cipher characters
text DB 'Number = $' ;output text ending with $
prnt TIMES 16 DB 0
DB '$' ;maximum sixteen ciphers output number - using directive TIMES we can define a field of equal items much easier
This program works with number from the input (from keyboard, in NASMIDE environmnet you have to enter the input using menu item parameters), in a word-range (from 0 to 65535). It is looking for the result using try-fail method. It tries to set particular bits of the searched result (beginning with the most significant) and then it computes a square of this number. If that square is greater than input number, the bit set has to be cleared.
MOV CX,7 ;...because two of them will mean ending of the input - pressing the ENTER key (0Dh, 0Ah),...
MOV BX,0 ;...and write them into memory beginning at the "input" label
SUB AX,2 ;in AX is the input characters count but we have to subtract two to get rid of the ENTER
JZ exit ;exit if there is no input
MOV CX,AX ;characters count into CX
MOV BX,10 ;we will convert decimal input into AX register
XOR DH,DH ;clear AX and DH
MUL BX ;multiply the timely result with ten
MOV DL,[DI] ;read the next character
SUB DL,'0' ;change the ASCII character into a number from 0 to 9
INC DI ;get the pointer on the next character
JC exit ;if the number isn't in range from 0 to 9, exit
ADD AX,DX ;add the timely result and the new cipher
LOOP mk_test ;i.e. SUB CX,1 and JNZ mk_test - a simple loop
INT 21h ;wrong input - exit
MOV CX,AX ;number we want to calculate square root from into CX register
MOV BL,10000000b ;beginning with the most significant bit
XOR BH,BH ;BH<-0
ADD BH,BL ;try to add the examined bit
MUL AL ;calculate a square from the searched result...
CMP CX,AX ;...and compare it with the input number
SUB BH,BL ;that was too much, subtract the bit
MOV AL,BL ;if everything is O.K. ...
MOV BL,AL ;move BL onto the next bit - divide it with two and it will rotate right
JNZ search ;if we haven't tried all bits, continue
SUB CX,AX ;calculate a square from the result and get the remainder
next1: ;print AX register - the result - using procedure like in printing numbers
next2: ;print CX register - remainder - likewise
input TIMES 7 DB 0 ;place for input from keyboard
ciphers DB '0123456789' ;characters and texts to print like in program printing numbers
text1 DB 'Square root = $'
output1 TIMES 3 DB 0
text2 DB ', remainder = $'
output2 TIMES 3 DB 0
The last program is something like a screensaver. It prints fourty "smiley" characters (character 01h ASCII) and moves them in various directions. If a smiley "falls out" the screen a new character is generated.
MOV AX,7*256+' '
MOV SI,39*2 ;we will print from a two-byte table beginning from the 39th character to the zero character - together 40 characters
JZ cycle ;find out if a key was pressed and when it was so, exit
XOR AH,AH ;but also get it out of the buffer
MOV CX,[SI+pos] ;find out if the particular character is valid (after launching the program none is valid)
JNZ output ;if it's O.K. print it, if not continue and generate a new one
CALL random ;random number into DX register, it calls procedure named "random", after returning it continues with the next instruction
MOV CX,DX ;and now we try to extract from the content of the DX register the direction of the new character (without using the most significant - unused bit the three most significant bits of the higher byte), its row (lower four bits of the higher byte), color (two most significant bits in the lower byte) and column (other six bits of the lower byte)
AND CX,0000111100111111b ;mask for the y and x coordinate of the character...
ADD CX,5*256+9 ;...which were generated in range from 0 to 15 (adding 5 changed to range from 5 to 20) and in range from 0 to 63 (adding 9 changed to range from 9 to 72)
MOV [SI+pos],CX ;store new coordinates into table
AND DX,0111000011000000b ;mask for the direction and color of the generated character
MOV [SI+info],DX ;store new informations into table
MOV DL,160 ;print the character, in CX remained its coordinates
SUB CX,0101h ;a correction from ranges 1..80 and 1..25 into ranges 0..79 a 0..24
ADD CL,CL ;multiply the x coordinate with two - one character takes in the screen memory two bytes
MUL DL ;and multiply the y coordinate with 80*2 because of the same reason
MOV DI,AX ;address of the character on the screen into DI
MOV BX,[SI+info] ;find out the direction and color of the character
DIV BL ;the color is recorded in the two most significant bits of the lower byte - we have to move it to the lowest position in a byte...
ADD AL,00001100b ;...and add 12 so we get a light color - we get then light red, light magenta, yellow and white
MOV AL,1 ;character 01h - a smiley
STOSW ;and print it
MOV BL,00100000b/2 ;so move the direction but only to the second lowest bit - we use a two-bytes table
MOV CX,[SI+pos] ;timely character position into CX register
ADD CX,[DI+tab] ;and add it with the "speed" according to the table
OR CH,CH ;we have to find out if the character fell out the screen
XOR CX,CX ;it fell out - delete it
MOV [SI+pos],CX ;store new position of the character
SUB SI,2 ;go to the next character
XOR AX,AX ;all characters printed - now we have to include a waiting loop so the characters don't flash before our eyes...
MOV ES,AX ;...without this it wouldn't be possible to recognize those characters on today's computers
JZ wait ;we'll wait for a change of the timer which is changed every 55 milliseconds, i.e. 18.2 times per second
JMP begin ;and again to the beginning
random: ;procedure for generating a random number
MOV BX,0 ;last generated number
MOV DH,BL ;I don't know how this works, it's transcribed from book "Assembler and ZX Spectrum 2" and its authors transcribed it from another program...
MOV DL,253 ;but it reliably generates each number in range from 0 to 65535
MOV [random+1],DX ;store the new random number...
RET ;...and return from the procedure
tab DW 0FFFFh,0FF00h,0FF01h,00001h,00101h,00100h,001FFh,000FFh ;a table of "speeds" according to the direction, beginning with the up-left direction clockwise, the higher byte is the "speed" in y coordinate, the lower byte is the "speed" in x, using numbers -1 (=0FFh=255), i.e.. up/left, 0 and 1, i.e. down/right
pos TIMES 40 DW 0 ;position of the characters before launching - everything is equal to zero so all characters are generated anew
info TIMES 40 DW 0 ;characters' informations - direction and color