Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何将负整数转换为字符串并在MASM汇编中输出_Assembly_X86_Masm_Signed Integer - Fatal编程技术网

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