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

Wie wandle ich eine Hexadezimalzahl (String) in eine Dezimalzahl (String) um?

Da man mit Strings nicht rechnen kann, muss die Hexadezimalzahl erst in das Computerformat (Dword) übertragen und daraus der Dezimalstring gebildet werden. Es handelt sich also um eine Kombination der Hex-Int-Umwandlung und der Int-Dez-Umwandlung.

Nasm
SEGMENT .data
    hex:  db "72 6B 68 62",0
SEGMENT .bss
    dezz:  resb 12              ; 11 Dezimalziffern + 1 Abschlussnull
SEGMENT .text
Hex2Dez:
    Hex2Dword:
        mov esi, hex            ; Vorgabe
        xor edx, edx            ; Ergebnis
    .Schleife:
        lodsb
        cmp al, '0'
        jb .Leerzeichen         ; keine Zahl, Leerzeichen ausprobieren
        cmp al, '9'
        ja .Majuskel            ; keine Zahl, Großbuchstaben ausprobieren
        and al, 0Fh
        shl edx, 4
        or dl, al
        jmp .Schleife
    .Leerzeichen:
        cmp al, 32
        je .Schleife
        jmp .Hex2IntEnde
    .Majuskel:
        cmp al, 'A'
        jb .Hex2IntEnde
        cmp al, 'F'
        ja .Minuskel            ; kein Großbuchstabe, Kleinbuchstaben ausprobieren
        sub al, 55
        shl edx, 4
        or dl, al
        jmp .Schleife
    .Minuskel:
        cmp al, 'a'
        jb .Hex2IntEnde
        cmp al, 'f'
        ja .Hex2IntEnde
        sub al, 87
        shl edx, 4
        or dl, al
        jmp .Schleife
    .Hex2IntEnde:                  ; Ergebnis in EDX

    Dword2Dez:
        mov eax, edx            ; Vorgabe
        mov edi, dezz           ; Ergebnis
        mov ebx, 10             ; Divisor
        xor ecx, ecx            ; ECX=0 (Anzahl der Ziffern)
    .Schleife_1:
        xor edx, edx
        div ebx                 ; EDX:EAX / EBX = EAX Rest EDX
        push dx                 ; LIFO
        add cl,1                ; ADD soll schneller sein als INC
        or  eax, eax            ; AX = 0?
        jnz .Schleife_1         ; nein: nochmal
    .Schleife_2:
        pop ax                  ; gepushte Ziffern zurückholen
        or al, 00110000b        ; Umwandlung in ASCII
        stosb                   ; Nur AL nach [EDI] (EDI ist ein Zeiger auf den String)
        loop .Schleife_2        ; bis keine Ziffern mehr da sind
        mov byte [edi], 0       ; ASCIIZ-Abschlussnull
    .Int2DezEnde:               ; Ergebnis in [dezz]

        ret

Ralph 'rkhb' Bauer Aug 2008