Some assembler code

Any off topic discussions should go in this forum. Post count is not increased by posting here.
FTP Access status is required to post in this forum. Find out how to get it
Forum rules
Any off topic discussions should go in this forum. Post count is not increased by posting here.
FTP Access status is required to post in this forum. Find out how to get it
Post Reply
Daniel
User avatar
Staff
Posts: 2607
Joined: Wed Apr 11, 2007 2:11 pm
Location: Germany, Earth
Contact:

Some assembler code

Post by Daniel »

Maybe someone here does know assembler. I want to know what this implies:

Code: Select all

void VideoInit()
{
    __asm {
        mov     ax, 1202h;
        mov     bx, 0301h;
        int     10h;

        mov     ax, 3h;
        mov     bx, 0h;
        int     10h;

        mov     ax, 1112h;
        mov     bx, 0h;
        int     10h;

        mov     ax, 1003h;
        mov     bx, 0h;
        int     10h;

        mov     ax, 0200h;
        mov     bx, 0h;
        mov     dx, 0h;
        int     10h;
    }
    Cls();
}

RentedMule
Donator
Posts: 937
Joined: Tue Oct 17, 2006 8:26 pm

Post by RentedMule »

Sure. It has been a while, so bare with me.

The first little block sets up the text mode to 400 scanlines. It is a little tricky to tell what it is doing because it is obfusicating the fact that it is putting 02H into the AH register, 12H into the AL register, 01H into the BH register and 03 into the BL register.

The second block is getting the cursor position and the size, on page 0.

The third block sets up the screen to 80x50 with a character width of 8.

The forth block sets up the video mode to VESA SVGA, version 2.

Daniel
User avatar
Staff
Posts: 2607
Joined: Wed Apr 11, 2007 2:11 pm
Location: Germany, Earth
Contact:

Post by Daniel »

Thank you

Kenneth
Donator
Posts: 2407
Joined: Sun May 13, 2007 12:42 am

Post by Kenneth »

Is this from Singularity?

Daniel
User avatar
Staff
Posts: 2607
Joined: Wed Apr 11, 2007 2:11 pm
Location: Germany, Earth
Contact:

Post by Daniel »

Windows OCManage wrote:Is this from Singularity?
Yes it is. There are also comments in the source which are saying the same, but I asked because I couldn't believe that this piece of code does what it does - I have tried to understand assembler but It's too hard

RentedMule
Donator
Posts: 937
Joined: Tue Oct 17, 2006 8:26 pm

Post by RentedMule »

Actually, it is quite easy. To access system services (like BIOS, VESA, SCSI, etc), you use an interrupt call. If you are familiar with programming (not making any assumptions either way), an interrupt would be akin to a function call. The parameters for those functions are put into the CPU registers, main ones (called the General Purpose Registers) being AX, BX, CX, and DX. Now, these are the original 16-bit registers originating from way back in the 8086. A reference to these original registers is at: http://ourworld.compuserve.com/homepage ... oc_cpu.htm

Each of the 16-bit general purpose registers can be split into two usable 8-bit registers. For instance, AX can be broken up into AH and AL, for A(high byte) and A(low byte).

Also, here is a reference to interrupt 10 (which is being used in the code snippet posted): http://en.wikipedia.org/wiki/INT_10

Basically, you set up the parameters (move a value into the registers), and call the interrupt. It is that easy.

One of the things that makes this bit of code tricky to a newcomer is the fact that two important values are being moved into, say, the AX register with one move statement... let me elaborate:

Lets take the first block of code:

Code: Select all

mov ax, 1202h;
mov bx, 0301h;
int  10h;
The first line is really moving 02h into AH and 12h into AL. This might seem backwards to you, because logic would tell you that 12 comes first, it should be going into the AH register. Actually, most processors now operate in what is called "little endian" mode. What this really means is that the bytes are stored backwards to how you normally read a number on paper. More details can be found here: http://en.wikipedia.org/wiki/Endianness#Little-endian

Ok, so anyway, 02h is being moved into AH and 12h is being moved into AL. Now take a look at the wikipedia page I linked to above and take a look at the third row in the table on that page, with the first column reading "Set cursor position".

You will notice, setting the cursor position involves moving 02h into AH, where whatever value is in BH is the page number. The second line takes care of this, by moving 01h into BH and 03h into BL. since BH is 01h, this means set cursor position to the first page.

Now with those three lines of code, there is already some problems with it. The first line moves 12h into AL, and the second line moves 03h into BL. Neither of these values do anything. They have no purpose, they will be ignored.

Also, you will notice in the documentation, that setting the cursor position also requires values in in DH to be the row the cursor gets moved to and DL is to be the column the cursor gets moved to. Neither of these are set, so essentially, even if the cursor makes it back to page 1 (if the values in DL and DL are invalid, the call to int 10 will fail), it will be in a completely random place. Now, there could be code before VideoInit to initialize the registers to sane values, but there is no way to know from this function, so it is bad practice to assume so.

The first block SHOULD be rewritten to:

Code: Select all

mov ah, 02h;
mov bh, 01h;
mov dx, 0101h;
int  10h;
The rest of the code is just as sloppy. Even the function VideoInit is declared void, so there is no way to return a value to let the caller know that it failed. So more or less, if for whatever reason this function blows up (maybe you are trying to run on a machine without VESA 2.0 support), the whole system crashes, where a better solution would be to try and fall back to some other video mode, or even output to the serial port.

Post Reply