Code Gems Part 2

This text comes from IMPHOBIA Issue IX - February 1995




* Short Palette Loading *

The traditional method to fill the palette registers sounds somehow like this (15 bytes+palette):
        mov     al,startcolor
        mov     dx,3c8h
        out     dx,al
        inc     dx
        mov     cx,colornum*3
        mov     si, offset rgbpalette
        rep     outsb
Here's the shorter way (13+1 bytes+palette):
        mov     dx,03c8h
        mov     si, offset startcolor
        outsb
        inc     dx
        mov     cx,colornum*3
        rep     outsb
After startcolor come the RGB components.
And here's the general procedure:
setpal:
        mov     dx,3c8h
        outsb
        inc     dx
        lodsw
        xchg    cx,ax
        rep     outsb
        ret
After startcolor (the byte at [SI]) is colornum*3 (the word at [SI+1]), then the RGBs. SI is loaded by the caller.

* Feeding the VGA registers *

An usual VGA initializer routine:
        mov     dx,03xxh
        mov     ax,xx
        out     dx,ax
        mov     dl,xx
        mov     al,xx
        out     dx,al
        ...
But why not to collect the values into one array like this:
        mov     si,offset vgaregs
        mov     dx,03xxh
        outsw
        mov     dl,xx
        outsb
        ...
This may be combined, per chance with REP OUTs too. Make sure that CH won't be loaded unnecessarily after REPs. See:
        mov     cl,3
        rep     outsb
is longer than
        outsb
        outsb
        outsb
but gives the same result.

* A nice tweaked mode operation *

Let's put a raw picture's line:
        mov     al,2
        mov     dx,3c4h
        out     dx,al
        inc     dx
        mov     al,11h
        mov     cx,linelength
onerow:
        out     dx,al
        movsb
        rol     al,1
        adc     di,0ffffh
        loop    onerow
Actually this is a very slow way to do it, I wanted to show just its philosophy.

* XCHG instead MOV and PUSH/POP *

Note that
        xchg    reg,ax
takes only 1 byte and the TASM compiles XCHG ANYREG,AX even if we write XCHG AX,ANYREG. And
        xchg    ax,ax
is nothing else but the good old NOP.( Protected mode freaks may think XCHG EAX,EAX :-) Sometimes when there is a free register, double XCHG REG,AX is better than PUSH/POP AX.

* Short Compare *

If a routine gives back the result in a register and its value is 0 on error and 1 on success, the ordinary
        or      ax,ax
        je      error
can be replaced with the shorter
        dec     ax
        jne     error
For example, the XMS driver reports the errors this way. Is it fair that testing if a register=0 is longer than testing if it is 1 or -1? :-(

* Tiny Little Instructions *

CBW/CWD/CDQ/CWDE are the short ways to clear/set AH/DX/EDX/upper word of EAX when the MSB of AL/AX/EAX/AX is known in advance.

* Writing a two-digit number *

Let's suppose we want to write out a two-digit number in any numerical system between [2..10]. Value comes in AL, the base of the numerical system is in AH.
WRITE2DIGIT     macro
local  zeros,convert

       mov     byte ptr aam_operand,ah
       call    convert
zeros  db      '00$'

convert:
aam_operand     equ $+1
        aam
        xchg    ah,al
        add     word ptr zeros,ax
        mov     ah,9
        pop     dx
        int     21h
endm
See it from a debugger ;-) When we want to write decimal numbers only, then unnecessary to rewrite the AAM's operand. The morals of the macro:

* Puzzle *

Remember? The solution is under 4 instructions...

* HLT *

HLT can be useful! It's very easy to make timings with it:
        mov     cx,18
        hlt
        loop    $-1
This was an 1-second delay.

* Macro Fun *

Let me ask You one of my favourite questions! Which programming language is this:
     Writeln('Hello, world!');
Pascal...?
Not!
This is assembly.Here's the solution:
WRITELN macro   _string
local   _afterstring

        call    _afterstring

db      _string,13,10,'$'

_afterstring:
        mov     ah,9
        pop     dx
        int     21h
endm
This idea was taken from Silent's Planet Zzyqxhaycom BBS advert.

* Optimizing for coding time *

Look at this:
b       equ     byte ptr
w       equ     word ptr
o       equ     offset
...
With these abbrevations some typing time can be saved. (Invented by TomCat.)

* Puzzle - The Solution *

imul eax,01010101h
(Now you can kill me.)

I would be very glad if the next issue would contain another part(s) of Code Gems from other coders. If You want to contact me, here's my address:
           Ervin / AbaddoN
              Ervin Toth
               HUNGARY
            1126 Budapest
         Kiss Janos str. 48/a
           (+36)-1-201-9563
       ervin@unicorn.sch.bme.hu