flat assembler
Message board for the users of flat assembler.

Index > DOS > I Have A Problem With A Simple .COM That Displays Text

Author
Thread Post new topic Reply to topic
Gambino



Joined: 20 Jul 2003
Posts: 44
Location: Romania
Gambino 07 Jul 2004, 18:34
Code:
ORG 100H

TX = 80
TY = 25

struc dstr data
{
 common
 .data db data
 .size = $-.data
}

virtual at 0
   write:
        .x        dw   ?
        .y        dw   ?
        .back   db   ?
        .fore    db   ?
;       .str      dstr   ?
; how can i implement something like this ?
; i know i can't do it this way
; tell me the right way plz
        .size = $
end virtual

push cs
pop ds

mov ax,03h
int 10h

mov [write.x], 10
mov [write.y], 10
mov [write.back], 1
mov [write.fore], 3
; i would like to pass here the string..
; something like mov[write.str], 'Test Message'
; or something like that.... ( I Know I Can't Do It This Way ! )
; plz tell me

call WriteStr

xor ax,ax
int 16h

int 20h

WriteStr:
        push  $B800
 pop   es

               mov   ax, x.data 
;              mov   ax, [write.str.data]
; i need
;  something that can be called globaly

    mov   si, ax

    mov   ax, [write.y]    ; (Y*TX-(TX-X))*2 ;((Y-1)*TX+X)*2
    mov   bx, TX
        mul   bx
    sub   bx, [write.x]
 sub   ax, bx
        mov   cx, 2
 mul   cx
    mov   di, ax

    mov   ah, [write.back]
      mov   al, [write.fore]
      shl   ah, 4
 or    ah, al
         
                mov   cx, x.size        
;              mov cx. [write.str.size]
; i need
; something that can be called globaly

      Continue:
   mov   al, byte [si]
 stosw
       inc si
      loopnz Continue
     ret

x dstr 'Test Message !'
    


The problem is that i want to pass the string that will be written on the screen like the others ( write.x ,write.y etc) and i can't do it
Can anyone plz help me ?

If do not understand what i'm trying to do plz tell me, and i will try to explain more , even if my english is a little bad..

( I Think This Is Brilliant Code Wink Made By Me, But I Got Stucked....
You Don't Need To Terminate Your String With Anything Very Happy
ex: msg db 'blah blah',0
You Can Give The Coordonates and Select background and foreground color Wink, It's like write('blah') and gotoxy(10,10) and TextColor etc From Pascal ALL IN ONE Cool
Post 07 Jul 2004, 18:34
View user's profile Send private message Reply with quote
crc



Joined: 21 Jun 2003
Posts: 637
Location: Penndel, PA [USA]
crc 07 Jul 2004, 22:23
I'd just use a macro to set up the string and pass arguments to the WriteStr routine. It'd be something like:

Code:
ORG 100H

TX = 80
TY = 25

virtual at 0
   write:
        .x        dw   ?
        .y        dw   ?
        .back   db   ?
        .fore    db   ?
        .size = $
end virtual

macro write_string data, x, y, bgcolor, fgcolor {
   local a, b, size
   mov [write.x], x
   mov [write.y], x
   mov [write.back], bgcolor
   mov [write.fore], fgcolor
   mov ax, a
   mov cx, [size]
   jmp b
   label a
   db data
   label size
   dw $-a
   label b
   call WriteStr
}

push cs
pop ds

mov ax,03h
int 10h

write_string 'This  is a test', 10, 10, 1, 3

xor ax,ax
int 16h

int 20h

WriteStr:
        push  $B800
        pop   es
        push  cx

        mov   si, ax

        mov   ax, [write.y]    ; (Y*TX-(TX-X))*2 ;((Y-1)*TX+X)*2
        mov   bx, TX
        mul   bx
        sub   bx, [write.x]
        sub   ax, bx
        mov   cx, 2
        mul   cx
        mov   di, ax

        mov   ah, [write.back]
        mov   al, [write.fore]
        shl   ah, 4
        or    ah, al
        pop   cx

      Continue:
        mov   al, byte [si]
        stosw
        inc si
        loopnz Continue
        ret
    


This could be modified a bit; I'll see if I can come up with something more like your example later tonight or tomorrow morning.
Post 07 Jul 2004, 22:23
View user's profile Send private message Visit poster's website Reply with quote
crc



Joined: 21 Jun 2003
Posts: 637
Location: Penndel, PA [USA]
crc 07 Jul 2004, 22:50
Ok, how about this:

Code:
ORG 100H

TX = 80
TY = 25

virtual at 0
   write:
        .x        dw   ?
        .y        dw   ?
        .back   db   ?
        .fore    db   ?
        .size = $
end virtual

macro mov a, b {
   local c, d, e
     if b eqtype ''
      jmp e
      label c
      db b
      label d
      dw $-c
      label e
        mov ax, c
        mov cx, [d]
     else
      move a, b
    end if
}

move fix mov

push cs
pop ds

mov ax,03h
int 10h

   mov [write.x], 10
   mov [write.y], 10
   mov [write.back], 1
   mov [write.fore], 3
   mov [write.str], 'this is a test'
   call WriteStr

xor ax,ax
int 16h

int 20h

WriteStr:
        push  $B800
        pop   es
        push  cx

        mov   si, ax

        mov   ax, [write.y]    ; (Y*TX-(TX-X))*2 ;((Y-1)*TX+X)*2
        mov   bx, TX
        mul   bx
        sub   bx, [write.x]
        sub   ax, bx
        mov   cx, 2
        mul   cx
        mov   di, ax

        mov   ah, [write.back]
        mov   al, [write.fore]
        shl   ah, 4
        or    ah, al
        pop   cx

      Continue:
        mov   al, byte [si]
        stosw
        inc si
        loopnz Continue
        ret    
    


This redefines mov to create a string, jump over it, and set ax=address, cx=length. If you use mov normally, nothing will change, so your code should work ok. (Note that I added a push cx, pop cx pair to the WriteStr routine as well)

_________________
Charles Childers, Programmer
Post 07 Jul 2004, 22:50
View user's profile Send private message Visit poster's website Reply with quote
Gambino



Joined: 20 Jul 2003
Posts: 44
Location: Romania
Gambino 09 Jul 2004, 04:28
Hey crc u got an A+ from me... Very Happy
Both variants are good, but i like the second write_string thingie Laughing
You took it one step farther ! Can u tell me if i can optimise the code even more ?

Thanx Man You're Good Cool
Post 09 Jul 2004, 04:28
View user's profile Send private message Reply with quote
crc



Joined: 21 Jun 2003
Posts: 637
Location: Penndel, PA [USA]
crc 09 Jul 2004, 11:26
Well the easiest way to optomize for size is to use the BIOS functions Smile For speed, your method looks good to me. It's flexible, and pretty clean. I made one more version (supporting both your syntax, and my write_str macro) with a couple of minor updates that make the code more reliable:

Code:
ORG 100H

TX = 80
TY = 25

; Some color names to use instead of raw numbers
BLACK = 0
BLUE = 1
GREEN = 2
PURPLE = 3
RED = 4
CYAN = 5
BROWN = 6
WHITE = 7
GREY = 8
BRIGHTBLUE = 9
BRIGHTGREEN = 10
BRIGHTPURPLE = 11
BRIGHTRED = 12
BRIGHTCYAN = 13
BRIGHTBROWN = 14
BRIGHTWHITE = 15

virtual at 0
   write:
        .x        dw   ?
        .y        dw   ?
        .back   db   ?
        .fore    db   ?
        .str    dw  ?
        .size   dw ?
end virtual

macro mov a, b {
   local c, d, e
     if b eqtype ''
      jmp e
      label c
      db b
      label d
      dw $-c
      label e
        mov ax, c
        mov [write.str], ax
        mov cx, [d]
        mov [write.size], cx
     else
      move a, b
    end if
}
move fix mov

macro write_string text, x, y, fg, bg {
   local a, b, size
   mov [write.x], x
   mov [write.y], y
   mov [write.back], bg
   mov [write.fore], fg
   mov [write.str], text
   call WriteStr
}

push cs
pop ds
push $b800      ; Set ES here, unless you need to alter it later on
pop es          ; It'll save a little time when you call WriteStr

mov ax,03h
int 10h

   mov [write.x], 10
   mov [write.y], 10
   mov [write.back], GREY
   mov [write.fore], BLUE
   mov [write.str], 'this is a test'
   call WriteStr
; Or this way:
;  write_str 'this is a test', 10, 10, GREY, BLUE

xor ax,ax
int 16h
int 20h

WriteStr:
        mov   si, [write.str]

        mov   ax, [write.y]    ; (Y*TX-(TX-X))*2 ;((Y-1)*TX+X)*2
        mov   bx, TX
        mul   bx
        sub   bx, [write.x]
        sub   ax, bx
        mov   cx, 2
        mul   cx
        mov   di, ax

        mov   ah, [write.back]
        mov   al, [write.fore]
        shl   ah, 4
        or    ah, al
        mov cx, [write.size]

      Continue:
        mov   al, byte [si]
        stosw
        inc si
        loop Continue           ; Was: loopnz
        ret                                                                                                  
    


This now loads si from write.str and cx from write.size. These changes will prevent some errors if the registers are assigned out of order Smile I also fixed a bug in the write_str macro (which assigned both X & Y to the same value). I'll see if I can shave off a couple of bytes though. One last change for now: I defined the names and values of some colors to make using this easier.
Post 09 Jul 2004, 11:26
View user's profile Send private message Visit poster's website Reply with quote
Gambino



Joined: 20 Jul 2003
Posts: 44
Location: Romania
Gambino 09 Jul 2004, 21:39
Code:
ORG 100H
USE16

TX = 80
; TY = 25 NOT NEEDED  Very Happy

; Some color names to use instead of raw numbers
BLACK = 0
BLUE = 1
GREEN = 2
PURPLE = 3
RED = 4
CYAN = 5
BROWN = 6
WHITE = 7
GREY = 8
BRIGHTBLUE = 9
BRIGHTGREEN = 10
BRIGHTPURPLE = 11
BRIGHTRED = 12
BRIGHTCYAN = 13
BRIGHTBROWN = 14
BRIGHTWHITE = 15

;------------------
; define procedure.
;------------------

macro proc name,[arg] {
common
  if used name
  name:
  virtual at bp+6
    if ~ arg eq
      forward
        local ..arg
        ..arg dw ?
        arg equ ..arg
      common
    end if
    ..ret = $ - (bp+6)
  end virtual
  local ..dynamic_data, ..dynamic_size

  dynamic_data equ ..dynamic_data
  dynamic_size equ ..dynamic_size

  virtual at bp - dynamic_size
    dynamic_data:
}

;------------------------------
; begin procedure instructions.
;------------------------------

macro begin {
    dynamic_size = $ - dynamic_data
  end virtual
   enter dynamic_size,0
}

;-----------------------
; Return from procedure.
;-----------------------

macro endp
 { leave
   if ..ret = 0
     retf
   else
     retf ..ret
   end if
  end if        ; for "used" check in proc macro
 }

;----------------
; Call procedure.
;----------------

macro callhere proc,[arg]
{
    if ~ arg eq
      reverse
        push arg
    end if
   common
    call proc
}


;----------------------------------------
; Make far call in the same code segment.
;----------------------------------------

macro callp proc,[arg] {
    if ~ arg eq
      reverse
        push arg
    end if
   common
    push cs
    call proc
}

push cs
pop ds

mov ax,03h
int 10h

callp WriteStr,30,20,BLUE,BRIGHTBROWN,mm
callp WriteStr,30,21,BLUE,BRIGHTWHITE,mm
callp WriteStr,30,23,15,BRIGHTRED,mmm ; 15-WHITE+BLINK

xor ax,ax
int 16h

int 20h

proc WriteStr,x,y,b,f,msg
     begin
        push  $B800
        pop   es

        mov   ax, [msg]
        mov   si, ax

        mov   ax, [y]       ; THIS ROUTINE WAS FIXED
        dec   ax            ; THE OFFSET ONSCREEN
        mov   cx, 80        ; WAS CALCULATED WRONG
        mul   cx            ; NOW THIS IS OK !
        add   ax, [x]       ;
                            ;
        ;mov   cx, 2        ; this 2 lines replaced
        ;mul   cx           ; by the one below
        shl   ax, 1         ; optimised Cool

        mov   di, ax

        mov   ah, byte [b]  ; Here We Calculate Color
        mov   al, byte [f]  ; For BackGround And
        shl   ah, 4         ; ForeGround
        or    ah, al        ;

        mov   al, byte [si]
      Continue:
        stosw
        inc si
        mov al, byte [si]
        or  al,   0
        jnz Continue
     endp


mm db 'Testing',0
mmm db 'Hey look FASM is good !',0    


hey is this better using procedures ? or not ? (i think not...)
i optimised and fixed a bug anyway in the main routine...
this is better so crc u can do the same for your version
if u want we can compare speeds to see how fast it is
any optimisation will be wellcome Cool
Post 09 Jul 2004, 21:39
View user's profile Send private message Reply with quote
crc



Joined: 21 Jun 2003
Posts: 637
Location: Penndel, PA [USA]
crc 09 Jul 2004, 22:11
I prefer the version without procedures. I did a new version with your changes to WriteStr:

Code:
ORG 100H

TX = 80

; Some color names to use instead of raw numbers
BLACK = 0
BLUE = 1
GREEN = 2
PURPLE = 3
RED = 4
CYAN = 5
BROWN = 6
WHITE = 7
GREY = 8
BRIGHTBLUE = 9
BRIGHTGREEN = 10
BRIGHTPURPLE = 11
BRIGHTRED = 12
BRIGHTCYAN = 13
BRIGHTBROWN = 14
BRIGHTWHITE = 15

virtual at 0
   write:
        .x        dw   ?
        .y        dw   ?
        .back   db   ?
        .fore    db   ?
        .str    dw  ?
end virtual

macro mov a, b {
   local c, d
     if b eqtype ''
      jmp d
      label c
      display b
      db b,0
      label d
        mov ax, c
        mov [write.str], ax
     else
      move a, b
    end if
}
move fix mov

macro write_string text, x, y, fg, bg {
   mov [write.x], x
   mov [write.y], y
   mov [write.back], bg
   mov [write.fore], fg
   mov [write.str], text
   call WriteStr
}

push cs
pop ds
push $b800      ; Set ES here, unless you need to alter it later on
pop es          ; It'll save a little time when you call WriteStr

mov ax,03h
int 10h

   mov [write.x], 10
   mov [write.y], 10
   mov [write.back], GREY
   mov [write.fore], BLUE
   mov [write.str], 'this is a test'
   call WriteStr
; Or this way:
;  write_str 'this is a test', 10, 10, GREY, BLUE

xor ax,ax
int 16h
int 20h

WriteStr:
        mov   ax, [write.y]       ; THIS ROUTINE WAS FIXED
        dec   ax            ; THE OFFSET ONSCREEN
        mov   cx, TX        ; WAS CALCULATED WRONG/
        mul   cx            ; NOW THIS IS OK !
        add   ax, [write.x]       ;
        shl   ax, 1         ; optimised
        mov   di, ax

        mov   ah, [write.back]
        mov   al, [write.fore]
        shl   ah, 4
        or    ah, al

        mov   si, [write.str]
      Continue:
        mov al, byte [si]
        stosw
        inc si
        cmp al, 0
        jnz Continue
ret               
    


This is 107 bytes in length, so it's getting to be pretty tight now. I find procedures to be complex; simple code is better. Besides, a macro like write_str is just as useful IMO. I'm going to try to do a version that passes parameters on the stack; that might be smaller or faster. Or maybe not Smile
Post 09 Jul 2004, 22:11
View user's profile Send private message Visit poster's website Reply with quote
Gambino



Joined: 20 Jul 2003
Posts: 44
Location: Romania
Gambino 10 Jul 2004, 11:50
Code:
ORG 100H
USE16       ;just for show

TX = 80
; TY = 25 Not Needed

; Some color names to use instead of raw numbers
BLACK            = 0
BLUE             = 1
GREEN            = 2
PURPLE           = 3
RED      = 4
CYAN             = 5
BROWN            = 6
WHITE            = 7
GREY             = 8
BRIGHTBLUE   = 9
BRIGHTGREEN  = 10
BRIGHTPURPLE = 11
BRIGHTRED    = 12
BRIGHTCYAN   = 13
BRIGHTBROWN  = 14
BRIGHTWHITE  = 15

virtual at 0
   write:
     .x      dw ?
        .y      dw ?
        .back   db ?
        .fore   db ?
        .str    dw ?
        .size   dw ?
end virtual

macro mov a, b {
   local c, d, e
     if b eqtype ''
      jmp e
      label c
      db b
      label d
      dw $-c
      label e
       mov ax, c
   mov [write.str], ax
 mov cx, [d]
 mov [write.size], cx
     else
      move a, b
    end if
}
move fix mov

macro write_str text, x, y, fg, bg {
   local a, b, size
   mov [write.x], x
   mov [write.y], y
   mov [write.back], bg
   mov [write.fore], fg
   mov [write.str], text
   call WriteStr
}

push cs
pop ds
;push $b800      ; Set ES here, unless you need to alter it later on
;pop es          ; It'll save a little time when you call WriteStr

mov ax,03h
int 10h

;   mov [write.x], 10
;   mov [write.y], 10
;   mov [write.back], GREY
;   mov [write.fore], BLUE
;   mov [write.str], 'this is a test'
;   call WriteStr

; Or this way:
write_str 'this is a test', 10, 10, GREY, BLUE ; Fixed was write_string
                            ; and was declared write_str
xor ax,ax
int 16h
int 20h

WriteStr:
mov  ax, 0B800h ;leave this here it should work like a proc
mov  es, ax         ;push 0B800h, pop es was better Rolling Eyes Question

mov  ax, [write.y];
dec  ax              ;
mov  cx, TX        ;
mul  cx            ;this routine calculates offset on-screen
add  ax, [write.x];
shl  ax, 1          ;
mov  di, ax       ;put offset in di

mov  ah, [write.back]  ;
mov  al, [write.fore]  ;this routine calculates back and fore
shl  ah, 4               ;
or   ah, al        ;

mov  cx, [write.size]  ;the size of the string to be printed

mov  si, [write.str]   ;here we move the offset of message in si
     Continue:
;mov   al, byte [si]   ;optimised with lodsb (i think...)
lodsb
stosw
;inc si                ;si is automatic increased by lodsb
loop Continue
ret    


Optimised a little i think....
I don't want the strings to be 0 terminated but it was required by procedures...now back to normal
Working ar ClearScreen and others Cool
Thinking....How much we can optimise this code ???
This code is part of a command iterpreter for an OS i am working with Dexter Cool
Post 10 Jul 2004, 11:50
View user's profile Send private message Reply with quote
Gambino



Joined: 20 Jul 2003
Posts: 44
Location: Romania
Gambino 10 Jul 2004, 12:16
Look at the command interpreter
http://board.flatassembler.net/topic.php?t=1823
We have bugs and need assistence...
crc please take a look Cool
Post 10 Jul 2004, 12:16
View user's profile Send private message Reply with quote
crc



Joined: 21 Jun 2003
Posts: 637
Location: Penndel, PA [USA]
crc 10 Jul 2004, 12:20
Do you want it optomized for size or for speed? How to proceed depends on which way you want it optomized. Let me know, and I'll see what I can do. If you want it optomized for speed, what CPU is it going to be run on? (Speed optomizations are highly specific to each CPU (386, 486, Pentium, Pentium II, Celeron, etc)
Post 10 Jul 2004, 12:20
View user's profile Send private message Visit poster's website Reply with quote
pelaillo
Missing in inaction


Joined: 19 Jun 2003
Posts: 878
Location: Colombia
pelaillo 10 Jul 2004, 15:12
Gambino wrote:
I don't want the strings to be 0 terminated but it was required by procedures...

What procedures?
As long as you don't use C libs in your OS you don't need them. And if needed, you could use for interface only.
Post 10 Jul 2004, 15:12
View user's profile Send private message Yahoo Messenger Reply with quote
Gambino



Joined: 20 Jul 2003
Posts: 44
Location: Romania
Gambino 11 Jul 2004, 14:05
crc i want the code to be optomized for size and speed...
they should be working on any 386+ but they exists only in museums Smile ( i have a 386 Very Happy but is missing a hdd ) so pentium is fine... ( i have a pentium too 133 mhz Cool )

Question
An OS should be optomized for speed or for size ?

pelaillo i wanted to see what is the diffrence between procedures and simple call - ret , i'm just testing to see how will be better to implement an OS Wink
Post 11 Jul 2004, 14:05
View user's profile Send private message Reply with quote
pelaillo
Missing in inaction


Joined: 19 Jun 2003
Posts: 878
Location: Colombia
pelaillo 11 Jul 2004, 15:34
I was talking about zero terminated strings. Who needs them in assembly?

speed or size? It depends on where your OS is supposed to run.
IMHO, an assembly OS must be optimized for speed, as the size is already smaller compared to actual alternatives.
Post 11 Jul 2004, 15:34
View user's profile Send private message Yahoo Messenger Reply with quote
crc



Joined: 21 Jun 2003
Posts: 637
Location: Penndel, PA [USA]
crc 11 Jul 2004, 17:12
Quote:
crc i want the code to be optomized for size and speed...
they should be working on any 386+ but they exists only in museums ( i have a 386 but is missing a hdd ) so pentium is fine... ( i have a pentium too 133 mhz )

Question
An OS should be optomized for speed or for size ?


Ok, I will see what kind of balance would be best. Generally optomizations come at a cost of either size or speed. (A case in point is loop unrolling, which is faster, but much larger in size).

Quote:
pelaillo i wanted to see what is the diffrence between procedures and simple call - ret , i'm just testing to see how will be better to implement an OS


Stick with call/ret; they tend to translate better if you start using interrupts for system calls. (If you intend to run programs that are not built into the kernel, you'll need some sort of system call interface.) Since this is a real mode kernel, taking over an interrupt is pretty easy; so I'd stick with call/ret. (Instead of calling a function, you use an interrupt; end the kernel routines that handles the interrupt with an iret).
Post 11 Jul 2004, 17:12
View user's profile Send private message Visit poster's website Reply with quote
Gambino



Joined: 20 Jul 2003
Posts: 44
Location: Romania
Gambino 11 Jul 2004, 20:23
this topic is closed the main topic is here

http://board.flatassembler.net/topic.php?t=1823
Post 11 Jul 2004, 20:23
View user's profile Send private message Reply with quote
Matrix



Joined: 04 Sep 2004
Posts: 1166
Location: Overflow
Matrix 09 Sep 2004, 16:35
This problem is common, i wonder why

you should take a look at this

http://board.flatassembler.net/topic.php?t=2186

MATRIX
Post 09 Sep 2004, 16:35
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.