如何将表示带符号的十六进制int的字符串转换为80x86中的带符号int双字数字? [英] How do I convert a string representing a signed hex int into its signed int Doubleword number in 80x86?
问题描述
所以我参加了一门汇编语言课程,我从这本书中解决了这个问题:
使用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
然后,您执行 所以,上面的整个代码块应该是: 我还添加了 您不检查十六进制A ... F数字是否在范围内 A ... F ,只是它低于或等于F 。否则它与 编辑:更正 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代码块,见下面。
shl eax,4
有相同的错误。因为通常应该避免重复的代码,所以我添加了 shift_eax_by_4_and_add_bl
标签以最小化重复的代码。
$ b sub bl,31h
- > <$ c
$ b <$ p $ b>
TestForHexD:
cmp('A'-0Ah)
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屋!