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

📄 opgave1.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 printouts  start: 	MOV 	BX,stkend	! Puts the register BX at the end of the nstack 	CLD 0:	CALL	rdline		! Read an input line into the inputb !S: <b>TOEVOEGING MOET ZIJN:    if (1na_laaste_teken == '=') { convert inputb to postfix }</b>  !S: <b>check of eerste karakter in inputb al de '\n' is,</b> !S: <b>  zo niet dan bestaat er een karakter VOOR de '\n'.</b> !S: <b>veel gekopieerd van 'rdline' en van 'central' (later optimaliseren?).</b> !	MOV  (pinbuf),inputb	! put input pointer at the start of the line !	CALL getcbuf !	MOV  AX,DX		! Copy input character into AX !	CMP  AX,'\n' 	CMP (inputb),'\n' !<b>Check of het eerste karakter in de string \n is</b> 	JLE  1f !S: <b>nu de echte check voor de '='.  let op verandering DI. gaat dit later goed?</b> 	SUB  DI,2         CMPB (DI),'=' 	JNE  1f         CALL topostfix   !S: <b>label 1 op volgende regel toegevoegd.</b> 1:	CALL    central		! Execute the commands in the inputb 	CALL    snlcr		! Output top of stack 	JMP     0b		! Start again by the read line  ! <b>topostfix lijkt op central</b> topostfix:			! Convert inputb from infix to postfix     PUSH BX 	PUSH BP 	MOV BP,SP 	MOV BX,inputb !<b>Zet BX op het begin van de string. BX bevat de pointer waar het volgende karakter geschreven mag worden</b> 	PUSH '=' !<b>zet het teken voor begin van de string op de stack</b> 1:	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 INTABLE(DI)		! The register DI is used to govern the call. 	JMP  1b  3:	MOVB (BX), '\0' !termineer de geschreven string 	MOV SP,BP !<b>clean up the stack</b> 	POP BP	!<b>restore the base pointer</b> 	POP BX	!<b>restore BX</b> 	MOV (pinbuf),inputb !zet pointer weer aan begin van inputb 	RET   central:			! The central interpretation loop 1:	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  1b 3:	RET  squit:	PUSH	(null)		! Exit system call routine. 	PUSH	(_exit) 	SYS  rdline:	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 in 1:	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 	RET  8:	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  1b  9:	PUSH eofmes		! Close process on end of input 	PUSH (_printf) 	SYS			! Print exit message 	ADD  SP,4 	CALL squit		! and terminate program  getcbuf: 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 	RET  clrs:	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 	RET  pushd:  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 	RET  srshift: SHR 6(SI),1		! Right shift 8-byte integer under SI 	RCR 4(SI),1 	RCR 2(SI),1 	RCR (SI),1 	RET  slshift: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) 	RET 9:	PUSH shfterr 	PUSH (_printf) 	SYS 	ADD  SP,4 	RET  dlshift:XCHG SI,DI		! Left shift 8-byte integer under DI 	CALL slshift		! by exchanging the registers SI and DI 	XCHG DI,SI 	RET  cpsd:	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 	RET  cpds:	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 	RET  subsd:	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 	RET  addsd:	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 	RET  mulsd:	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,64 1:	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),0 2:	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 	RET  divsd:	! 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,CX 0:	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 srshift 3:	ADD  (BX),1	! Increment quotient 	ADC  2(BX),0 	ADC  4(BX),0 	ADC  6(BX),0 	CALL subsd	! Subtract shifted divisor from divident 4:	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 remainder 9:	XCHG DI,BX 	PUSH nulmes	! Print message division by 0 refused 	PUSH (_printf) 	SYS 	ADD  SP,4 6:	POP  BX 	POP  CX 	RET  ! From here we get the routines which push and pop variables on the stack ! The input commands calls those routines from the dispatch table. ! The first routine supplies the address of a variable from its name in DX  getvar:  CALL getcbuf		! Read variable name (between A and Z) 	MOV  AX,DX 	CMP  AX,90 	JG   9f 	SUB  AX,65 	JL   9f 	SHL  AX,1 	SHL  AX,1 	SHL  AX,1 	ADD  AX,varbuf 	MOV  DI,AX 	RET 9:	MOV  DI,8*26 	PUSH varmes 	PUSH (_printf) 	SYS 	ADD  SP,4 	RET  store:  CALL getvar	! Store top of nstack in indicated variable 	MOV  SI,BX 	CALL cpsd 	ADD  BX,8 	RET  recall:	CALL getvar	! Load top of nstack from indicated variable 	SUB  BX,8 	MOV  SI,BX 	CALL cpds 	RET  sxchg:  MOV  DI,oper1		! Exchange top two values of nstack  	MOV  SI,BX 	CALL cpsd 	MOV  DI,BX 	ADD  DI,8 	CALL cpds 	MOV  SI,oper1 	CALL cpsd 	RET  spop:	CMP  BX,stkend	! Pop top of nstack and discard the value 	JGE  topstck 	ADD BX,8 

⌨️ 快捷键说明

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