From the flatassembler board:
- FASM whines with "reserved word used as symbol"
Instructions like MOV AX, [CX] or JMP WORD [AX] cause this error - FASM bug ?
Your BUG. Only BX, BP, SI and DI are available for indexing in 16-bit code. FASM's report is bad, but it originates from internal design. This is a "problem" of 8086 design and 16-bit code. Using more registers like EAX etc. for addressing is a privilege of 32-bit code on 80386 and later CPU's.
Not every register 16-bit register can be used as an address register, only the following combinations are allowed:
- Only displacement:
[displacement]
- Only base register:
[BX+displacement]
- Only base pointer:
[BP+displacement]
- Only index register
[SI+displacement] or [DI+displacement]
- Base and index register:
[BX+SI+displacement] or [BX+DI+displacement]
- Base pointer and index register:
[BP+SI+displacement] or [BP+DI+displacement]
The displacement can be omitted when 0. It can be a variable name here, for example. In this case you could write
mov al, [HEXi]
instead or use one of the allowed registers instead:
mov di, HEXi
mov al, [di]
The register size does not have to be specified here with byte, as it is clearly specified by the target register.
How can I manipulate the characters of the HEXi string?
Assuming the value to be output is in dx and should be written as a hexadecimal number in the string HEXi. With
mov [bx+HEXi], al
a character from the register al can be written to the bx-th position of HEXi, starting from zero. Since the string already starts with 0x and that should not be overwritten, the first two characters are skipped using
mov [bx+HEXi+2], al
The value HEXi+2 is encoded as the immediate value mentioned above. Now 4 bits should each be converted to a hexadecimal digit, i.e. the characters
0to 9 (character codes 0x30 to 0x39) and
A to F (character codes 0x41 to 0x46`).
This is done in the following steps:
First the lower 4 bits of dx are isolated and converted into character codes 0x30 up to 0x3F with
mov al, dl ; Copy the lower 8 bits of dx to al
and al, 0x0F ; Set the upper 4 bits of al to zero
or al, 0x30 ; Convert to charcode
The character codes 0x3A to 0x3F must be shifted to 0x41 to 0x46. For this purpose, it is first checked whether the value lies in it, in order to shift it if necessary:
cmp al, 0x39
jbe noShiftNeeded
add al, 7
noShiftNeeded:
This should happen for all for 4-bit nibbles of the 16-bit value in dx. After each step, dx is shifted to the right by 4 bits so that the previous code can be used again. The final code is then:
print_hex:
pusha
mov bx, 3 ; Start with last character
hexLoop:
mov al, dl ; Copy the lower 8 bits of dx to al
and al, 0x0F ; Set the upper 4 bits of al to zero
or al, 0x30 ; Convert to charcode
cmp al, 0x39
jbe noShiftNeeded
add al, 7
noShiftNeeded:
mov [bx+HEXi+2], al ; Write the character to HEXi
shr dx, 4 ; To be able to repeat this with the next 4-bit nibble
sub bx, 1 ; If this wasn't the forth character, repeat
jnc hexLoop
popa
ret