FAQ der Newsgroup de.comp.lang.assembler (d.c.l.a.)

Wie wandle ich ein Integer (Byte, Word etc.) in eine Hexadezimalzahl (String) um?

Wenn der Inhalt eines Registers eine Zahl repräsentiert, dann spricht das Intel-Manual allgemein von 'Integer', wobei die Größe und das Vorzeichen der Zahl keine Rolle spielen. Integer sind immer Binärzahlen, also eine lückenlose Folge von Nullen und Einsen (Bits). Um diese Zahlen gut darstellen zu können, bedient man sich des Hexadezimalsystems:

29282d = 111001001100010b = 7262h

Die kleinen Buchstaben hinter den Zahlen bezeichnen das Zahlensystem: d(ezimal), b(inär), h(exadezimal). Für die hexadezimale Zahl hat sich auch die Schreibweise 0x7262 (C/C++) eingebürgert. Es gibt auch &H7262 (Basic) und $7262 (Pascal). Die hexadezimale Schreibweise dient ausschließlich dem Zweck der besseren Darstellung.

DezimalBinärHexadezimalAnmerkungen
00 0 0 0 0 Eine einzelne Binärziffer (0 oder 1) nennt man Bit. Eine Gruppe von 4 Bits nennt man Nibble.

In x86-Prozessoren sind die Register 8, 16, 32 oder 64 Bits breit, also immer Vielfaches von 4. Mit 4 Bits kann man 16 Zahlen darstellen: 0-15. Damit man auch für die Zahlen 10-15 eine einstellige Zahl verwenden kann, ersetzt man sie durch Buchstaben 'A' bis 'F'.

Jede Integerzahl kann durch eine jeweils immer gleiche Anzahl von Nibbles dargestellt werden. Es ist deshalb einfach, die verschiedenen Integerformate so darzustellen, dass auf einen Blick die darin enthaltenen anderen Formate sichtbar sind. Beispiel:
    eax = 726B6862 (4 Bytes = 8 Nibbles)
     ax =     6862 (2 Bytes = 4 Nibbles)
     ah =     68   (1 Byte  = 2 Nibbles)
     al =       62 (1 Byte  = 2 Nibbles)
10 0 0 1 1
20 0 1 0 2
30 0 1 1 3
40 1 0 0 4
50 1 0 1 5
60 1 1 0 6
70 1 1 1 7
81 0 0 0 8
91 0 0 1 9
101 0 1 0 A
111 0 1 1 B
121 1 0 0 C
131 1 0 1 D
141 1 1 0 E
151 1 1 1 F

In der ASCII-Tabelle stehen zwischen '9' und 'A' noch andere Buchstaben, so dass eine einfache lineare Übertragung nicht möglich ist. Zwei Methoden gibt es für die Umwandlung, die im folgenden in Nasm-Schreibweise dargestellt werden.

Aufgabe: Umwandlung von 1919641698d in Hexadezimal

Methode 1 (Tabelle):

    BITS 32
    SECTION .data
        zahl:     dd 1919641698
        htab:     db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
        ergebnis: db "xxxxxxxx",0    ; 8 Buchstaben + Abschlussnull

    SECTION .text
      Int2Hex:
        mov edx, [zahl]      ; EDX, EBX, EDI können auch Funktionsargumente sein
        mov ebx, htab        ; Zeiger auf Umwandlungstabelle
        mov edi, ergebnis    ; Zeiger auf Ergebnispuffer
        mov ecx, 8
      Schleife:
        shld eax, edx, 4     ; vorderstes Nibble von EDX nach EAX
        shl edx, 4
        and al, 0Fh          ; vorderes Nibble (Altlast) löschen
        xlatb                ; AL = ascii(AL)
        stosb
        loop Schleife
        mov byte [edi], 0    ; Abschlussnull
        ret

Danach steht in 'ergebnis' die Hexadezimalzahl.

Methode 2 (Fehlerkorrektur):

    BITS 32
    SECTION .data
        zahl:  dd 1919641698
        ergebnis: db "xxxxxxxx",0
    SECTION .text
      Int2Hex:
        mov edx, [zahl]      ; EDX und EDI können auch Funktionsargumente sein
        mov edi, ergebnis    ; Zeiger auf Ergebnispuffer
        mov ecx, 8
      Schleife:
        shld eax, edx, 4     ; vorderstes Nibble von EDX nach EAX
        shl edx, 4
        and al, 0Fh          ; vorderes Nibble (Altlast) löschen
        or al, 30h           ; ASCII
        cmp al, '9'
        jbe J1               ; Ergebnis <= '9'
        add al, 7            ; auf die richtige Stelle in der ASCII-Tabelle korrigieren
      J1:
        stosb
        loop Schleife
        mov byte [edi], 0    ; Abschlussnull
        ret

Danach steht in 'ergebnis' die Hexadezimalzahl.

Ralph 'rkhb' Bauer 05.08.2008