If you know C, then it works like this:
const uint8_t table[256] = { ...some byte constants (table data) ... };
const uint8_t* ds_bx = table;
uint8_t al = <some value to translate>;
al = ds_bx[al]; // al = table[al];
// like "mov al,[ds:bx + al]" in ASM
That [ds:bx + al]
is not legal memory operand for mov
instruction, but xlat
accepts it, actually that's the only way how xlat
will address memory (you can't modify it to use different registers).
What kind of data you put in the table, or where you locate the table in memory, is up to you. Also what you use it for. This is not related to memory-paging or some other memory OS tables, this is just purely user data thing.
You can for example use it to translate index of food in menu into price for food, if your food index is 0..255 and price will fit into 8 bits too. Then you reserve 256 bytes for table containing price data, and load ds:bx
with address of that table, put index of food into al
, and the xlat
will translate the index into price from the table.
In my Greece-flag drawing DOS 51B COM (binary) (source) I use the xlat
instruction to translate index of strip-column 0..4 into blue/blue/white/blue/blue configuration.
I check first if the [x,y] coordinates are in the top left part of flag, where is the big white cross on blue rectangle. If outside, the colour of pixel is simple (y div strip_size) & 1
alternating blue/white colour.
But inside the cross area, I calculate 5x5 grid, and the middle row strip is full white. The two strips above and under the middle has to be drawn in [blue, blue, white, blue, blue]
depending on x-coordinate (to which column-strip it belongs). To make this conversion from [0, 1, 2, 3, 4]
values into [1, 1, 0, 1, 1]
I'm using xlat
instruction, pointing into the code itself, and masking the instruction opcodes to extract only lowest bit (odd/even). By small rearranging of instructions in the code I managed to get wanted odd/even instruction opcode bytes at address where I can reach them through xlat
.
If I would do that conversion by if-else
branching, or some other arithmetic, it would take more bytes of code, than simple xlat
reusing already needed value in bx
and al
.
In common applications you will hardly find any usage for xlat
instruction. It's archaism from 8086 times, compiler will certainly not use it, and most of hand written assembly neither, as usually you can use simple mov al,[bx+si]
or something similar.
In 32b mode if you know the value is already zero-extended to 32b, the mov al,[ebx+eax]
is faster than xlat
(with same result).
In code-golfing, when you are trying to produce shortest machine code the xlat
may be handy (so far I needed it twice in life, for hexadecimal number formatting, and for that Greece flag drawing code).