需要编写一个程序,该程序将两个数字作为输入并打印它们的总和。不知道我在哪里出错了。我觉得这个部门可能有点时髦,但我真的在努力解决为什么我的输出不正确。防爆。输出:输入10和11 - 输出22.我感谢任何帮助!
.model small
;-----------------------------------------------------
.stack 64
;-----------------------------------------------------
.data
PR DB 'ENTER: ','$'
Num1 Label Byte
Max1 DB 3 ; need to hit atmost 3 keys when entering- 2 digits and the enter key
Act1 Db ?
N1 DB 4 DUP ('$')
Num2 Label Byte
Max2 DB 3 ; need to hit atmost 3 keys when entering- 2 digits and the enter key
Act2 Db ?
N2 DB 4 DUP ('$')
Hold DW ?
Res DB 3 DUP ('$')
msg Db " Result is $"
;-----------------------------------------------------
.code
MAIN proc FAR
mov AX,@data ; Initialize segment
mov DS,AX ; registers
call CLEAR
call SET_CURSOR
call REQUEST_INPUT
call GET_INPUT1
call SET_CURSOR2
call REQUEST_INPUT
call GET_INPUT2
call SET_CURSOR3
call Convert
mov AX,4C00h ; Exit to DOS
int 21h
MAIN endp
;-----------------------------------------------------
CLEAR proc NEAR
mov AX, 0600H
mov BH, 71H
mov CX, 0000H
mov DX, 184FH
int 10H
ret
CLEAR endp
;-----------------------------------------------------
SET_CURSOR proc NEAR
mov AH, 02H
mov BH, 0 ;sets color of backround
mov DH, 5
mov DL, 10
int 10H
ret
SET_CURSOR endp
;-----------------------------------------------------
REQUEST_INPUT proc NEAR
mov AH, 09H
lea DX, PR
int 21H
ret
REQUEST_INPUT endp
;-----------------------------------------------------
GET_INPUT1 proc NEAR
mov AH, 0AH
lea DX,Num1
int 21H
mov BH, 00
mov BL, Max1
mov N1[BX],'$'
ret
GET_INPUT1 endp
;-----------------------------------------------------
GET_INPUT2 proc NEAR
mov AH, 0AH
lea DX,Num2
int 21H
mov BH, 00
mov BL, Max2
mov N2[BX],'$'
ret
GET_INPUT2 endp
;-----------------------------------------------------
Convert proc NEAR
mov BX, 0
mov AH, 00h
mov Al, N1[BX] ; Get a character
Sub Al, 48 ; to get decimel value from character
Mov Bx, 10
Mul Bx
mov Cl, Al ; Result of multiplication stored in Al
mov BX, 1
mov BH, 00h
mov Bl, N1[BX] ; Get a character
Sub BL, 48
Add Cl, Bl ; Add first digit and second digit
mov BX, 0
mov CH, 00h
mov Al, N2[BX] ; Get a character
Sub Al, 48 ; to get decimel value from character
Mov Bx, 10
Mul Bx
Mov Bl, Al ; Result of multiplication stored in Al
mov BX, 1
mov BH, 00h
mov AL, N2[BX] ; Get a character
Sub Al, 48 ;to get decimel value from character
Add Al, Bl ; Add first and second digit
Add Cl, Al ; Add number one and number two
Mov Ah, 0; zero out ah before devision
Mov Al, Cl
Mov Cl, 10
Div Cl
Add Al, 48 ;Value of int devision
Mov Res[0], Al
Add AH, 48 ;value of remainder
Mov Res[1], AH
mov AH,09h
lea DX, msg
int 21H
mov AH,09h
lea DX, Res
int 21H
ret
Convert endp
;-----------------------------------------------------
SET_CURSOR2 proc NEAR
mov AH, 02H
mov BH, 0 ;sets color of backround
mov DH, 6
mov DL, 10
int 10H
ret
SET_CURSOR2 endp
;-----------------------------------------------------
SET_CURSOR3 proc NEAR
mov AH, 02H
mov BH, 0 ;sets color of backround
mov DH, 7
mov DL, 10
int 10H
ret
SET_CURSOR3 endp
;------------------------------------------------------------
;formula ()N1[0]-48)*10 + (N1[1]-48)
;same for N2
;before printing need to divide result of N1+N2 by 10. the quation is the frist character remainder is the second character- quaotiant will be in AL, Remainder in AH
;then need to add 48 before putting them into the array Res
;To go back Add Al,48-Mov Res[0], AL
;-----------------------------------------------------------'
end MAIN
答案 0 :(得分:2)
8086在您的代码中重复使用了3个以上的寄存器ax
,bx
,cx
。
虽然您的代码正在执行大量不必要的值重置,但您设法避免任何冲突,直到Mov Bl, Al
(存储N2 [0] * 10的结果),然后mov bx,1
覆盖这个值。
如果你使用调试器,你可能会注意到你失去了价值。
如果你知道,你将访问例如N2 [1],不要打扰bx
,只需写mov al,[N2+1]
。
如果您执行mul bx
,那么您正在执行dx:ax = bx * ax
(如果您不确定它是如何工作的,请经常documentation查看说明),在您的2位数字的特殊情况下乘以10,你可以设置al
(0-9值)并执行mul bl
(10),这会将结果放入ax
(0-90值),清除上限8位ax
为你。
如果我已经通过尝试只做不可避免的事情来解决清理代码问题,那么如何完全删除一个mul
:
如果你有数字x,y存储为x 1 ,x 0 和y 1 ,y 0 ,其中n =Σn i * 10 i ,则:
x +y⇔x 1 * 10 + x 0 * 1 + y 1 * 10 + y 0 * 1⇔
⇔10*(x 1 + y 1 )+(x 0 + y 0 )
所以在你的代码中你可以这样做:
mov al,[N1+0] ; ASCII x1
add al,[N2+0] ; ASCII y1 (no real overflow risk, 8b is enough)
sub al,2*'0' ; convert from ASCII to value
mov ah,10
mul ah ; ax = 10 * (x1+y1) (value is 0 to 180)
add al,[N1+1] ; add ASCII x0 (48-57 value)
add al,[N2+1] ; add ASCII y0
; max possible AL value = 180 + 57 + 57 = 294
; -> may overflow, but doesn't matter, conversion will "fix" it
sub al,2*'0' ; convert x0,y0 from ASCII to values
; will "fix" overflow by ignoring AH all the time, keeping it 0
; ax = result here (0 to 188 value = fits to 8 bits)
因为2位输入约束(这远远不是通用的加法例程,实际上使用了该约束的每一位),因此可以仅使用Convert PROC
来编写ax
LEA
保持代码非常简单和简短。)
BTW,如果你要使用386+(32位)指令集,那么* 10可以使用; eax = 0-9 value
add eax,eax ; *2
lea eax,[eax+eax*4] ; *5
指令在两条指令中完成,如下所示:
mul
这完全避免了imul eax,eax,10
,这曾经很慢......最新的x86 CPU实际上做add
可能会更快,因为它的单指令与两个简单指令相比,但多年来,这两个新成员(lea
和mul
)更便宜了#34;而不是单imul
/ ; al = 0-9 value
add al,al ; AL = 2*value
mov dl,al ; copy 2*value to DL
add al,al ; AL = 4*value
add al,al ; AL = 8*value
add al,dl ; AL = 10*value
。
在最初的8086上,完成所有这样的添加仍然会更快:
mul bl
比 export class MyDirective {
constructor($interval) {
'ngInject';
this.template = '<div id=chart></div>';
this.restrict = 'E';
this.scope = {}
this.$interval = $interval;
}
compile(tElement) {
tElement.css('position', 'absolute');
}
link(scope, element) {
this.$interval(() => this.chart(), 1000);
}
chart() {
c3.generate({
bindto: '#chart',
data:{
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 140, 200, 150, 50]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
// or
//width: 100 // this makes bar width 100px
}
});
}
}
,在原始8086上需要大约70-77个时钟计算,上面的代码只需要原始8086上的4 * 3 + 2 = 14个时钟。