Inline Assembler :/

At a push.. can any one help me out with this:

[code]
procedure WriteXY(X, Y : byte; AChar : char); assembler;
{Extra code is needed for X and Y to be variables of type byte}
asm
xor bx, bx {Clear BX}
xor cx, cx {Clear CX}
mov bl, X {Move X into last 8 bits of bx}
mov cl, Y {Move Y into Counter (last 8 bits)}
dec cl {Take 1 from Counter}
@loop1: {(because of dec cx) "For I := 1 to (Y - 1)"}
add bx, 80 {Inc bx by 80 (Inc(Offset,80))}
loop @loop1 {End loop}
dec bx {(This and next line) Offset := (Offset - 1) * 2}
add bx, bx {Multiply bx by 2}
push es {Preserve segment reg.}
(*push ss {Preserve}
push di { "" }
mov dx, offset AChar {Move the offset of AChar into dx}
mov di, dx {dx -=> di}
mov dx, seg AChar {Move the memory segment address of AChar into dx}
mov ss, dx {dx -=> ss}
mov dl, ss:[di] {Move the contents of Mem[ss:di] into dl}
pop di {Pop back}
pop ss {Pop back} *)
mov ax, $B800 {Move Screen mem segement into ax}
mov es, ax {ax into es}
mov di, bx
mov es:[di],dl {Move Char 01 into $B800:Offset}
pop es {Pop es back from top of stack}
end;
[/code]

The part commented out with (* *) is what im having trouble with...
I did this small example.. to try and figure out how to manipulate the char... and it doesnt work either:

[code]
procedure GetChar;

var T1, T2 : word;
TheChar : char;

begin
TheChar := #1;
asm
mov ax, seg TheChar
mov T1, ax
mov ax, offset TheChar
mov T2, ax
end;
{T1 := Seg(TheChar);
T2 := Ofs(TheChar);}
Write(Mem[T1:T2])
end;
[/code]

If the commented out code is used instead of the assembler, it does work..
What am I doing wrong? :/

Thanks,
-Matt.

Comments

  • If all you are doing is getting and putting charactes to the text screen, try this:

    procedure putchar(x, y: byte; c: char); assembler;
    asm
    push ES
    mov AX, 0b800h
    mov ES, AX
    xor AX, AX
    mov AL, y
    xor BX, BX
    mov bl, 160
    mul bl { ax = y offset }
    xor bx, bx
    mov bl, x
    add ax, bl
    add ax, bl { ax = offset to place char
    mov di, ax { es:di points to screen position }
    mov al, c { load character into ax }
    stosb { write char to screen }
    pop es
    end;



  • [b][red]This message was edited by Starburn at 2002-10-4 5:37:27[/red][/b][hr]
    Ahh, but ... an 8bit register cannot be added to a 16 bit one...
    (pascals inline assembler will give a compile error),
    And also, I was using a char as a test, I needed the memory location so when I change it to a string/array of chars, they will be easy to access as they will be in consectutive memory locations.. unless theres another way to do it easier, with a string.


    :(

    Also, why 160 into bl? Is this for 80x25 screen mode? And one more question .. why 0b800h ? does the h represent hexidecimal?.. and so whats the 0 for?

    Thanks.



  • : [b][red]This message was edited by Starburn at 2002-10-4 5:37:27[/red][/b][hr]
    : Ahh, but ... an 8bit register cannot be added to a 16 bit one...
    : (pascals inline assembler will give a compile error),
    : And also, I was using a char as a test, I needed the memory location so when I change it to a string/array of chars, they will be easy to access as they will be in consectutive memory locations.. unless theres another way to do it easier, with a string.
    :
    :
    : :(
    :
    : Also, why 160 into bl? Is this for 80x25 screen mode? And one more question .. why 0b800h ? does the h represent hexidecimal?.. and so whats the 0 for?
    :
    : Thanks.
    :
    :
    :
    :

    You are right, you cannot add 8 and 16 bit registers, but
    you can 16 and 16 bit as long as you clear upper half of
    the one with 8-bit value.

    Number 160 had to do with the way text screen is organized.
    there are 80x25 characters displayed, however one line is
    not 80 but 160 byte long because of attrib characters ("colors"):

    LINE0: attrib0,char0, attrib1, char1, ... , attrib79, char79,
    LINE1: attrib80,char80, attrib81,char81, ... , attrib159,char159,
    LINE2: attrib160,char160, etc.

    So here is working code

    [code]
    procedure putchar(x,y:byte; c:char); assembler;
    asm
    push es { save ES on stack }

    mov AX, 0b800h
    mov ES, AX { point ES to text screen }

    xor AX, AX
    mov AL, y { AX = y }

    xor BX, BX
    mov bl, 80
    mul bl { AX = y*80 }

    xor bx, bx
    mov bl, x
    add ax, bx { AX = y*80+x }

    add ax, ax { AX = (y*80+x)*2 }
    mov di, ax { ES:DI points to screen position }
    mov al, c { load character into AX }
    stosb { write one char to screen }
    pop es { restore original ES from stack }
    end;


    begin
    asm mov ax,3; int 16 end;
    putchar ( 0,0,'A');
    putchar ( 10,10,'B');
    putchar ( 40,12,'C');
    readln;
    end.
    [/code]

    Iby
  • Ah. Thanks Iby.

    asm mov ax,3; int 16 end; = I assume this is clear screen? Moving 3 into the accumulator register, and the interupt 16 is called?


    So... moving on from the place character code, if in place of a char it was a string, how could this be handled? Would the absolute of the string return its length? and therefore a loop could be used?
    i.e. string[] or would it be better to directly reference the consecutive memory locations?

    Thanks in advance.
  • : Ah. Thanks Iby.
    :
    : asm mov ax,3; int 16 end; = I assume this is clear screen? Moving 3 into the accumulator register, and the interupt 16 is called?
    :

    Correct. This sets text mode 03h and interrupt 16 is video interrupt
    10h ($10 in pascal). After mode is set, screen is cleared.


    : So... moving on from the place character code, if in place of a char it was a string, how could this be handled? Would the absolute of the string return its length? and therefore a loop could be used?
    : i.e. string[] or would it be better to directly reference the consecutive memory locations?
    :
    : Thanks in advance.
    :


    Just write to every other location or make a better version
    of the previous procedure by adding attribute parameters.
    Then in code make sure that attribute is loaded in one half
    of the AX, while character is in other. This way you can
    write both caracter and attributes in one shot but the write
    has to be 16bit of course. To perform 16bit write (instead
    of 8bit), replace STOSB (byte) with STOSW (word).
    Now this whole thing can be done in a loop for the string.
    String length is the first byte of the string while string
    content follows. Since direct writing to video memory
    doesn't involve interrupts, it is much faster than
    [code]
    GOTOXY(x,y);
    WRITELN(Text);
    [/code]

    Last time I was checking performance differnce (ca. 10 years ago)
    the PASM version was about 500 times faster than pascal code above.


    Hope this helps,


    Iby


  • Yes thank you :) I never thought of writing the attrib + char at once...

    I will whip up some code when I have some time (got analysis deadline for computing in 3days, so im busy atm :). and post it up here, so you can have a look, see what u think.

    Thanks for all your help, its much appreciated.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories