我的汇编中的简单程序有问题。我正在使用DOSbox和TASM。我有程序问题。操作数类型与第76 78 80行不匹配。这是在乘法之后。我尝试使用difftrent变量
进行一些更改; --------------------------------------------
; Equation=(a+c*b)/d-2*c,
; --------------------------------------------
.model small
.stack 100h
.data
a db 0
b db 0
c db 0
d db 0
result1 db ?
result2 db ?
message1 db "Equation: (a+c*b)/d-2*c a=$"
message2 db "b=$"
message3 db "c=$"
message4 db "d=$"
message5 db "Result=$"
.code
start: mov ax,@data
mov ds,ax
mov ax, seg message1 ;get a and save to a variable
mov ds,ax
mov dx,offset message1
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov a,al
mov ax, seg message2 ;get b and save to a variable
mov ds,ax
mov dx,offset message2
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov b,al
mov ax, seg message3 ;get c and save to a variable
mov ds,ax
mov dx,offset message3
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov c,al
mov ax, seg message4 ;get d and save to a variable
mov ds,ax
mov dx,offset message4
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov d,al
mov al,b ; (a+c*b) ------------------------error
mul c
add ax,a ; ------------------------error
push ax ;save current ax
mov ax,c ;d-2*c------------------------error
shl ax,2
sub d,ax
pop bx ;get previous ax to bx
div bx ; div ax:bx
mov result1,al
mov result2,ah
add result1,30h ;converting to string
add result2,30h ;converting to string
mov al,result1
mov bl,result2
mov ax, seg message5
mov ds,ax
mov dx,offset message5
mov ah, 9h
int 21h
mov al,result1
mov bl,result2
mov dl, al
mov ah , 2h
int 21h
mov dl, bl
mov ah , 2h
int 21h
mov ax,4C00h
int 21h
end start
答案 0 :(得分:3)
你的程序几乎是好的,你只有操作数大小的一些问题,这是正常的。所以我接受了你的代码并进行了一些小改动,这些更改被注释并用箭头指示(< ========),它们是:
var pack = d3.layout.pack()
.size([500,400])
.value(function(d) { return d.size; });
时你正在做(d-2 * c)/(a + c * b)。div bx
换行符。13,10
修正了shl ax,2
。一个shl ax,1
是x2,两个shl
是x2x2。shl
,因为当dl
使用单词作为除数时,其余部分保留在div
。这是您的代码,稍有变化(在EMU8086上测试):
dx
接下来是你要做的事情"列表:
Assembly x86 Date to Number - Breaking a string into smaller sections
32 bit Calculator in 8086 Assembly
最后,测试数据:
; --------------------------------------------
; Equation=(a+c*b)/d-2*c,
; --------------------------------------------.model small
.stack 100h
.data
a db 0
b db 0
c db 0
d db 0
result1 db ?
result2 db ?
message1 db 13,10,"Equation: (a+c*b)/d-2*c",13,10,"a=$"
message2 db 13,10,"b=$" ;<================= 13,10 IS
message3 db 13,10,"c=$" ;<================= LINEBREAK.
message4 db 13,10,"d=$" ;<=================
message5 db 13,10,"Quotient=$" ;<=================
message6 db 13,10,"Remainder=$" ;<=================
.code
start: mov ax,@data
mov ds,ax
mov ax, seg message1 ;get a and save to a variable
mov ds,ax
mov dx,offset message1
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov a,al
mov ax, seg message2 ;get b and save to a variable
mov ds,ax
mov dx,offset message2
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov b,al
mov ax, seg message3 ;get c and save to a variable
mov ds,ax
mov dx,offset message3
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov c,al
mov ax, seg message4 ;get d and save to a variable
mov ds,ax
mov dx,offset message4
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov d,al
mov al,b ; (a+c*b)
mul c
mov cl,A ;<======== MOV A TO CX TO
mov ch,0 ;<======== ADD IT TO AX.
add ax,CX ;<======== C*B + A.
;push ax ;<======== NO LONGER NECESSARY BECAUSE
;<======== IN NEXT BLOCK WE USE BX.
mov bl,C ;<======== MOV C TO BL AND CLEAR
mov bh,0 ;<======== BH. NOW C IS IN BX.
shl bx,1 ;<======== 2*c. ONE SHIFT IS x2, TWO SHIFTS ARE x2x2.
sub d,bl ;d - 2c
mov bl,d ;<======== MOV D TO BL AND CLEAR BH. NOW
mov bh,0 ;<======== D IS IN BX. BX = (D-2C).
;pop ax ;<======== NO LONGER NECESSARY. AX CONTAINS (A+C*B).
mov dx,0 ;<======== CLEAR DX, BECAUSE DIVISOR IS A WORD.
;<======== WHEN DIVISOR IS A WORD, DIV USES DX:AX.
div bx ;<======== dx:ax / bx == DX:(A+C*B) / (D-2C). THIS
;<======== DIVISION IS UNSIGNED, FOR SIGNED USE IDIV.
mov result1,al ;<===== QUOTIENT.
mov result2,dl ;<===== REMAINDER, BECAUSE DIVISOR IS WORD.
add result1,30h ;converting to string
add result2,30h ;converting to string
mov al,result1
mov bl,result2
;DISPLAY QUOTIENT <=============
mov ax, seg message5
mov ds,ax
mov dx,offset message5
mov ah, 9h
int 21h
mov al,result1
mov dl, al
mov ah , 2h
int 21h
;DISPLAY REMAINDER <=============
mov ax, seg message6
mov ds,ax
mov dx,offset message6
mov ah, 9h
int 21h
mov dl, bl
mov ah , 2h
int 21h
mov ax,4C00h
int 21h
end start
答案 1 :(得分:1)
因为这个问题在 9k 的浏览量上取得了巨大的成功 并且因为接受的答案本质上是错误的和误导性的,我决定发布一个正确的版本,以便人们最终可以找到如何计算这些简单的表达式.
我的程序有问题。操作数类型在第 76 78 80 行不匹配。
<块引用>add ax,a ; line 76
push ax
mov ax,c ; line 78
shl ax,2
sub d,ax ; line 80
在大多数汇编指令中,逗号两边操作数的大小必须匹配。由于您已将 a、b、c 和 d 变量定义为字节,您不能通过 word 大小的寄存器 AX
合法地使用它们。这就是 TASM 给您错误消息的原因。
在计算 (a+c*b)/d-2*c
之类的表达式时,您必须遵守代数规则。
*
和 /
位于 +
和 -
之前冗余括号我们得到的一切:(a+c*b)/d-2*c
<=> ((a+(c*b))/d)-(2*c)
考虑到 a、b 和 c 是从 0 到 9 的个位数,并且 d 是从 1 到 9 的一位数,结果的范围可以从 -18 到 72。因此我们可以使用字节大小的操作来计算整个表达式。没有必要使用带符号的除法 idiv
,因为此时的红利总是为正数。
mov al, c ; AL = c
mul b ; AL = c * b AH is 0
add al, a ; AL = (c * b) + a AH is 0
div d ; AL = ((c * b) + a) / d AH is remainder
sub al, c ; AL = (((c * b) + a) / d) - c AH is remainder
sub al, c ; AL = ((((c * b) + a) / d) - c) - c AH is remainder
请注意,我们只使用了一个寄存器 (AX
) 来查找结果。你会预料到这一点吗?
以下是我对这一切的实现。我只省略了显示商和余数的部分,但我提供了一个链接 Displaying numbers with DOS 非常详细地解释了如何输出有符号和无符号数字。这是您必须了解的基本内容,因此如果您完整阅读,绝对不会浪费时间。
; --------------------------------------------
; Expression=(a+c*b)/d-2*c,
; --------------------------------------------
ORG 256 ; Use the .COM file format
; Make sure all inputs are valid single digit numbers
cld
mov dx, offset msgA
mov ah, 09h ; DOS.PrintString
int 21h
mov di, offset a ; Storage for the a, b, c, and d variables (adjacent in memory)
mov si, offset msgB ; Offset of the incomplete message
mov bl, "a" ; Character that completes the message
Again:
mov [si+2], bl ; Completing the message
inc bl
mov dx, si
mov ah, 09h ; DOS.PrintString
int 21h
Redo:
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL
sub al, 30h ; From character ["0","9"] to number [0,9]
cmp al, 10
jnb Redo
stosb ; Is indeed in range [0,9]
cmp bl, "e" ; Repeat for "b", "c", and "d"
jb Again
dec di
cmp al, 0
je Redo ; Can't allow d=0 since it will be used as a divider
; The calculation
mov al, c ; AL = c
mul b ; AL = c * b AH is 0
add al, a ; AL = (c * b) + a AH is 0
div d ; AL = ((c * b) + a) / d AH is remainder
sub al, c ; AL = (((c * b) + a) / d) - c AH is remainder
sub al, c ; AL = ((((c * b) + a) / d) - c) - c AH is remainder
mov Q, ax ; Storage for the Q, and R variables (adjacent in memory)
; Displaying the quotient and remainder
mov dx, offset msgB ; Offset of the incomplete message
mov ax, 0951h ; DOS.PrintString
mov [msgB + 2], al ; Completing the message with AL = "Q"
int 21h
mov al, Q
call DisplaySignedNumber8
mov dx, offset msgB ; Offset of the incomplete message
mov ax, 0952h ; DOS.PrintString
mov [msgB + 2], al ; Completing the message with AL = "R"
int 21h
mov al, R
call DisplaySignedNumber8
mov ax, 4C00h ; DOS.Terminate
int 21h
; --------------------------------
a db 0
b db 0
c db 0
d db 0
Q db 0
R db 0
msgA db "Formula: (a+c*b)/d-2*c$"
msgB db 13, 10, "? = $"