Assembly 处理负整数的汇编MASM

Assembly 处理负整数的汇编MASM,assembly,x86,masm,twos-complement,irvine32,Assembly,X86,Masm,Twos Complement,Irvine32,我被指示在汇编中编写一个程序,该程序将执行以下算术: ((A+B)/C)*((D-A)+E) 当没有负值起作用时,我成功地做到了这一点,但是假设A=5,B=4,C=3,D=2,E=1。这给了我们((5+4)/3)*((2-5)+1)或-6 这就是我需要帮助的地方。我做了一些研究,发现2的补充是一个解决方案,但我不确定是否能在我的代码中实现它 如果有人能帮助我,我将非常感激 INCLUDE Irvine32.inc ; ((A + B) / C) * ((D - A) + E) .data val

我被指示在汇编中编写一个程序,该程序将执行以下算术:

((A+B)/C)*((D-A)+E)

当没有负值起作用时,我成功地做到了这一点,但是假设A=5,B=4,C=3,D=2,E=1。这给了我们((5+4)/3)*((2-5)+1)或-6

这就是我需要帮助的地方。我做了一些研究,发现2的补充是一个解决方案,但我不确定是否能在我的代码中实现它

如果有人能帮助我,我将非常感激

INCLUDE Irvine32.inc ; ((A + B) / C) * ((D - A) + E) .data valA dword 1 valB dword 2 valC dword 3 valD dword 4 valE dword 5 .code main PROC mov ecx, valA add ecx, valB mov edx, valC call Divide mov ecx, eax mov edx, valD sub edx, valA add edx, valE call Multiply exit main ENDP 包括Irvine32.inc ; ((A+B)/C)*((D-A)+E) .数据 瓦拉·德沃德1号 瓦尔布·德沃德2号 瓦尔克德沃德3 瓦尔德沃德4 淡水河谷德沃德5号 .代码 主进程 莫夫埃克斯,瓦拉 添加ecx,valB mov edx,valC 调用Divide mov-ecx,eax 莫夫·埃德克斯,瓦尔德 瓦拉分电能谱 加edx,淡水河谷 呼叫倍增 出口 主端
*除法和乘法程序分别进行除法和乘法

在twos补码机上,
add
sub
操作对于有符号量和无符号量实际上是相同的,因此程序的这些部分不需要更改。有关于有符号除法和乘法的特定指令,因此请确保函数使用这些指令(或直接使用它们)。

Irvine的指令应替换为将参数
EAX
作为有符号数处理的指令

在CPU内部,负“-2”和正“4294967294”被转换为相同的值:0xFFFFFE。积极执行除法6/-2(6/4294967294),并获得结果0=0x00000000,结果正确:-3=0xFFFFFFFD

结果的高部分不同(
EDX
)。由于在这种情况下不需要高部分,因此不强制使用

有符号和无符号数字的和没有不同的版本。这是引入2的补码编码的主要原因。这只是一个解释:如果程序员决定这应该是一个有符号的数字,那么它就是一个有符号的数字。如果他/她/它决定这是一个无符号数字,那么它就是一个无符号数字。CPU不关心这些事情——结果总是一样的

下面是一个示例,其中包含,和:

需要进行2的补码计算,以获得数字的绝对值。例如,-2的表示有两部分:符号('-')和绝对值('2')。获取绝对值的一个简单方法是查看符号位,即数字最左边的位,然后进行适当的跳转。计算本身仅由执行

例如,和:

下面是一个无跳跃获取EAX绝对值的算法:

cdq
xor eax, edx
sub eax, edx

您不需要实现2的补码。处理器已经用这种方式处理了数据的负数。你检查了最终结果了吗?是0xFFFFFA吗?如果是这样,那就是-6.我同意。DIV和MUL没有那么复杂的指令,IDIV和IMUL(签名的对应项)也没有那么复杂,并且可以避免(我觉得模棱两可)调用神秘代码。也许,
Divide
Multiply
正在使用DIV和MUL而不是IDIV和IMUL。
; ((A + B) / C) * ((D - A) + E)
INCLUDE Irvine32.inc

.DATA
valA dword 5
valB dword 4
valC dword 3
valD dword 2
valE dword 1

.CODE
main PROC
    mov ecx, valA
    add ecx, valB
    mov edx, valC
    call Divide

    mov ecx, eax
    mov edx, valD
    sub edx, valA
    add edx, valE
    call Multiply

    test eax, eax           ; Set the flags according to (EAX AND EAX)
    jns J1                  ; Skip the next block if EAX is positive (no sign)

        ; EAX is negative
        push eax            ; Preserve EAX
        mov al, '-'         ; Write the letter '-'
        call WriteChar      ; http://programming.msjc.edu/asm/help/index.html?page=source%2Firvinelib%2Fwritechar.htm
        pop eax             ; Restore EAX
        neg eax             ; 2's complement

    J1:
    call WriteDec           ; Write EAX as positive number

    exit
main ENDP

Divide PROC USES ECX EDX    ; EAX = ECX / EDX
    mov eax, ecx
    mov ecx, edx
    xor edx, edx
    idiv ecx                ; signed division, e.g 6/-3 = -2
    ret
Divide ENDP

Multiply PROC USES ECX EDX  ; EAX = ECX * EDX
    mov eax, edx
    imul ecx                ; signed multiplication
    ret
Multiply ENDP

END main
cdq
xor eax, edx
sub eax, edx