⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deskcalc.s

📁 坦尼保姆
💻 S
📖 第 1 页 / 共 2 页
字号:
!	EIGHT BYTE INTEGER POCKET CALCULATOR IN REVERSE POLISH! This program emulates a stack oriented integer machine in polish notation.! The central data structure consists of eight byte signed long ints, which! are pushed onto and popped from a stack which is called "nstack".! The size of this stack is 1024 of those longs. Moreover the emulated! machine has a memory containing 26 of those eight byte variables,! which are indicated by the variable names "A" through "Z".! The machine is supposed to read commands and integers from standard input.! The operators all pop their arguments from the stack and push the result.! The admitted binary operators are: addition, indicated by a "+" character;! subtraction, "-"; multiplication, "*"; integer division discarding! the remainder, indicated by a ":" character; and the remainder operation! indicated by "%". ! There is a unary minus operator "~"; a pop from stack operator "p";! duplicate top of stack "d"; and exchange the two integers on the top of! the stack "x". The operator "^" prints the entire stack, and if an end of! line is encountered the top element of the stack is printed if available.! If the input is numerical, the indicated number is pushed onto the stack.! The command "sA" is a store operation, which pops the top of stack and stores! it into the variable "A"; retrieval is done with the "r" command, so "rZ"! gets the value of variable "Z" and pushes it onto the stack.! The command "q" terminates the program.! As an example program we could try! 35 18-d*dsA\n  which pushes first 35, then 18, computes the difference,(17)! duplicates and multiplies it (289) duplicate and stores it in "A".! The end of line prints the top of stack, so the result is 289.! The aim of this exercise is: First to understand the calculation! Secondly to program an extra feature in such a way that the calculator! accepts lines in infix notation. In this infix notation the operators are! put between the numbers, and the order of evaluation can be influenced by! means of parentheses. Those infix notation lines will be recognised! by an equal sign "=" at the end of a line. If such a line is encountered,! then it must be converted into reversed polish notation. After the converted! line is processed the result is on top of the stack, and this value is printed! because of the end of line which is encountered after the "=" sign.! In the section "Stack addressing" this conversion process is discussed.! Note that in infix notation the operators "x" "p" "d" "q" and "s" cannot! be used. Provisions should be made that recalled variable can be used in! stead of numbers, so "rA+rB=\n" is admitted and must give the expected answer.! Central in the program is the integer stack "nstack" which consists! of 1024 8-byte integers. The stack is used from high to low addresses! and register BX is used to indicate the top of stack.! After a line is read from standard input into the buffer "inputb" it is! scanned one character at the time. Two integer buffers "curbuf" and "nxtbuf"! are used to keep the bytes which are to be processed. A copy of "curbuf"! is kept in DX, and "nxtbuf" is used to have a read ahead of one byte.! The routine "getcbuf" copies the "nxtbuf" into DX and "curbuf" and moves! another byte into "nxtbuf". The input line in "inputb" is scanned by means! of a pointer variable "pinbuf"..SECT .TEXT	TEN = 0xa		! Use this constant for decimal printoutsstart:	MOV 	BX,stkend	! Puts the register BX at the end of the nstack	CLD0:	CALL	rdline		! Read an input line into the inputb	CALL    central		! Execute the commands in the inputb	CALL    snlcr		! Output top of stack	JMP     0b		! Start again by the read linecentral:			! The central interpretation loop1:	CALL getcbuf	MOV  AX,DX		! Copy input character into AX	CMP  AX,0		! Zero means end of buffer, finish central.	JLE  3f	SHL  AX,1		! Double the value of the input byte to	MOV  DI,AX		! use it in the dispatch table DTABLE	CALL DTABLE(DI)		! The register DI is used to govern the call.	JMP  1b3:	RETsquit:	PUSH	(null)		! Exit system call routine.	PUSH	(_exit)	SYSrdline:	MOV  DI,inputb		! Use DI register to store characters in inputb	XOR  CX,CX		! Cleanup CX, which counts the number of bytes	PUSH (_getchar)		! Prepare for the read byte from standard in1:	SYS			! get next byte	CMP  AX,0	JL   9f			! finish on AX<0, i.e. end of file.	CMPB AL,'\b'	JE   8f			! move one character back on a backspace	STOSB			! store character in inputb, auto increment DI	INC  CX			! One more character read	CMP  AX,'\n'	JNE  1b			! If not end of line, get next byte	MOVB (DI),'\0'		! Close input string with a zero byte	MOV  (pinbuf),inputb	! put input pointer at the start of the line	CALL getcbuf		! Fill the next character buffer	ADD  SP,2		! Stack cleanup	RET8:	CMP  CX,0 		! Correct current line with backspaces.	JE   1b			! No correction at the start of the line	DEC  CX			! Decrement byte count	DEC  DI			! Decrement buffer pointer	JMP  1b9:	PUSH eofmes		! Close process on end of input	PUSH (_printf)	SYS			! Print exit message	ADD  SP,4	CALL squit		! and terminate programgetcbuf: PUSH AX		! Save AX	XOR  DX,DX		! Cleanup DX	MOVB DL,(nxtbuf)	! Get DL from nxtbuf	MOV  (curbuf),DX	! Fill curbuf	XCHG SI,(pinbuf)	! get pointer from pinbuf	LODSB			! Get next character from inputb; increment SI	MOVB (nxtbuf),AL	! Fill nxtbuf with new character	XCHG (pinbuf),SI	! Restore SI and pot neww value in pinbuf 	POP AX			! Restore AX 	RET			! Back! The three registers BX, SI and DI which can be used to point in the data! segment are used to boint to the bottom address of the 8-byte integers which! are used as the basic data units in this exercise. The BX register governs! the nstack, and the DI and SI point to the destination and the source for! the integers used in the computation. So the basic computations used those! registers in every computation, and we need routines to clean the integer! variables indicated, to copy and exchange them, for addition, subtraction,! multiplication, division, and the determination of remainders. Because these! last three computations involve complicated loops in their routines there! are five scratch variables oper1 through oper5, which are used for this ! purpose.clrd:	PUSH DX			! Put 8-byte value 0 in the variable under DI	XOR  DX,DX		! Cleanup DX	MOV  (DI),DX		! and enter this value 0 into four consecutive	MOV  2(DI),DX		! memory words indicated by DI	MOV  4(DI),DX	MOV  6(DI),DX	POP  DX	RETclrs:	XCHG SI,DI		! Put 8-byte value 0 in the variable under SI	CALL clrd		! by exchangeing the pointers twice and clrd	XCHG DI,SI	RETpushd:  SUB  BX,2		! Push 8-byte integer under DI onto nstack	MOV  AX,6(DI)		! using the register BX as its stackpointer 	MOV  (BX),AX	SUB  BX,2	MOV  AX,4(DI)	MOV  (BX),AX	SUB  BX,2	MOV  AX,2(DI)	MOV  (BX),AX	SUB  BX,2	MOV  AX,(DI)	MOV  (BX),AX	RETsrshift: SHR 6(SI),1		! Right shift 8-byte integer under SI	RCR 4(SI),1	RCR 2(SI),1	RCR (SI),1	RETslshift:SHL  (SI),1		! Left shift 8-byte integer under SI	RCL  2(SI),1	RCL  4(SI),1	RCL  6(SI),1	JC   9f			! Jump on carry set	(Unsigned overflow)	JO   9f			! Jump on overflow	(Signed overflow)	CMP  6(SI),0	JL   9f			! Jump on negative	(Signed overflow)	RET9:	PUSH shfterr	PUSH (_printf)	SYS	ADD  SP,4	RETdlshift:XCHG SI,DI		! Left shift 8-byte integer under DI	CALL slshift		! by exchanging the registers SI and DI	XCHG DI,SI	RETcpsd:	MOV  AX,(SI)		! Copy variable under SI to variable under DI	MOV  (DI),AX	MOV  AX,2(SI)	MOV  2(DI),AX	MOV  AX,4(SI)	MOV  4(DI),AX	MOV  AX,6(SI)	MOV  6(DI),AX	RETcpds:	MOV  AX,(DI)		! Copy variable under DI to variable under SI	MOV  (SI),AX	MOV  AX,2(DI)	MOV  2(SI),AX	MOV  AX,4(DI)	MOV  4(SI),AX	MOV  AX,6(DI)	MOV  6(SI),AX	RETsubsd:	MOV  AX,(SI)		! Subtract source (SI) from destination (DI)	SUB  (DI),AX	MOV  AX,2(SI)	SBB  2(DI),AX	MOV  AX,4(SI)	SBB  4(DI),AX	MOV  AX,6(SI)	SBB  6(DI),AX	RETaddsd:	MOV  AX,(SI)		! Add source (SI) to destination (DI)	ADD  (DI),AX	MOV  AX,2(SI)	ADC  2(DI),AX	MOV  AX,4(SI)	ADC  4(DI),AX	MOV  AX,6(SI)	ADC  6(DI),AX	RETmulsd:	PUSH CX			! Multiply source (SI) to destination (DI)	PUSH BX	MOV  BX,oper2		! Use oper2 as a 16 byte shift register.	MOV  (BX),0	MOV  2(BX),0	MOV  4(BX),0	MOV  6(BX),0	MOV  CX,641:	SHL  (BX),1	! Multiplication is shift followed by add in case of a 1	RCL  2(BX),1	RCL  4(BX),1	RCL  6(BX),1	RCL  8(BX),1	RCL  10(BX),1	RCL  12(BX),1	RCL  14(BX),1	SHL  (SI),1	! Shift the source	RCL  2(SI),1	RCL  4(SI),1	RCL  6(SI),1	JNC  2f		! and look if a carry is shifted out. This would be a 1	INC  (SI)	! in that case this inc makes a rotate for the source	MOV  AX,(DI)	! and the add of the multiplyer is done here	ADD  (BX),AX	MOV  AX,2(DI)	ADC  2(BX),AX	MOV  AX,4(DI)	ADC  4(BX),AX	MOV  AX,6(DI)	ADC  6(BX),AX	ADC  8(DI),0	! multiplyers are just 8 byte, so only adc from here	ADC  10(DI),0	ADC  12(DI),0	ADC  14(DI),02:	LOOP 1b	MOV  AX,(BX)	MOV  (DI),AX	MOV  AX,2(BX)	MOV  2(DI),AX	MOV  AX,4(BX)	MOV  4(DI),AX	MOV  AX,6(BX)	MOV  6(DI),AX	POP  BX	POP  CX	RETdivsd:	! Divides the positive number addressed by DI by the number in (SI).	! Keeps the sources unchanged, but copies them into	! oper1, oper2 en oper3	! stores remainder in oper1, divisor in oper2 en quotient in oper3.	PUSH CX	PUSH BX	MOV  BX,oper3	XCHG BX,DI	CALL clrd	! Get an 8-byte 0 value	CALL cmpds	! Compare with divisor under SI	CMP  AX,0	JE   9f		! And jump to error is divisor is zero	XCHG DI,BX	PUSH DI	PUSH SI	PUSH DI	MOV  DI,oper2	! Scratch variable oper2 in DI	CALL cpsd	! Copy source value i.e the divisor to oper2	MOV  DI,oper1	POP  SI 	! Old DI is extracted as SI as source for the divident	CALL cpsd	! and the divident is copied to oper1	MOV  SI,oper2	XOR  CX,CX0:	CALL cmpds	! Next compare divident and divisor	CMP  AX,0	JL   2f	JE   3f	ADD  CX,1	CALL slshift	! Shift left divisor left until its larger than divident	JMP  0b		! Determines ho often subtraction should be attempted.2:	CMP   CX,0	JE    8f	! Never shifted, then divident is rest	DEC  CX	CALL srshift3:	ADD  (BX),1	! Increment quotient	ADC  2(BX),0	ADC  4(BX),0	ADC  6(BX),0	CALL subsd	! Subtract shifted divisor from divident4:	CMP  CX,0	JE   8f		! Nothing to shift, then ready	DEC  CX	CALL srshift	! right shift divisor (i.e. backwards)	XCHG DI,BX	CALL dlshift	! left shift quotient	XCHG BX,DI	CALL cmpds	! Compare again if subtraction is necessary	CMP  AX,0	JGE  3b		! Yes: Increment quotient again and subtract (Label 3)	JMP  4b		! No: Shifts only (Label 4)8:	POP  SI		! Divisor back at original value in oper2	POP  DI		! oper3 contains quotient.	JMP 6f		! oper1 contains remainder9:	XCHG DI,BX	PUSH nulmes	! Print message division by 0 refused	PUSH (_printf)	SYS

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -