2

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

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

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

这是我需要帮助的地方。我做了一些研究,发现 2's 恭维是一个解决方案,但我不确定在我的代码中实现它。

如果有人可以帮助我,我将不胜感激!

包括 Irvine32.inc
; ((A + B) / C) * ((D - A) + E)
。数据
valA dword 1
valB dword 2
valC dword 3
valD dword 4
值 dword 5

。代码
主进程

    mov ecx, valA
    添加 ecx, valB
    mov edx, valC
    叫除法
    mov ecx, eax
    mov edx, valD
    子 edx, valA
    添加 edx, valE
    调用乘法

    出口

主要ENDP

*除法和乘法程序分别除法和乘法。

4

2 回答 2

2

欧文的WriteDec应该被替换为WriteInt将参数处理EAX为有符号数。

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

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

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

这是一个带有WriteInt,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

    call WriteInt           ; Write a positive or negative 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

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

示例WriteDec,IDIVIMUL:

; ((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

这是一个无需跳转即可获得EAX绝对值的算法:

cdq
xor eax, edx
sub eax, edx
于 2015-12-26T10:24:43.487 回答
1

在二进制补码机器上,有符号addsub无符号数量的操作实际上是相同的,因此程序的这些部分不需要更改。有符号除法和乘法有特定的说明,因此请确保函数使用这些(或直接使用它们)。

于 2013-11-10T05:27:47.873 回答