Page 2 of 2

Re: I know a very optimized way to print characters in pmode

Posted: Fri Nov 11, 2011 2:52 am
by rdos
Why are such simple things so hard in C? :mrgreen:

Code: Select all

    mov ax,730h
    mov edi,0B8000h
    mov [edi],ax    ; will write "0" in top left corner

Re: I know a very optimized way to print characters in pmode

Posted: Fri Nov 11, 2011 2:59 am
by Solar
rdos wrote:Why are such simple things so hard in C? :mrgreen:
Because your ASM example doesn't do the same thing (printing a parameterized character to a parameterized location). 8)

Moreover, your ASM source is specific to a certain assembler, and won't necessarily compile on a different one (AT&T vs. Intel syntax). The C source discussed here would compile on any C compiler. 8)

Re: I know a very optimized way to print characters in pmode

Posted: Fri Nov 11, 2011 4:02 am
by rdos
Solar wrote:Because your ASM example doesn't do the same thing (printing a parameterized character to a parameterized location). 8)
That's easy to fix: :mrgreen:

Code: Select all


;  AH = attribute
;  AL = char
;  BL = row
;  BH = col

WriteChar   Proc
    push edi
    push ax
    mov al,80
    mul bl
    add al,bh
    adc ah,0
    add ax,ax
    mov edi,0B8000h
    or di,ax
    pop ax
    mov [edi],ax
    pop edi
    ret
WriteChar   Endp

Solar wrote:Moreover, your ASM source is specific to a certain assembler, and won't necessarily compile on a different one (AT&T vs. Intel syntax). The C source discussed here would compile on any C compiler. 8)
Yes, but it is unreadable.

BTW, if you also want a version that is independent of the physical location of the video-buffer, and that have forecolor and backcolor as parameters instead of the combined attribute, it looks something like this:

Code: Select all

;  AL   Char
;  BL   Fore color
;  BH   Back color
;  CX   Column
;  DX   Row

WriteChar Proc
    push ds
    push ax
    push di
    mov ah,bh
    shl ah,4
    or ah,bl
    push ax
    push dx
    mov ax,80
    mul dx
    add ax,cx
    add ax,ax
    mov di,ax
    mov ax,dosb800
    mov ds,ax
    pop dx
    pop ax
    mov [di],ax
    pop di
    pop ax
    pop ds
    ret
WriteChar   Endp

Re: I know a very optimized way to print characters in pmode

Posted: Fri Nov 11, 2011 4:21 am
by rdos
berkus wrote:
rdos wrote:Yes, but it is unreadable.
It's unreadable because it was written in a pretty lame way. See Solar's improvement, which is heaps more readable.
Well, it consists of a set of unreadable macros instead. There is nothing more frustrating than to try to figure out how a particular #define is evaluated by the compiler when these are generated based on a zillion other defines. :evil:

Re: I know a very optimized way to print characters in pmode

Posted: Fri Nov 11, 2011 4:31 am
by Combuster
The fact that you suck at chinese doesn't make it a bad thing that there are a billion people out there fluent with it.

You're breaking the language war rule, stop it please.

Re: I know a very optimized way to print characters in pmode

Posted: Fri Nov 11, 2011 4:58 am
by Solar
rdos wrote:
berkus wrote:
rdos wrote:Yes, but it is unreadable.
See Solar's improvement, which is heaps more readable.
Well, it consists of a set of unreadable macros instead.
Neither "unreadable" nor "a set" (since there is only one macro), hence I call "troll".

If all you have is a hammer, a screw is just a funny-looking and somewhat impractical nail...

Re: I know a very optimized way to print characters in pmode

Posted: Fri Nov 11, 2011 5:41 am
by Brendan
Hi,
Solar wrote:I took the liberty of optimizing your code further:
This version suffers from the same problem as the original - it fails to recognise that often you're printing a string and you only need to do the "address = start + (y * 80 + x) * 2" calculation once for the first character, then "address += 2" for each additional character. Basically, the next step in optimisation is to realise "putch()" is virtually irrelevant because you're using "putstring()" for almost everything instead.

The first step in optimising "putstring()" is to just append the new string to a buffer while checking if it contains any '\n' characters. If it does you'd copy whole lines (and never partial lines) to display memory. Basically "putstring()" would call a "putline(int y, char *string)" function that does "address = start + y * 80 * 2" for the first character and then "address += 2" for the remaining characters (or maybe a "lodsb; stosw" loop).

The next step would be to realise that this causes excessive scrolling. For example, if you add 12 lines of text at once, then you scroll 12 times (by 1 line each time) instead of only scrolling once (by 12 lines). To fix that you add a "flush_console()" function. The "putstring()" function just appends data to the buffer, and "flush_console()" counts how many lines are in the buffer, scrolls the screen once (if necessary), then copies text from the buffer to the screen.


Cheers,

Brendan

Re: I know a very optimized way to print characters in pmode

Posted: Fri Nov 11, 2011 6:12 am
by Solar
Agreed.

My "optimization" was aiming at a proof that proper use of constants doesn't mean an increase in executable size. (Plus some implied hints to coding style).

As Karlosoft pointed out, the clrscr() function could be replaced by a memset() call, and you pointed out some valid issues with the underlying algorithm.

All in all, I would think twice before implementing either putch() or putstring() or whatever. Chances are you'll want to use <stdio.h>-like functionality sooner or later, and that doesn't need either putch() or putstring(), but a backend for plain old write( 1, ... ), i.e. a memcpy() capable of handling linefeeds...