如何将表示带符号的十六进制int的字符串转换为80x86中的带符号int双字数字? [英] How do I convert a string representing a signed hex int into its signed int Doubleword number in 80x86?

查看:272
本文介绍了如何将表示带符号的十六进制int的字符串转换为80x86中的带符号int双字数字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我参加了一门汇编语言课程,我从这本书中解决了这个问题:
使用windows 32控制台(所以我有一个 io.h 使用),我应该接受用户输入的有效十六进制值,然后在寄存器 EAX 中显示实际的十六进制值。因此,如果用户输入AB CD E2 18,那么在 EAX 过程之后将保存值: ABCDE218
我坚持的部分是 A - F 值。例如,如果我使用 A ,我可以读取 00000010 ,但我不知道如何将其更改为其十六进制值 A 。这是我到目前为止:

  .586 
.MODEL FLAT
.CODE

hexToInt PROC
push ebp;保存基指针
mov ebp,esp;建立栈帧
sub esp,4;本地空间签署
推ebx;保存寄存器
按edx
按esi
pushfd;保存标志

mov esi,[ebp + 8]; get参数(源地址)

WhileBlankD:
cmp BYTE PTR [esi],'';空间?
jne EndWhileBlankD;如果不是
inc esi,则退出;增加字符指针
jmp WhileBlankD;并再试一次
EndWhileBlankD:

mov eax,1;默认符号乘数
IfPlusD:cmp BYTE PTR [esi],'+';领先+?
je SkipSignD;如果是,跳过
ifMinusD:
cmp BYTE PTR [esi],' - ';领导 - ?
jne EndIfSignD;如果不是,则保存默认值+
mov eax,-1; -1为减号
SkipSignD:
inc esi;移过标志
EndIfSignD:

mov [ebp-4],eax;保存符号乘数
mov eax,0;数字被累加

WhileDigitD:
cmp BYTE PTR [esi],'0';将下一个字符与'0'比较
jb EndWhileDigitD;如果小于'0',则不是数字
cmp BYTE PTR [esi],'9';与'9'比较
ja TestForHexD
mov bl,[esi]; ASCII字符为BL
和ebx,0000000Fh;转换为单位整数
和eax,ebx
shl eax,4
inc esi
jmp WhileDigitD
TestForHexD:
cmp BYTE PTR [esi] ,'F'
ja EndWhileDigitD
mov bl,[esi]
sub bl,31h
和ebx,000000FFh
或al,bl
shl eax ,4
inc esi;增量字符指针
jmp WhileDigitD;去尝试下一个字符
EndWhileDigitD:

;如果值是< 80000000h,乘以符号
cmp eax,80000000h; 80000000H?
jnb endIfMaxD;如果没有,则跳过
imul DWORD PTR [ebp-4];使签署的号码
endIfMaxD:

popfd;恢复标志
pop esi;恢复寄存器
pop edx
pop ebx
mov esp,ebp;删除局部变量空间
pop ebp
ret;退出
hexToInt ENDP

END



TestForHex 标签是我试图将ASCII字符串转换为十六进制的地方。我四处张望,看到我可以通过转移和掩饰完成我的目标,但我无法弄清楚,也找不到任何例子。在这一点上,我确信它的东西非常小,我只是在看,但我被卡住了。

解决方案

首先,在 0 ... 9 字符串到整数转换代码中,您不需要执行ASCII转换为二进制转换你应该这样做,但是你做和ebx,0Fh ,这是不正确的。您需要从每个ASCII字符中减去'0' 30h ),如下所示:

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

然后,也在 0 ... 9 字符串转换为整数转换代码:

 
和eax,ebx

如果数字包含只有0到9位数字,和eax,ebx 总是会产生0.应该是:

 
或al,bl

然后,您执行 shl eax,4 ,即使你不知道是否会有更多数字。这意味着该数字将比它应该大16倍。然后,您给示例输入空格,但您的代码不处理空格( 20h ),它会结束阅读输入,查看低于'0'( 30h ),它似乎只接受前导空格(如果你不想接受它们之间的空格,就跳过这个)。

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

 
WhileDigitD:
cmp byte ptr [esi],'';如果你不想在两者之间有空格,请删除它。
je next_char;如果你不想在两者之间有空格,请删除它。
cmp BYTE PTR [esi],'0';将下一个字符与'0'比较
jb EndWhileDigitD;如果小于'0',则不是数字
cmp BYTE PTR [esi],'9';与'9'比较
ja TestForHexD
mov bl,[esi]; ASCII字符到BL

sub bl,'0'; sub bl,30h - >将ASCII转换为二进制。

shift_eax_by_4_and_add_bl:
shl eax,4;将当前值4位移到左边。
或al,bl;添加当前数字的值。

next_char:
inc esi
jmp WhileDigitD

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

您不检查十六进制A ... F数字是否在范围内 A ... F ,只是它低于或等于F 。否则它与 shl eax,4 有相同的错误。因为通常应该避免重复的代码,所以我添加了 shift_eax_by_4_and_add_bl 标签以最小化重复的代码。

所以我认为它应该是:
$ b

编辑:更正 sub bl,31h - > <$ c
$ b <$ p $ b>
TestForHexD:
cmp('A'-0Ah)

'BY'PTR [esi],'A'
jb EndWhileDigitD
cmp BYTE PTR [esi],'F'
ja EndWhileDigitD
mov bl,[esi]
sub bl,('A'-0Ah); sub bl,55 - >将ASCII转换为二进制。
jmp shift_eax_by_4_and_add_bl


So I am taking an assembly language course and I am stuck on this problem from the book: Using the windows 32 console (so I have an io.h to use), I am supposed to take a valid hex value inputted by the user and then display the actual hex value in the register EAX. So if the user entered "AB CD E2 18", then after the procedure EAX would hold the value: ABCDE218. The parts that I am stuck on are the A-F values. If I use A for example, I can get the bits to read 00000010, but I don't know how to change that into its hex value A. Here is what I have so far:

.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

The TestForHex label is where I am trying to convert the ASCII string to hex. I was looking around and read that I could accomplish my goal by shifting and masking, but I can't figure it out and I can't find any examples. At this point I am sure its something really small that I am just over looking, but I am stuck.

解决方案

There are some bugs in your code.

First, in 0 ... 9 string to integer conversion code, you don't do ASCII to binary conversion as you should do, but instead you do and ebx,0Fh, which is incorrect. You need to subtract '0' (30h) from each ASCII character, like this:

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

Then, also in 0 ... 9 string to integer conversion code:

and    eax, ebx

If the number consists of only 0...9 digits, and eax, ebx will produce always 0. It should be:

or al,bl

Then, you do shl eax,4, even if you don't know if there will be more digits. That means that the number will be 16 times bigger than it should.

Then, you give the example input with spaces, but your code does not handle spaces (20h) properly, it ends reading input for any value below '0' (30h), it seems to accept only leading spaces (skip this if you don't want to accept spaces in between).

So, the entire code block above should be:

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

I also added labels next_char and shift_eax_by_4_and_add_bl. The reason for next_char should be evident, shift_eax_by_4_and_add_bl is to minimize duplicate code of 0...9 and A...F code blocks, see below.

You don't check that that the hexadecimal A...F digit is within range A ... F, only that it's below or equal to F. Otherwise it has same bug with shl eax,4. And as usually duplicate code should be avoided, I added shift_eax_by_4_and_add_bl label to minimize duplicate code.

So I think it should be:

Edit: corrected 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

这篇关于如何将表示带符号的十六进制int的字符串转换为80x86中的带符号int双字数字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆