## Pascal

Moderators: None (Apply to moderate this forum)
Number of threads: 4106
Number of posts: 14016

This Forum Only

Inline Assembler :/ Posted by Starburn on 4 Oct 2002 at 2:20 AM
At a push.. can any one help me out with this:

```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;
```

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:

```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;
```

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

Thanks,
-Matt.
Putting and getting text charactes. Posted by slicer69 on 4 Oct 2002 at 4:33 AM
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;

Re: Putting and getting text charactes. Posted by Starburn on 4 Oct 2002 at 5:33 AM
This message was edited by Starburn at 2002-10-4 5:37:27

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.

Re: Putting and getting text charactes. Posted by iby on 5 Oct 2002 at 6:43 AM
: This message was edited by Starburn at 2002-10-4 5:37:27

: 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

```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.
```

Iby
Re: Putting and getting text charactes. Posted by Starburn on 8 Oct 2002 at 4:59 AM
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[<var>] or would it be better to directly reference the consecutive memory locations?

Thanks in advance.
Re: Putting and getting text charactes. Posted by iby on 8 Oct 2002 at 9:06 AM
: 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[<var>] 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
``` GOTOXY(x,y);
WRITELN(Text);
```

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

Re: Putting and getting text charactes. Posted by Starburn on 8 Oct 2002 at 10:30 AM
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.

## Recent Jobs

Official Programmer's Heaven Blogs
Web Hosting | Browser and Social Games | Gadgets

Popular resources on Programmersheaven.com
Assembly | Basic | C | C# | C++ | Delphi | Flash | Java | JavaScript | Pascal | Perl | PHP | Python | Ruby | Visual Basic
© Copyright 2011 Programmersheaven.com - All rights reserved.
Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
Operated by CommunityHeaven, a BootstrapLabs company.