I have done my research and stumbled upon many solutions to change some characters of the string. I am trying to print a hex code in it's string form. But I have tried all the solutions but it won't compile on "Flat assembler". Following is my code :
mov bx, HELLO
call print_string
mov dx, 0x1fb6
call print_hex
jmp $
print_hex:
pusha
mov cx, HEXi
mov al, byte ptr [cx]
back:
popa
ret
include "print_string.asm"
HELLO: db 'Hello, World!',0
HEXi: db '0x0000',0
times 510 -( $ - $$ ) db 0
dw 0xaa55
On Compilation it just shows invalid expression error.
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:
[displacement]
[BX+displacement]
[BP+displacement]
[SI+displacement]
or [DI+displacement]
[BX+SI+displacement]
or [BX+DI+displacement]
[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
0
to 9
(character codes 0x30
to 0x39
) andA
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