flat assembler
Message board for the users of flat assembler.

 Index > DOS > How to convert decimal to 32-bit hex in DOS (for hexdump)? Goto page 1, 2  Next
Author
FlierMate11

Joined: 13 Oct 2022
Posts: 94
FlierMate11 27 Jan 2023, 10:12
Previously, Tomasz offered his solution to me for 32-bit and 64-bit programming.

Now, I port my hexdump from Windows & Linux to DOS, but limited to 16-bit register, I cannot convert to hexadecimal value larger than 16-bit, at least I don't know how.

Code:
```ConvertLongHex:     Nice code snippet by Tomasz Grysztar (flat assembler)
xor      di,di
mov     cx, 4
.loop1:
rol      dx,4
mov      si,dx
and      si,1111b
mov      al,[_digits+si]
mov      [di+_hexnum],al
inc      di
dec      cx
jnz      .loop1
ret
...
...
_hexnum   rb 4
db '\$'
_hexval   rb 2
db '\$'
_digits   db '0123456789ABCDEF'

```

Can someone enlighten?

This is the 32-bit hex edition:
Code:
```ConvertLongHex:     Nice code snippet by Tomasz Grysztar (flat assembler)
xor      ebx,ebx
mov     ecx, 8
.loop1:
rol      edx,4
mov      eax,edx
and      eax,1111b
mov      al,[_digits+eax]
mov      [ebx+_hexnum],al
inc      ebx
dec      ecx
jnz      .loop1
ret        ```

Last edited by FlierMate11 on 27 Jan 2023, 10:17; edited 1 time in total
27 Jan 2023, 10:12
FlierMate11

Joined: 13 Oct 2022
Posts: 94
FlierMate11 27 Jan 2023, 10:13
Example output of my hexdump (almost finished except the hexadecimal conversion part, because 16-bit offset only)
Code:
```0000  4D 5A 41 00 02 00 01 00 02 00 1F 00 FF FF 32 00   MZA...........2.
0010  00 01 00 00 00 00 00 00 1C 00 00 00 01 00 00 00   ................
0020  B8 1A 00 8E D8 FC 26 0F B6 0E 80 00 26 8D 3E 81   ......&.....&.>.
0030  00 8D 36 81 00 83 F9 00 0F 84 F2 00 26 8A 05 3C   ..6.........&..<
0040  20 75 07 3C 0D 74 09 47 EB F2 88 04 46 47 E2 EC    u.<.t.G....FG..    ```
27 Jan 2023, 10:13
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 20132
revolution 27 Jan 2023, 10:26
Not enough room for 8 characters.
FlierMate11 wrote:
Code:
`_hexnum   rb 4    `
27 Jan 2023, 10:26
FlierMate11

Joined: 13 Oct 2022
Posts: 94
FlierMate11 27 Jan 2023, 11:11
revolution wrote:
Not enough room for 8 characters.
FlierMate11 wrote:
Code:
`_hexnum   rb 4    `

Yes, I changed it.

But if I change it back to
Code:
`_hexnum   rb 8    `

and set "mov cx, 8", this is the "32-bit" hex output (see offset):
Code:
```00000000  4D 5A 41 00 02 00 01 00 02 00 1F 00 FF FF 32 00   MZA...........2.
00100010  00 01 00 00 00 00 00 00 1C 00 00 00 01 00 00 00   ................
00200020  B8 1A 00 8E D8 FC 26 0F B6 0E 80 00 26 8D 3E 81   ......&.....&.>.
00300030  00 8D 36 81 00 83 F9 00 0F 84 F2 00 26 8A 05 3C   ..6.........&..<
00400040  20 75 07 3C 0D 74 09 47 EB F2 88 04 46 47 E2 EC    u.<.t.G....FG..
00500050  B0 24 88 04 BA 81 00 B4 09 CD 21 B4 3D 30 C0 BA   .\$........!.=0..
00600060  81 00 CD 21 A3 7B 00 0F 82 CC 00 B4 3F 8B 1E 7B   ...!.{......?..{
00700070  00 B9 10 00 BA 67 00 CD 21 A3 77 00 0F 82 C7 00   .....g..!.w.....
00800080  8B 0E 77 00 85 C9 0F 84 9A 00 89 0E 7D 00 8B 16   ..w.........}...
00900090  7F 00 B9 04 00 E8 F3 00 E8 D6 00 E8 BE 00 31 C9   ..............1.
00A000A0  31 D2 89 CE 8A 54 67 51 B9 02 00 E8 F2 00 E8 C7   1....TgQ........    ```

Do you know what's wrong? Or must use two registers for it?
27 Jan 2023, 11:11
FlierMate11

Joined: 13 Oct 2022
Posts: 94
FlierMate11 27 Jan 2023, 11:17
Code:
```mov     dx, [_offset]
mov     cx, 4
call    ConvertLongHex
```

I forgot to post the "mov dx, [_offset]" in above.

Looks like "rol dx, 4" is the bottleneck.

Anyway, the dx can only contain 16-bit value......
27 Jan 2023, 11:17
FlierMate11

Joined: 13 Oct 2022
Posts: 94
FlierMate11 27 Jan 2023, 11:33
I think I will just publish this HEXDUMPD (for DOS version) for small files only (below 64KB) until I have better solution to support large file offset.

Thanks to @macomics and @sinsi for their help in solving command-line arguments in DOS (https://board.flatassembler.net/topic.php?t=22564&start=20), I benefited from it indirectly.

If anyone want to create polyglot EXE, can combine my Hexdump for DOS with Hexdump for Windows.

https://board.flatassembler.net/topic.php?t=22184

Change the first line to :
Code:
```format PE console on 'HEXDUMPD.EXE'
```

Compile my HEXDUMPD.asm (DOS), and then compile HEXDUMPW.asm (Win32), you'll now have a 2-in-1 EXE.

Can redirect to file:
Code:
```hexdumpd abc.exe > b.txt

hexdumpw test.jpg > c.txt
```

27 Jan 2023, 11:33
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 20132
revolution 27 Jan 2023, 11:45
FlierMate11 wrote:
Do you know what's wrong? Or must use two registers for it?
No. You had only posted random snippets so no way to tell what you did.

But one thing is for sure, you don't need to use two registers if you are running the code on a 32-bit capable machine.
27 Jan 2023, 11:45
ProMiNick

Joined: 24 Mar 2012
Posts: 786
Location: Russian Federation, Sochi
ProMiNick 27 Jan 2023, 12:12
Code:
```INT2HEX:
;in
;si - ptr INT
;cx - size in bytes of int limited by ram occupied by [si] & [di] addressed buffers
;di - ptr HEX
xor     ax, ax
;mov     dx, cx
jmp     .cvt_in
.loop:
dec     si
mov     al, [si]
ror     ax, 4
shr     ah, 4
test    ah,\$10
jz      @F
@@:
test    al,\$10
jz      @F
@@:
stosw
.cvt_in:
dec     cx
jnz     .loop
mov     [di], cl
;sub     di, dx      ```
27 Jan 2023, 12:12
FlierMate11

Joined: 13 Oct 2022
Posts: 94
FlierMate11 27 Jan 2023, 12:46
Thanks @ProMiNick, I am still trying to make it work.

Is the "di" register increment (cld) or decrement (std)?

I set the value as below:
Code:
```mov     di, _hexnum
mov     si, _offset
mov     cx, 4

...
...
_offset   dd 0
_hexnum   rb 8
db '\$'
```

Output is incorrect though:
Code:
```    000000   4D 5A 41 00 02 00 01 00 02 00 1F 00 FF FF 32 00   MZA...........2.
0000000  00 01 00 00 00 00 00 00 1C 00 00 00 01 00 00 00   ................
0000000  B8 1A 00 8E D8 FC 26 0F B6 0E 80 00 26 8D 3E 81   ......&.....&.>.
0000001  00 8D 36 81 00 83 F9 00 0F 84 F2 00 26 8A 05 3C   ..6.........&..<
000000C  20 75 07 3C 0D 74 09 47 EB F2 88 04 46 47 E2 EC    u.<.t.G....FG..
000000C  B0 24 88 04 BA 81 00 B4 09 CD 21 B4 3D 30 C0 BA   .\$........!.=0..
000000A  81 00 CD 21 A3 7B 00 0F 82 CC 00 B4 3F 8B 1E 7B   ...!.{......?..{
000000B  00 B9 10 00 BA 67 00 CD 21 A3 77 00 0F 82 C7 00   .....g..!.w.....
0000000  8B 0E 77 00 85 C9 0F 84 9A 00 89 0E 7D 00 8B 16   ..w.........}...
0000006  7F 00 B9 04 00 E8 F3 00 E8 D6 00 E8 BE 00 31 C9   ..............1.
0000009  31 D2 89 CE 8A 54 67 51 B9 02 00 E8 F2 00 E8 C7   1....TgQ........
0000007  00 E8 AF 00 59 41 3B 0E 7D 00 72 E4 83 F9 10 72   ....YA;.}.r....r
0000002  02 EB 11 BB 10 00 29 CB E8 98 00 E8 95 00 E8 92   ......).........
0000002  00 4B 75 F4 E8 85 00 31 C9 31 D2 89 CE 8A 54 67   .Ku....1.1....Tg
0000007  51 80 FA 20 72 0E 80 FA 7F 73 09 88 16 45 00 E8   Q.. r....s...E..
0000008  8D 00 EB 08 C6 06 45 00 2E E8 83 00 59 41 3B 0E   ......E.....YA;.
010000E  7D 00 72 D5 83 F9 10 72 02 EB 0E BB 10 00 29 CB   }.r....r......).
010000B  E8 50 00 E8 4D 00 4B 75 F7 E8 4E 00 83 06 7F 00   .P..M.Ku..N.....
0100000  10 E9 47 FF B4 3E 8B 1E 7B 00 CD 21 EB 29 BA 00   ..G..>..{..!.)..
0100000  00 B4 09 CD 21 EB 20 BA 1D 00 B4 09 CD 21 BA 81   ....!. ......!..
0100001  00 B4 09 CD 21 EB 10 BA 31 00 B4 09 CD 21 BA 81   ....!...1....!..
0100001  00 B4 09 CD 21 EB 00 B8 00 4C CD 21 BA 62 00 E8   ....!....L.!.b..
0100008  24 00 C3 BA 65 00 E8 1D 00 C3 BA 47 00 E8 16 00   \$...e......G....
0100000  C3 BA 4A 00 E8 0F 00 C3 BA 4F 00 E8 08 00 C3 BA   ..J......O......
010000A  45 00 E8 01 00 C3 B4 09 CD 21 C3 31 FF C1 C2 04   E........!.1....
0100004  89 D6 83 E6 0F 8A 44 52 88 45 4A 47 49 75 EE C3   ......DR.EJGIu..
```

Since I set "di" register to data segment, I change the "stosw" a litte bit:
Code:
```      @@:
mov     [di], ax
```

If I cannot make it work, then I will just leave it as it. Thank you.
27 Jan 2023, 12:46
ProMiNick

Joined: 24 Mar 2012
Posts: 786
Location: Russian Federation, Sochi
ProMiNick 27 Jan 2023, 12:56
mov [di], cl - I force zero termination, maybe in DOS should be '\$'. by the way thou already type '\$' following _hexnum after 8 bytes. just clear mine termination.
27 Jan 2023, 12:56
macomics

Joined: 26 Jan 2021
Posts: 913
Location: Russia
macomics 27 Jan 2023, 14:49
FlierMate1 wrote:
Thanks to @macomics and @sinsi for their help in solving command-line arguments in DOS

Tomasz Grysztar determines the end of the parameter string by the carriage return symbol (CR = \$0D)
SOURCE/DOS/FASM.ASM:113-130
Code:
```get_params:
mov     [input_file],0
mov     [output_file],0
mov     [symbols_file],0
mov     [memory_setting],0
mov     [passes_limit],100
mov     [definitions_pointer],predefinitions
push    ds
mov     ds,[psp_segment]
mov     esi,81h
mov     edi,params
find_param:
lodsb
cmp     al,20h
je      find_param
cmp     al,'-'
je      option_param
cmp     al,0Dh    ```
27 Jan 2023, 14:49
FlierMate11

Joined: 13 Oct 2022
Posts: 94
FlierMate11 27 Jan 2023, 16:25
macomics wrote:
FlierMate1 wrote:
Thanks to @macomics and @sinsi for their help in solving command-line arguments in DOS

Tomasz Grysztar determines the end of the parameter string by the carriage return symbol (CR = \$0D)
SOURCE/DOS/FASM.ASM:113-130

Luckily I did also in my HexdumpD.asm above, I notice it too from random search on the Internet.

It works for me, yes, I think CR needs to be detected.

Below is my code modified from yours. Taken from my hexdumpd.asm:
Must put null-character also at the back of filename so that DOS interrupt AH=3dh can open ASCIIZ filename. But also put "\$" so that AH=9 can print it on screen.
Code:
```        movzx   cx, [es:CMD_LENGTH]
lea     di, [es:CMD_STRING]
lea     si, [_filename]
cmp     cx, 0
jz      err0
again:
mov     al, [es:di]
cmp     al, ' '
jnz     continue
inc     di
jmp     again
continue:
cmp     al, 13
jz      skip
mov     [si], al
inc     si
inc     di
loop    again
skip:
xor     al, al
mov     [si],al
inc     si
mov     al, '\$'
mov     [si], al
```
27 Jan 2023, 16:25
FlierMate2

Joined: 21 Mar 2023
Posts: 39
FlierMate2 04 Apr 2023, 10:45
I have successfully convert 32-bit integer to hex values with the help of a cyber-pal.

This is the code:
Code:
```;input: si - pointer to 32-bit integer
;output: _hexnum
ConvertLongHex:     Nice code snippet by angch (Ang Chin Han)
lea di, [_hexnum]
mov bx, 2
.loop3:
mov dx, word [si+2]
mov cx, 4   ; 4 hexgit per 16 bit word
push si
.loop1:
rol dx, 4
mov si, dx
and  si, 0000fh
mov al,[_digits+si]
mov [di],al
inc di
dec cx
jnz .loop1
pop si
sub si, 2 ; Next 16 bit word
dec bx
jnz .loop3
ret              ```

And the data segment:
Code:
```_offset   dd 0
_hexnum   rb 8
db '\$'
_digits   db '0123456789ABCDEF'      ```

My hexdump for DOS now fully operational with file larger than 64KB.

04 Apr 2023, 10:45
SeproMan

Joined: 11 Oct 2009
Posts: 69
Location: Belgium
SeproMan 10 Apr 2023, 20:11
I see that you have chosen to not use 32-bit registers in your ConvertLongHex subroutine. This decision of course is yours, and a good reason for doing so is to create an HEXDUMPD.EXE that can run on even the oldest of x86 architectures like 8086 or 80186. However, I did notice that your code is nonetheless using 32-bit operations and instructions that these old architectures don't support!

The MOVZX instruction was introduced with the 80386. You should replace 'movzx cx, [es:CMD_LENGTH]' by:

Code:
```xor   cx, cx
mov   cl, [es:CMD_LENGTH]    ```

FASM will encode the 'add [_offset], 16' instruction so it performs a 32-bit addition because you used DD to define _offset. You should write this as:
Code:
```add   word [_offset], 16
adc   word [_offset + 2], 0    ```

In ConvertLongHex and ConvertShortHex, the ROL instructions cannot rotate by an immediate count. You should use a count from the CL register. The following code snippets correct that problem. (I could not resist optimizing the code for speed ):

Code:
```; IN (si) OUT (di) MOD (al,bx,cl,si)
ConvertLongHex:
mov  cl, 4                ; CONST
mov  di, _hexnum + 8      ; Easier to fill from the end
.loop:
mov  bl, [si]             ; SI points at current byte in a dword
and  bx, 15
dec  di
mov  al, [_digits + bx]
mov  [di], al
mov  bl, [si]
shr  bl, cl
dec  di
mov  al, [_digits + bx]
mov  [di], al
inc  si
cmp  di, _hexnum
jne  .loop
ret

; IN (dl) OUT () MOD (ax,bx,cl)
ConvertShortHex:
mov  cl, 4                ; CONST
mov  bl, dl
and  bx, 15
mov  ah, [_digits + bx]
mov  bl, dl
shr  bl, cl
mov  al, [_digits + bx]
mov  [_hexval], ax
ret    ```

_________________
10 Apr 2023, 20:11
FlierMate2

Joined: 21 Mar 2023
Posts: 39
FlierMate2 11 Apr 2023, 07:50
SeproMan wrote:
I see that you have chosen to not use 32-bit registers in your ConvertLongHex subroutine. This decision of course is yours, and a good reason for doing so is to create an HEXDUMPD.EXE that can run on even the oldest of x86 architectures like 8086 or 80186. However, I did notice that your code is nonetheless using 32-bit operations and instructions that these old architectures don't support!

The MOVZX instruction was introduced with the 80386. You should replace 'movzx cx, [es:CMD_LENGTH]' by:

Code:
```xor   cx, cx
mov   cl, [es:CMD_LENGTH]    ```

Good eye! Thanks for your correction, this is a serious defect in my previous release of Hexdump for DOS, but fortunately I didn't promote it on DOS forum as it is not a real DOS program then.

I fixed it just now.

Quote:
...the ROL instructions cannot rotate by an immediate count.

From what I check, ROL with immediate value as argument is allowed starting from 80186.

For example,
Code:
` 66 c1 c2 04             rol    dx,0x4    `

As for your hex conversion routine, I will keep it for future reference (and it also serves as reference for other forum members here), I wish you posted a little earlier before I found the solution.
Thank you once again!
11 Apr 2023, 07:50
macomics

Joined: 26 Jan 2021
Posts: 913
Location: Russia
macomics 11 Apr 2023, 09:50
Here is another option, but now using xlat
Code:
```; IN (si) OUT (di) MOD (al,bx,cl,si)
ConvertLongHex:
mov  cl, 4                ; CONST
mov  di, _hexnum + 8      ; Easier to fill from the end
mov  bx, _digits
.loop:
lods byte [si]                 ; SI points at current byte in a dword
mov  ah, al
and  al, 15
shr  ah, cl
dec  di
xlat byte [bx]
mov  [di], al
dec  di
mov  al, ah
xlat byte [bx]
mov  [di], al
cmp  di, _hexnum
jne  .loop
ret

; IN (dl) OUT () MOD (ax,bx,cl)
ConvertShortHex:
mov  cl, 4                ; CONST
mov  bx, _digits
mov  al, dl
and  al, 15
shr  dl, cl
xlat byte [bx]
xchg al, ah
xlat byte [bx]
mov  [_hexval], ax
ret    ```
11 Apr 2023, 09:50
FlierMate2

Joined: 21 Mar 2023
Posts: 39
FlierMate2 14 Apr 2023, 07:33
Sorry for multiple version of HEXDUMPD.ASM, this latest 0.03 version is uploaded with patches suggested by SeproMan, basically the:

Code:
```xor   cx, cx
mov   cl, [es:CMD_LENGTH]     ```

...and...

Code:
```add   word [_offset], 16
adc   word [_offset + 2], 0        ```

Thanks SeproMan!

14 Apr 2023, 07:33
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 20132
revolution 14 Apr 2023, 07:44
I hope you aren't conflating DOS and 8086 instructions.

You can use DOS with 32-bit instructions. DOS can run on 32-bit machines. It can also run on 64-bit machines. Just that it runs in real mode. That doesn't limit the instructions to only 8086, or 16-bit. It does make using 64-bit registers tricky because you need to switch modes, but otherwise unless you really have a very very old 80[1|2]86 machine then 32-bit code will run fine.
14 Apr 2023, 07:44
FlierMate2

Joined: 21 Mar 2023
Posts: 39
FlierMate2 14 Apr 2023, 08:01
revolution wrote:
I hope you aren't conflating DOS and 8086 instructions.

You can use DOS with 32-bit instructions. DOS can run on 32-bit machines. It can also run on 64-bit machines. Just that it runs in real mode. That doesn't limit the instructions to only 8086, or 16-bit. It does make using 64-bit registers tricky because you need to switch modes, but otherwise unless you really have a very very old 80[1|2]86 machine then 32-bit code will run fine.

Thank you for the timely reminder, I almost confused between DOS and 8086 instructions.
However, I still believe a small number of people are still using ancient machine to run DOS, then this HEXDUMPD.EXE might be for them. But I heard DOS users mainly use DEBUG.EXE to perform hexdump....

revolution wrote:
But one thing is for sure, you don't need to use two registers if you are running the code on a 32-bit capable machine.

Aha, now I fully understand what you mean.
14 Apr 2023, 08:01
macomics

Joined: 26 Jan 2021
Posts: 913
Location: Russia
macomics 14 Apr 2023, 09:19
FlierMate2 wrote:
But I heard DOS users mainly use DEBUG.EXE to perform hexdump....

Now there is TD.EXE and DEBUGX.COM

Last edited by macomics on 08 Mar 2024, 09:44; edited 2 times in total
14 Apr 2023, 09:19
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First

 Jump to: Select a forum Official----------------AssemblyPeripheria General----------------MainTutorials and ExamplesDOSWindowsLinuxUnixMenuetOS Specific----------------MacroinstructionsOS ConstructionIDE DevelopmentProjects and IdeasNon-x86 architecturesHigh Level LanguagesProgramming Language DesignCompiler Internals Other----------------FeedbackHeapTest Area
Goto page 1, 2  Next

Forum Rules:
 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum