如何转换代表签署廉政十六进制字符串转换成它的符号整数双字号码中的80x86?(How do I co

2019-08-31 08:14发布

所以,我正在汇编语言课程,我被困在这书上的问题:使用32位的Windows控制台(所以我有一个io.h使用),我应该采取由用户输入一个有效的十六进制值,然后显示在所述寄存器中的实际十六进制值EAX 。 因此,如果用户输入“AB CD E2 18”,然后在手术后EAX将持有的价值: ABCDE218 。 我是粘在部件是A - F值。 如果我使用A例如,我可以得到位读取00000010 ,但我不知道如何更改成其十六进制值A 。 这是我到目前为止有:

.586
.MODEL FLAT
.CODE

hexToInt    PROC
        push   ebp                 ; save base pointer
        mov    ebp, esp            ; establish stack frame
        sub    esp, 4              ; local space for sign
        push   ebx                 ; Save registers
        push   edx
        push   esi
        pushfd                     ; save flags

        mov    esi,[ebp+8]         ; get parameter (source addr)

WhileBlankD:
        cmp    BYTE PTR [esi],' '  ; space?
        jne    EndWhileBlankD      ; exit if not
        inc    esi                 ; increment character pointer
        jmp    WhileBlankD         ; and try again
EndWhileBlankD:

        mov    eax,1               ; default sign multiplier
IfPlusD:cmp    BYTE PTR [esi],'+'  ; leading + ?
        je     SkipSignD           ; if so, skip over
IfMinusD:
        cmp    BYTE PTR [esi],'-'  ; leading - ?
        jne    EndIfSignD          ; if not, save default +
        mov    eax,-1              ; -1 for minus sign
SkipSignD:
        inc    esi                 ; move past sign
EndIfSignD:

        mov    [ebp-4],eax         ; save sign multiplier
        mov    eax,0               ; number being accumulated

WhileDigitD:
        cmp    BYTE PTR [esi],'0'  ; compare next character to '0'
        jb     EndWhileDigitD      ; not a digit if smaller than '0'
        cmp    BYTE PTR [esi],'9'  ; compare to '9'
        ja     TestForHexD      
        mov    bl,[esi]            ; ASCII character to BL
        and    ebx,0000000Fh       ; convert to single-digit integer
        and    eax, ebx
        shl    eax, 4
        inc    esi
        jmp    WhileDigitD
TestForHexD:
        cmp    BYTE PTR [esi], 'F'
        ja     EndWhileDigitD
        mov    bl, [esi]
        sub    bl, 31h
        and    ebx, 000000FFh
        or     al, bl
        shl    eax, 4
        inc    esi                 ; increment character pointer
        jmp    WhileDigitD         ; go try next character
EndWhileDigitD:

; if value is < 80000000h, multiply by sign
        cmp    eax,80000000h       ; 80000000h?
        jnb    endIfMaxD           ; skip if not
        imul   DWORD PTR [ebp-4]   ; make signed number
endIfMaxD:

        popfd                      ; restore flags
        pop    esi                 ; restore registers
        pop    edx
        pop    ebx
        mov    esp, ebp            ; delete local variable space
        pop    ebp 
        ret                        ; exit
hexToInt    ENDP

        END

TestForHex标签就是我想要的ASCII字符串为十六进制转换。 我环顾四周,阅读,我可以通过移动和掩蔽实现我的目标,但我无法弄清楚,我无法找到任何的例子。 在这一点上,我相信它的东西真的不多,我只是找过,但我坚持。

Answer 1:

有在你的代码的一些错误。

首先,在0到9的字符串整数转换代码,你不这样做ASCII到二进制的转换,你应该做的,而是你做的and ebx,0Fh ,这是不正确。 你需要减去'0'30h )从每个ASCII字符,就像这样:

mov bl,[esi]
sub bl,'0' ; sub bl,30h

然后,也是在0到9的字符串整数转换代码:

and    eax, ebx

如果数字只包括0〜9个数字, and eax, ebx总是会产生0。它应该是:

or al,bl

然后,你做shl eax,4 ,即使你不知道会不会有更多的数字。 这意味着,数量会比它应该大16倍。

然后,你给用空格输入的例子,但你的代码不处理空间( 20h )正确,它结束读取输入下面的任何值'0'30h如果您还没有),它似乎只接受开头的空格(跳过此“不想接受空格之间)。

所以,上面的整个代码块应该是:

WhileDigitD:
        cmp    byte ptr [esi], ' ' ; delete this if you don't want spaces in between.
        je     next_char           ; delete this if you don't want spaces in between.
        cmp    BYTE PTR [esi],'0'  ; compare next character to '0'
        jb     EndWhileDigitD      ; not a digit if smaller than '0'
        cmp    BYTE PTR [esi],'9'  ; compare to '9'
        ja     TestForHexD      
        mov    bl,[esi]            ; ASCII character to BL

        sub    bl,'0'              ; sub bl,30h -> convert ASCII to binary.

shift_eax_by_4_and_add_bl:
        shl    eax,4               ; shift the current value 4 bits to left.
        or     al,bl               ; add the value of the current digit.

next_char:
        inc    esi
        jmp    WhileDigitD

我还添加了标签next_charshift_eax_by_4_and_add_bl 。 原因next_char应该是很明显, shift_eax_by_4_and_add_bl是最小化的0〜9和A重复代码... F代码块,见下文。

你不检查的十六进制A ... F位在这个范围内A ... F,只知道它是低于或等于F。 否则,它有同样的bug shl eax,4 。 而作为一般的重复代码应该避免,我添加shift_eax_by_4_and_add_bl标签,以尽量减少重复的代码。

所以,我觉得应该是:

编辑:校正sub bl,31h - > sub bl,('A'-0Ah)

TestForHexD:
        cmp    BYTE PTR [esi], 'A'
        jb     EndWhileDigitD
        cmp    BYTE PTR [esi], 'F'
        ja     EndWhileDigitD
        mov    bl,[esi]
        sub    bl,('A'-0Ah)         ; sub bl,55 -> convert ASCII to binary.
        jmp    shift_eax_by_4_and_add_bl


Answer 2:

如果你需要转换的字符(为简单起见,假设,以大写字母),表示一个十六进制数字成数字,你需要做到这一点的价值:

IF char >= 'A'
  value = char - 'A' + 10
ELSE
  value = char - '0'
ENDIF

如果你需要做相反的,你做相反的:

IF value >= 10
  char = value - 10 + 'A'
ELSE
  char = value + '0'
ENDIF

在这里,你利用的事实是ASCII字符09已经连续ASCII码等做了ASCII字符A通过F



文章来源: How do I convert a string representing a signed hex int into its signed int Doubleword number in 80x86?