Showing posts with label interrupt. Show all posts
Showing posts with label interrupt. Show all posts

Wednesday, January 15, 2014

How to set video mode in X86 assembly?


The interrupt no. 10H is dedicated for all kinds on video operation of 8086/8088 DOS system. The function number 01 with interrupt 10H is used to set the video mode.
The mode values must be set in AL register.


The values 00h to 03H specifies the text modes of DOS. Remaining are Graphics modes. The default text mode is 80 X 25. That is, 80 character per line X 25 line per screen page.
So, this text resolution can be changed with the help of interrupt no. 10H.

By setting any video mode, the display screen will be cleared automatically.

For e.g.

    MOV AH,00H
  MOV AL,00H
  INT 10H

This will set the video mode (text) of 40 characters per line X 25 line per page. It changes the default resolution. Likewise, we may use different kind of values in AL register.

These are:

00H – 40 X 25 (text) color burst OFF
01H – 40 X 25 (text)
02H – 80 X 25 (text) color burst OFF
03H – 80 X 25
04H – 320 X 200 pixels (graphics)
05H – 320 X 200 pixels (graphics) color burst OFF
06H – 640 X 200 (graphics)
... and so on.

To Know more about these values, refer book “Advanced MS-DOS Programming” by Ray Duncan (BPB Publications).

Sunday, January 12, 2014

Printing a String using x86 assembly under MASM/TASM


String is an array of character, where all character are stored in contiguous fashion. In computer's view, string is an array of bytes stored in contiguous memory. Here, I have used term 'byte' because computer does not recognize integer and character separately. It knows only bytes. 

 
To print a string, we need an array of bytes or character stored in a memory with a 'end of string' character. Let's see how it is done.
Generally,the array are stored in a data segment.For example, 
 
    .data
             char db 'a','b','c','d','$'

Here, 'char' is the name of array variable. These characters will get stored in contiguous memory locations with values 'abcd'. The '$' is end of string character. It recognizes that there are no more characters after it. It is compulsory to have '$' as the end of string characters for all strings. As I already told, computer only knows bytes, following declaration of string is also similar to previous one.

    .data
    char db 41,42,43,44,'$'

Here, 41, 42, 43 & 44 are ASCII values of 'abcd' respectively. In order to print a string on screen x86 architecture uses DOS interrupt number 21H with function number 09H. So,

    INT 21H & AH=09H

will do the task for us.
Before this, we must store offset address/effective address of the string in data register (DX). Address of string or address of first character of string must be stored in DX register, function 09H gets this address from DX and print the characters on the screen from first byte till '$'.
Following code will print 'welcome' on screen.

.DATA
      MESSAGE DB 'WELCOME$'

.CODE
     MOV DX, @DATA
     MOV DS, AX
     LEA DX, MESSAGE
     MOV AH, 09H
     INT 21H

  MOV AH, 4CH
  INT 21H
END

The instruction 'LEA' loads the offset of effective address of variable 'MESSAGE' in DX register. Remember, it is mandatory to have '$' at the end!
You may try by removing '$' from the string.

Monday, January 6, 2014

Print a number using Assembly Language


Let's see something simple but interesting stuff in assembly language. To print a value on screen, various high level programming languages use there library function and statement. For example, C uses 'printf', C++ uses 'cout', Java uses 'println' and Python uses 'print'. It is single line statements that does our task. But, microprocessor implements several sequential steps to print a number on screen. 
 

Here, I have used the widely used MASM to demonstrate this work. Basically, to print a number microprocessor don't have any function for this. It is only possible to print a single character with function number 02 an interrupt number 21h. The character that you have to print, must be present in DL register.
For example,

MOV DL,'a'
MOV AH,02H
INT 21H

This code will print 'a' on the screen (without quote!). Here DL register of processor is storing ASCII value of character 'a'. So, following code will also do the same task, as ASCII value of character 'a' is 41 in hexadecimal.
 
MOV DL,41H
MOV AH,02H
INT 21H

Here, 02 is function number and it is necessary to store it in AH register before invoking an interrupt. Now, to print number on screen it is not directly possible using assembly language. We need to do it using ASCII values of hexadecimal digit. Remember ASCII values of 0 to 9 are 30 to 39 respectively. So, if you want to print 5 on screen, we need to store 35 in DL register before invoking the interrupt. Now, following code will print 5 on screen.
 
MOV DL,35H
MOV AH,02H
INT 21H

It means that, we need code conversion by adding 30 in hex to the respective single digit number. If you want to print 2 digit number the same procedure can be followed for both digit by rotating. Then one after the another following algorithm will do the task for us.
  1. Get a two digit number in temporary register say BH.
  2. Rotate the bits of the number by 4 position so hex digit would be swapped.
  3. Copy the rotated number in DL register.
  4. Mask high order 4 bits to zero.
  5. Add 30h in DL.
  6. Use function 02h and int 21h to print the number.
  7. Repeat the steps 2 to 6 for second digit also.
Code:
  1. MOV BH,96H ;number to print
  2. MOV CH,02H ;number of digits
  3. MOV CL,04H ;rotation count
  4. UP:ROL BH,CL ;swap digits
  5. MOV DL,BH
  6. AND DL,0FH ;mask MSB digit
  7. ADD DL,30H ;add 30 in DL
  8. MOV AH,02H ;function number
  9. INT 21H
  10. DEC CH ;do twice
  11. JNZ UP
Here, we simulate the code stepwise.
  1. BH=96H
  2. CH=02H
  3. CL=04H
  4. BH=69H
  5. DL=69H
  6. DL=09H
  7. DL=39H
  8. AH=02H
  9. It will print DL=39 i.e 9 on screen.
  10. CH=01H
  11. Condition true as ZF=0. Jump to 4th Statement.
  1. BH=96H
  2. DL=96H
  3. DL=06H
  4. DL=36H
  5. AH=02H
  6. It will print DL=36 i.e 6 on screen.
  7. CH=00H
  8. Condition false so terminate.
Now, here we have printed the hex digits only between 0-9. But, if digits are between A-F then we need to check this condition also. The ASCII value of numbers and characters have difference of 07H. So, if the hex digit of number is greater than 9 then to have to add 07H also in DL register. The following code will do the task.
 
MOV BH,5CH ;number to print
MOV CH,02H
MOV CL,04H
UP:
ROL BH,CL
MOV DL,BH
AND DL,0FH
CMP DL,09H
JBE NEXT
ADD DL,07H
NEXT:
ADD DL,30H
MOV AH,02H
INT 21H
DEC CH
JNZ UP

You may use debugger to check the execution of the code. It is to be noted that this code will work in x86 architecture using MASM or TASM.