Assembly 如何将负整数转换为字符串并在MASM汇编中输出
我应该从用户那里获取带符号的整数,计算输入的数字之和,然后显示平均值。问题是,负数似乎没有正确显示,尽管我知道总和和平均数的计算是正确的 我需要在我的程序中添加什么来解释负数,以便正确显示负数Assembly 如何将负整数转换为字符串并在MASM汇编中输出,assembly,x86,masm,signed-integer,Assembly,X86,Masm,Signed Integer,我应该从用户那里获取带符号的整数,计算输入的数字之和,然后显示平均值。问题是,负数似乎没有正确显示,尽管我知道总和和平均数的计算是正确的 我需要在我的程序中添加什么来解释负数,以便正确显示负数 . . . writeVal PROC USES eax LOCAL resultString[11]:BYTE lea eax, resultString push eax push [ebp + 8] call intToStr
.
.
.
writeVal PROC USES eax
LOCAL resultString[11]:BYTE
lea eax, resultString
push eax
push [ebp + 8]
call intToStr
lea eax, resultString
displayString eax ; print num
ret 4
writeVal ENDP
intToStr PROC USES eax ebx ecx
LOCAL tempChar:DWORD
mov eax, [ebp + 8]
mov ebx, 10
mov ecx, 0
cld
divideByTen:
cdq
idiv ebx
push edx
inc ecx
cmp eax, 0
jne divideByTen
mov edi, [ebp + 12] ; move into dest array
jmp storeChar
;store char in array
storeChar:
pop tempChar
mov al, BYTE PTR tempChar
add al, 48
stosb
loop storeChar
mov al, 0
stosb
ret 8
intToStr ENDP
.
.
.
如果输入为负数,则将该事实记录在某个地方(在寄存器中)并
neg
输入号码。(例如,测试eax,eax
/jnl
跳过一个不小于-0的块,否则落入处理该情况的块。)
然后以正常方式将无符号int->string转换(使用div
而不是idiv
)到缓冲区中
如果使用push/pop策略反转数字,可以将'-'
放入缓冲区,并立即递增指针。否则,如果要以最不重要的一级顺序存储数字,从缓冲区的末尾开始并递减指针(如中),请等到结尾处,在前面加上一个'-'
使用无符号处理最负整数的角大小写
-2147483648
,位模式0x8000000
。它的绝对值不能表示为32位2的补码正整数,只能表示为32位无符号。您只需检查数字是否小于零,然后使用指令对其求反,并将负号-
应用于结果字符串
缓冲区:
writeVal
的代码为:
编译并运行:
将打印:
欢迎来到Stackoverflow。请阅读。你为什么要从你的问题中删除ASM代码?请检查我下面的答案,并让我知道它是否对你有效。你通过重做LEA和使用stos使你的if身体过于复杂。只需
mov字节ptr[eax],'-'
inceax
在neg ebx
之前或之后,就像我在回答中建议的那样。但使用ECX或EDX代替EBX;EBX在标准调用约定中保留调用。(电子数据交换也是如此)。在不保存/恢复它们的情况下不要修改它们。@PeterCordes完成,谢谢。我有超过15年的时间来编写MASM,而像这样的重要细节都被模糊了!我在看到你的答案之前就想到了这个。如果我看过的话,我不会犹豫的。谢谢你写了一些详细的代码。我知道真实的例子对初学者很有帮助,但有时我会跳过这一级别的努力/细节,去做一些看起来很琐碎的事情,以便在脑海中描绘代码。请注意,如果您正在调用OP的intToStr
函数I,当该函数将其视为已签名时,此包装器将无法正确处理0x8000000
,该函数在neg
之后“仍然为负”。为什么neg
无法处理0x8000000
?我实际上按下了-2143123456
,它是0x80428800
,程序打印了-2143123456
。使用-2147483647
(0x8000001
)仍打印-2147483647
。我使用旧的ml
编译它,Microsoft(R)宏汇编程序版本6.14.8444
neg
确实“正确”地处理了它,但最负数是2的补码的特例。e、 g.-128
在8位2的补码中是它自己的2的补码逆。i、 e.它溢出回到签名时的-128。因此,在这种情况下,应将结果视为未签名。如果将其传递给使用cdq/idiv进行签名除法10的函数,则不会执行此操作xor edx,edx
/div
可以,甚至可以xor edx,edx
/idiv
进行零扩展,然后使用两个非负输入进行64/32=>32位有符号除法。
writeVal PROC USES eax ecx edi
LOCAL resultString[11]:BYTE
lea eax, resultString
mov ecx, [ebp + 8] ; load passed number to ebx
test ecx, ecx ; test number to see if it's less than zero
jnl non_negative ; jump if not less to non_negative
neg ecx ; else we have a negative number so neg to make it positive
mov byte ptr [eax], '-' ; set resultString[0] to '-'
inc eax ; increase resultString ptr + 1
non_negative:
push eax ; push the resultString + 1
push ecx ; push the number
call intToStr ; convert the number
lea eax, resultString
printc eax ; print num
ret 4
writeVal ENDP
start:
push -14286754
call writeVal
exit
end start
-14286754