Assembly MASM Dealing with Negative Integers

前端 未结 2 884
孤独总比滥情好
孤独总比滥情好 2021-01-22 02:31

I was instructed to write a program in assembly that will carry out the following arithmetic:

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

I\'ve succeeded in doing this when n

相关标签:
2条回答
  • 2021-01-22 02:45

    Irvines's WriteDec should be replaced by WriteInt which handles the argument EAX as signed number.

    Inside the CPU, the negative "-2" and the positive "4294967294" are transformed to the same value: 0xFFFFFFFE. DIV performs the division 6/-2 positively (6/4294967294) and gets the result 0 = 0x00000000, with IDIV the result is correct: -3 = 0xFFFFFFFD.

    MUL and IMUL differ in the high part of the result (EDX). Since the high part is not needed in this case, it is not mandatory to use IMUL.

    There are no different versions of ADD and SUB for signed and unsigned numbers. This was the main reason for introducing the 2's complement coding. It's just a thing of interpretation: if the programmer decides that this should be a signed number, then it is a signed number. If he/she/it decides that this is an unsigned number, then it is an unsigned number. The CPU doesn't care about such things - the results will be always the same.

    Here's an example with WriteInt, IDIV and 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
    

    A 2's complement calculation is needed to get the absolute value of the number. E.g. the representation of -2 has two parts: a sign ('-') and an absolute value ('2'). A simple way to get the absolute value is to look at the sign bit, the leftmost bit of the number, and to jump appropriate. The calculation itself is performed just by NEG.

    Example with WriteDec, IDIV and 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
    

    Here is an algorithm to get the absolute value of EAX without jump:

    cdq
    xor eax, edx
    sub eax, edx
    
    0 讨论(0)
  • 2021-01-22 03:10

    On a twos complement machine, add and sub operations are actually the same for signed and unsigned quantities, so those parts of your program don't need to change. There are specific instructions for signed division and multiplication, so make sure the functions use those (or just use them directly).

    0 讨论(0)
提交回复
热议问题