8086汇编的32位计算器

32 bit Calculator in 8086 Assembly

32 位计算器

谁能帮我用 MASM32 中的 32 位计算器。我认为加法和减法都可以,但我不能打印十进制数;

0002FFFF - 10005 = 1fffa

内存中:0001 0FFFA

打印:165530(十进制)

DATA_HERE     SEGMENT       

    mult1 dw 0002H
          dw 0FFFFH
    mult2 dw 0001H
          dw 0005H
    ans   dw 0,0

DATA_HERE    ENDS

STACK_HERE     SEGMENT STACK
    DW 40 DUP(0)
STACK_HERE    ENDS

CODE_HERE    SEGMENT
    ASSUME CS:CODE_HERE, DS:DATA_HERE, SS: STACK_HERE

INICIO:
MOV AX,DATA_HERE
MOV DS,AX   

ADD:

MOV AX,mult1+2 ; take lower 16-bit of NUM1; take 
ADD AX,mult2+2 ; AX = AX + lower 16-bit of NUM2
MOV ans+2,AX ; Store lower 16-bit result at ans

MOV AX,mult1 ; take higher 16-bit of NUM1 in AX; 
ADC AX,mult2 ; AX = AX + NUM2 + CF (add with carry)
MOV ans,AX ; Store higher 16-bit result at ans


SUBTRACT:


MOV AX,mult1+2 ; take lower 16-bit of NUM1 in AX ; 
SUB AX,mult2+2 ; AX = AX - lower 16-bit of NUM2
MOV ans+2,AX ; Store lower 16-bit result at ans

MOV AX,mult1 ; take higher 16-bit of NUM1 in AX; 
SUB AX,mult2 ; AX = AX - NUM2
MOV ans,AX ; Store higher 16-bit result at ans

xor si,si
mov si,0   

ciclo:        
   mov AX, ans[si];          
   call display ; print AX
   add si, 2

cmp si, 2
JLE ciclo

mov ax,4C00h
int 21h        

display   proc  
  ;push CX     
  ;Beginning of procedure
  MOV BX, 10     ;Initializes divisor
  ;MOV DX, 0000H    ;Clears DX
  MOV CX, 0000H    ;Clears CX
      ;Splitting process starts here
.Dloop1:  
   MOV DX, 0000H    ;Clears DX during jump
   DIV BX      ;Divides AX by BX
   PUSH DX     ;Pushes DX(remainder) to stack
   INC CX      ;Increments counter to track the number of digits
   CMP AX, 0     ;Checks if there is still something in AX to divide
   JNE .Dloop1     ;Jumps if AX is not zero

.Dloop2:  POP DX      ;Pops from stack to DX
   ADD DX, 30H     ;Converts to it's ASCII equivalent
   MOV AH, 02H     
   INT 21H      ;calls DOS to display character
LOOP .Dloop2    ;Loops till CX equals zero

   ;pop CX
   RET       ;returns control
display  ENDP



CODE_HERE    ENDS
END INICIO

您首先将低 16 位打印为十进制 FFFA -> 65530 和第二个字中的 1。

1 65530。

如果您有 32 位处理器,您可以使用 EAX/EDX 寄存器执行除法。

不然就更复杂了。然后你必须模拟一个 32 位除法。那可不好玩 ;-)。

这里有一个提示:http://en.wikipedia.org/wiki/Division_algorithm(是的,你必须处理位)

如果您编写一个 C 程序将 long 值除以 10L,为您的处理器(16 位)编译它并分解输出,您可以看到他们是如何做到的。这只是一个想法。我自己没有尝试过。您必须确保您的 long 值足够大,以便编译器没有机会进行优化。 ;-)

接下来的代码,用EMU8086做的,在两个分开的字中得到一个32位的数字,然后都转换成字符串。该代码使用最大的 32 位数字 0FFFF FFFFh,您可以将其更改为任何其他数字,从 0 到 FFFF FFFFh,它将起作用(注释将帮助您理解代码中发生的事情):

.model small

.stack 100h

.data

num_low dw ?                 ;32 BIT
num_hig dw ?                 ;NUMBER.
buf     db 12 dup('$')       ;NUMBER CONVERTED TO STRING.

.code
start:

;INITIALIZE DATA SEGMENT.
  mov  ax, @data
  mov  ds, ax

;STORE BIG 32 BIT NUMBER = 4294967295 = 0FFFF FFFFh.
  mov  num_low, 0FFFFh
  mov  num_hig, 0FFFFh

;CONVERT 32 BIT NUMBER TO STRING.
  mov  si, offset buf
  call number2string32bit

;DISPLAY STRING (32 BIT NUMBER CONVERTED).
  mov  ah, 9
  mov  dx, offset buf
  int  21h  

;WAIT FOR ANY KEY.    
  mov  ah, 7
  int  21h

;FINISH PROGRAM.
  mov  ax, 4c00h
  int  21h

;------------------------------------------
;CONVERT 32 BIT NUMBER IN STRING.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE DIVIDING
;NUMBER BY 10, STORING REMAINDERS IN STACK, THEN
;EXTRACT THEM IN REVERSE ORDER TO BUILD STRING.
;PARAMETERS : num_low = LOW  WORD OF 32 BIT NUMBER.
;             num_hig = HIGH WORD OF 32 BIT NUMBER.
;             SI  = POINTING WHERE TO STORE STRING.

number2string32bit proc

  mov  bx, 10                ;DIVIDE NUMBER BY 10 TO EXTRACT DIGITS.
  mov  cx, 0                 ;DIGITS COUNTER. NECESSARY TO POP REMAINDERS.

extracting: 

;DIVIDE HIGHER WORD OF 32 BIT NUMBER.
  mov  dx, 0                 ;DX NOT NECESSARY FOR THE HIGH WORD.
  mov  ax, num_hig
  div  bx
  mov  num_hig, ax           ;HIGHER WORD OF RESULT.

;DIVIDE LOWER WORD OF 32 BIT NUMBER.
;VERY IMPORTANT : PREVIOUS DX IS NECESSARY FOR THE LOW WORD.
  mov  ax, num_low
  div  bx
  mov  num_low, ax           ;LOWER WORD OF RESULT.

  push dx                    ;STORE REMAINDER (EXTRACTED DIGIT).
  inc  cx                    ;INCREASE DIGIT COUNTER.

;CHECK END OF PROCESS.
  cmp  ax, 0                 ;IF LOWER WORD IS
  jne  extracting            ;NOT ZERO, REPEAT.   

;NOW RETRIEVE PUSHED DIGITS. THERE ARE CX DIGITS STORED IN STACK.
poping:  
  pop  dx                    ;GET STORED DIGIT.
  add  dl, 48                ;CONVERT DIGIT TO CHARACTER.
  mov  [ si ], dl            ;STORE CHARACTER IN STRING.
  inc  si                    ;POSITION FOR NEXT CHARACTER.
  loop poping                ;CX--. IF ( CX > 0 ) REPEAT.

  ret
number2string32bit endp  

;------------------------------------------

end start