1

I couldn't find a clear-cut example to comprehend

1.What does XLAT instruction do?
2. Why do we use it?(applications).

My books describes XLAT

XLAT simplifies the implementation of look-up tables [1]

but I fail to understands which table(s) is the author talking about?
Any help would be appreciable!

[1] The 8088 and 8086 Microprocessors. Walter A. Triebel
Avtar Singh

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Zahid Khan
  • 2,130
  • 2
  • 18
  • 31
  • 6
    Even the first result on my search engine for “x86 xlat” explains the thing very thoroughly. http://www.felixcloutier.com/x86/XLAT:XLATB.html – Sami Kuhmonen Nov 29 '17 at 15:57
  • @SamiKuhmonen Bro, I still dont get, which table they are refering to? – Zahid Khan Nov 29 '17 at 16:02
  • There’s even a pseudo code example of exactly what it does. – Sami Kuhmonen Nov 29 '17 at 16:06
  • 1
    The table is specified as DS:BX (BX being the memory offset to the beginning of the table). _AL_ is the index into the table. XLAT will simply return the value at index _AL_ – Michael Petch Nov 29 '17 at 16:15
  • 3
    As for an example. I recently wrote this [SO answer](https://stackoverflow.com/a/47320115/3857942) that uses XLAT to do the translation of byte to HEX characters. In particular the function `print_byte_hex`. The code was for 16-bit real mode. The XLAT was used to convert the value 0 through 15 to the ASCII value '0 to '9' and 'A' to 'F' – Michael Petch Nov 29 '17 at 16:22
  • Why my question is downvoted? – Zahid Khan Nov 29 '17 at 17:49
  • 6
    @ZahidKhan probably (I guess, I didn't downvote) because search of "x86 xlat instructions" will return many relevant resources, and it's hard to imagine what was not clear to you, would you copy few things into question and explain how you understand them, or what exactly not, it would look like more effort was put into your question. The "table" used by `xlat` is any 256B memory region pointed to by `ds:(e/r)bx`, the returned byte is loaded from address `ds:(e/r)bx+al`. It's up to programmer to set up `ds:bx` with some address into some useful data ("table") to translate `al` into `tab[al]`. – Ped7g Nov 29 '17 at 19:07
  • 1
    I once did 51 byte long DOS binary to draw Greece flag. I used `xlat` instruction, pointing to the code instructions themselves, using them as configuration data for the blue/white strips. The TASM source is available [here](http://ped.7gods.org/GREECE.ASM), but comments are not in English, and overall it's written for minimal size, so it may look very cryptic and weird. If you have DOS debugger, you can try to debug the [binary](http://ped.7gods.org/GREECE.COM) to see, if you can figure out, how it works, and how the `xlat` is used with `al=index of strip` to translate that into blue/white. – Ped7g Nov 29 '17 at 19:11
  • @Ped7g got some hint, but I tried my best to include what what was bothering me, I dont know what this table is and also why we use xlat instuction. – Zahid Khan Nov 29 '17 at 19:45
  • @Ped7g I am using emu8086 that also very helpful. Your answer almost killed my confusion but still little bit confused, what values it is comparing it against? You said it is same as switch in c? Ryt? – Zahid Khan Nov 29 '17 at 19:47
  • Is the author in my question refering to paging and segmentation in OS? – Zahid Khan Nov 29 '17 at 19:49
  • 1
    No, the Author is not referring to paging and segmentation. – Michael Petch Nov 29 '17 at 22:57

5 Answers5

11

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

phuclv
  • 37,963
  • 15
  • 156
  • 475
Ped7g
  • 16,236
  • 3
  • 26
  • 63
  • 3
    Important: The `ds:[bx + al]` "addressing mode" it uses zero-extends `AL`. So the C version definitely needs to use `unsigned byte al`. This is obviously what you want, but not what you get from signed array indexes in C. – Peter Cordes Nov 29 '17 at 21:31
  • 2
    And BTW, if the rest of EAX is known to be zero, `movzx eax, byte [ebx+eax]` is more efficient (for speed) in 32-bit code (or `add cl, [ebx+eax]` or whatever), but `xlatb` does have uses for code-size optimization. It's probably most useful on 8086 without `movzx` (386), because `movzx` to zero extend a byte index into a full register solves the same problem. – Peter Cordes Nov 29 '17 at 21:35
  • @PeterCordes I would never expect `byte` to be signed... that's why avoided `char` ... I should have used `uint8_t`... will edit it. ... Oh wait, Java has signed `byte`. ... but Java is ... nevermind. – Ped7g Nov 29 '17 at 22:42
  • I didn't expect anything from `byte`, it's not a standard type. I thought you were just making up C-like terminology to describe asm. – Peter Cordes Nov 29 '17 at 22:53
  • 3
    Not covered by this is the fact that [`xlatb`](https://ulukai.org/ecm/doc/insref.htm#insXLATB) can have its segment overridden. So it defaults to `ds:(r/e)bx + al` but can take any segment instead. – ecm Aug 19 '20 at 07:44
9

It does a simple byte based lookup against a table specified in DS:BX (in real mode). Used for doing straight character set conversions (ASCII to EBCDIC) for example. I've used it to do other index/result based byte lookups in the past. Slow, but compact instruction.

Brian Knoblauch
  • 20,639
  • 15
  • 57
  • 92
0

Long time since I was programming the 8086. I remember it was used for lookup tables. If you know C you can compare it to the switch() statement which when using a good compiler translated all the cases to a lookup (jump) table instead of using "spaghetti programming" with a lot of if-then-else.

Each case then translates to an address + offset in the jump table which then contains the addresses of the functions to call.

Then a simple JMP is executed and it's done. No compare statements are used. Just addition which makes it fast regardless of how many cases you have.

  • Upvoted as satisfing yet, if are able to add code for better understandability for further readers also. I would be pleased accept the answer. – Zahid Khan Nov 29 '17 at 17:02
  • 5
    `xlatb` is a *byte* lookup. A `switch` jump table is definitely not the obvious use-case, because you need to zero-extend the result to 16 bits. @ZahidKhan: a lookup table is just an array. It doesn't imply anything about control-flow like a `switch`. e.g. to speed up popcount, you can use a table of how many set bits, so `popcount(AL)` = `bits_table[AL]`, which you can implement using `xlatb`. – Peter Cordes Nov 29 '17 at 17:41
0

XLAT Locates a byte entry in a table in memory, using the contents of the AL register as a table index, then copies the contents of the table entry back into the AL register.

umar salman
  • 401
  • 4
  • 5
0
TAB DB '0123456789ABCDEF'
MOV AL,1101B ; Index = 13
MOV BX,OFFSET TAB
XLAT

the index of Al is 13 so the Al after this code will be = 'D'

FearHax
  • 1
  • 1
  • That won't assemble; `:` is a full colon, not a semi-colon `;` comment character. And you're missing a comma in the mov to BX. Also, `1101B` isn't "index = 6", it's 13 like you said in the text. – Peter Cordes Dec 09 '21 at 15:42
  • thanks i edited the code – FearHax Dec 09 '21 at 16:09
  • Your answer could be improved by adding more information on what the code does and how it helps the OP. – Tyler2P Dec 09 '21 at 20:49