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