mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	Pep/8 is a toy assembly language used in some universities for teaching the basics of assembly and low-level programming. Signed-off-by: Lucas Bajolet <lucas.bajolet@gmail.com>
		
			
				
	
	
		
			435 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			435 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
; Reads a square from stdin, then computes whether it is a magic square or not.
 | 
						|
;
 | 
						|
; A Magic Square is a square following a specific set of rules, namely:
 | 
						|
; - The sum of each row must be the same as the sum of the diagonal
 | 
						|
; - The sum of the anti-diagonal must be the same as the sum of the diagonal
 | 
						|
; - The sum of each column must be the same as the sum of the diagonal
 | 
						|
;
 | 
						|
; If any column, row, or anti-diagonal does not follow the aformented rules,
 | 
						|
; the program will output its number to stdout.
 | 
						|
;
 | 
						|
; Columns are identified by a negative digit, ranging from -1 to -n
 | 
						|
; The anti-diagonal is identified by the number 0.
 | 
						|
; Finally, rows are identified by a positive integer, ranging from 1 to n.
 | 
						|
;
 | 
						|
; Formatting:
 | 
						|
; First a number `n` is read from Stdin, it will determine the size of the square
 | 
						|
; Then, enter the data for the square, `n` entries will be read
 | 
						|
; The data is sequentially added to the square in memory, from the upper-left corner
 | 
						|
; to the lower-right corner, in a zig-zag pattern
 | 
						|
;
 | 
						|
; Example:
 | 
						|
; 3
 | 
						|
; 4   9   3
 | 
						|
; 3   5   7
 | 
						|
; 8   1   6
 | 
						|
;
 | 
						|
; Limitation: Since there is no dynamic allocation, the size
 | 
						|
; of the square is capped at a maximum of 32*32.
 | 
						|
; Any size lower than 1 or higher than 32 will produce
 | 
						|
; an error and the termination of the program.
 | 
						|
 | 
						|
;_start
 | 
						|
		DECI	sidelen, d
 | 
						|
		LDA	sidelen, d
 | 
						|
		CPA	1, i
 | 
						|
		BRLT	sderror
 | 
						|
		CPA	32, i
 | 
						|
		BRGT	sderror
 | 
						|
		LDX	sidelen, d
 | 
						|
		CALL	mult
 | 
						|
		STA	sqlen, d
 | 
						|
		CALL	fillsq
 | 
						|
		LDA	sidelen, d
 | 
						|
		LDX	square, i
 | 
						|
		CALL	diagsum
 | 
						|
		STA	dgsm, d
 | 
						|
		CALL	colsums
 | 
						|
		LDA	sidelen, d
 | 
						|
		LDX	square, i
 | 
						|
		CALL	cdiagsum
 | 
						|
		CPA	dgsm, d
 | 
						|
		BREQ	cnt
 | 
						|
		DECO	0, i
 | 
						|
		CHARO	'\n', i
 | 
						|
cnt:		STA	cdsm, d
 | 
						|
		CALL	rowsums
 | 
						|
		STOP
 | 
						|
el:		.BLOCK 2
 | 
						|
; Length of a side of the square
 | 
						|
sidelen:	.WORD 0
 | 
						|
; Total length  of the square
 | 
						|
sqlen:		.BLOCK 2
 | 
						|
; 32 * 32 square of integers
 | 
						|
square: 	.BLOCK 255
 | 
						|
		.BLOCK 255
 | 
						|
		.BLOCK 255
 | 
						|
		.BLOCK 255
 | 
						|
		.BLOCK 255
 | 
						|
		.BLOCK 255
 | 
						|
		.BLOCK 255
 | 
						|
		.BLOCK 255
 | 
						|
		.BLOCK 8
 | 
						|
 | 
						|
; Prints an error and terminates the program
 | 
						|
sderror:	STRO stderr, d
 | 
						|
		STOP
 | 
						|
 | 
						|
; Parameters:	A: Size of a side of the square
 | 
						|
;		X: Base address of the square
 | 
						|
;		cscolid: Identifier of the column (0-based)
 | 
						|
 | 
						|
; Computes the sum of each column
 | 
						|
; If the sum is not the same as dgsm, its index will be printed (in negative form)
 | 
						|
;
 | 
						|
; Parameters:	A: Size of a side of the square
 | 
						|
;		X: Address of the square
 | 
						|
;
 | 
						|
; Return:	void
 | 
						|
colsums:STA	clsmsqsz, d
 | 
						|
		STX	clsmsqad, d
 | 
						|
		SUBA	1, i
 | 
						|
		STA	clsmyp, d
 | 
						|
clssmlp:CPA	0 ,i
 | 
						|
		BRLT	clsmout
 | 
						|
		STA	cscolid, d
 | 
						|
		LDA	clsmsqsz, d
 | 
						|
		LDX	clsmsqsz, d
 | 
						|
		CALL	colsum
 | 
						|
		CPA	dgsm, d
 | 
						|
		BREQ	clsdecpt
 | 
						|
		LDX	clsmyp, d
 | 
						|
		NEGX
 | 
						|
		STX	clsmyp, d
 | 
						|
		DECO	clsmyp, d
 | 
						|
		CHARO	'\n', i
 | 
						|
		LDX	clsmyp, d
 | 
						|
		NEGX
 | 
						|
		STX	clsmyp, d
 | 
						|
clsdecpt:	LDA	clsmyp, d
 | 
						|
		SUBA	1, i
 | 
						|
		STA	clsmyp, d
 | 
						|
		BR	clssmlp
 | 
						|
clsmout:	RET0
 | 
						|
clsmsqad:	.BLOCK 2
 | 
						|
clsmsqsz:	.BLOCK 2
 | 
						|
clsmyp_:		.BLOCK 2
 | 
						|
 | 
						|
; Compute the sum of each row
 | 
						|
; Prints its index if the value does not match dgsum
 | 
						|
;
 | 
						|
; Parameters:	A: Size of a side of the square
 | 
						|
;		X: Address of the square
 | 
						|
;
 | 
						|
; Returns:	void
 | 
						|
rowsums:	STA	maxrows, d
 | 
						|
		STX	rowssqad, d
 | 
						|
		LDA	0, i
 | 
						|
		STA	tmprwsm, d
 | 
						|
		STA	rowid, d
 | 
						|
rwsmslp:	CPA	maxrows, d
 | 
						|
		BRGE	rwsmsout
 | 
						|
		STA	rwxpos, d
 | 
						|
		LDA	maxrows, d
 | 
						|
		LDX	rowssqad, d
 | 
						|
		CALL	rowsum
 | 
						|
		CPA	dgsm, d
 | 
						|
		STA	tmprwsm, d
 | 
						|
		BREQ	rwinccpt
 | 
						|
		DECO	rowid, d
 | 
						|
		CHARO	'\n', i
 | 
						|
rwinccpt:	LDA	rowid, d
 | 
						|
		ADDA	1, i
 | 
						|
		STA	rowid, d
 | 
						|
		BR	rwsmslp
 | 
						|
rwsmsout:	RET0
 | 
						|
; Number of rows to compute
 | 
						|
maxrows:	.BLOCK 2
 | 
						|
; Square address
 | 
						|
rowssqad:	.BLOCK 2
 | 
						|
; Current rowid
 | 
						|
rowid:		.BLOCK 2
 | 
						|
; Current rowsum
 | 
						|
tmprwsm:	.BLOCK 2
 | 
						|
 | 
						|
; Gets an element at the indexes given as parameter
 | 
						|
; The square is supposed to contain only integers
 | 
						|
; No check will be made on the correctness of the indexes
 | 
						|
;
 | 
						|
; Parameters:	A: Size of a side of the square (in elements)
 | 
						|
;		X: Base address of the square
 | 
						|
;		xpos: Position in X for the element (0-indexed)
 | 
						|
;		ypos: Position in Y for the element (0-indexed)
 | 
						|
;
 | 
						|
; Return:	A will contain the element
 | 
						|
;
 | 
						|
; Side-effects: Registers A and X will neither be saved nor restored upon call
 | 
						|
;		ypos will be altered
 | 
						|
elemat:		STX	elsqaddr, d
 | 
						|
		ASLA
 | 
						|
		LDX	xpos, d
 | 
						|
		CALL	mult
 | 
						|
		STA	xpos, d
 | 
						|
		LDX	ypos, d
 | 
						|
		ASLX
 | 
						|
		STX	ypos, d
 | 
						|
		ADDA	ypos, d
 | 
						|
		ADDA	elsqaddr, d
 | 
						|
		STA	elsqaddr, d
 | 
						|
		LDX	elsqaddr, d
 | 
						|
		LDA	0, x
 | 
						|
		RET0
 | 
						|
; X-index in square (in elements)
 | 
						|
xpos:		.BLOCK 2
 | 
						|
; Y-index in square (in elements)
 | 
						|
ypos:		.BLOCK 2
 | 
						|
; Address to fetch elements at
 | 
						|
elsqaddr:	.BLOCK 2
 | 
						|
 | 
						|
; Fills the square with input from the user
 | 
						|
;
 | 
						|
; Pass via register A the number of inputs to be read
 | 
						|
fillsq:		LDX	0, i
 | 
						|
filloop:	SUBA	1, i
 | 
						|
		CPA	0, i
 | 
						|
		BRLT	fillout
 | 
						|
		DECI	square, x
 | 
						|
		ADDX	2, i
 | 
						|
		BR	filloop
 | 
						|
fillout:	RET0
 | 
						|
 | 
						|
; Computes the sum of the digits of a column
 | 
						|
; The square is supposed to contain integers only
 | 
						|
;
 | 
						|
; Parameters:	A: Size of a side of the square
 | 
						|
;		X: Base address of the square
 | 
						|
;		cscolid: Identifier of the column (0-based)
 | 
						|
;
 | 
						|
; Return:	A: Sum of the digits of the column
 | 
						|
colsum:		STA	csclsqsz, d
 | 
						|
		STX	csclsqad, d
 | 
						|
		LDA	0, i
 | 
						|
		STA	csclsum, d
 | 
						|
		STA	csclxpos, d
 | 
						|
clsmloop:	CPA	csclsqsz, d
 | 
						|
		BRGE	colout
 | 
						|
		LDA	cscolid, d
 | 
						|
		STA	ypos, d
 | 
						|
		LDA	csclxpos, d
 | 
						|
		STA	xpos, d
 | 
						|
		LDA	csclsqsz, d
 | 
						|
		LDX	csclsqad, d
 | 
						|
		CALL	elemat
 | 
						|
		ADDA	csclsum, d
 | 
						|
		STA	csclsum, d
 | 
						|
		LDA	csclxpos, d
 | 
						|
		ADDA	1, i
 | 
						|
		STA	csclxpos, d
 | 
						|
		BR	clsmloop
 | 
						|
colout:		LDA	csclsum, d
 | 
						|
		RET0
 | 
						|
; Identifier of the column which sum is to be computed
 | 
						|
cscolid:	.BLOCK 2
 | 
						|
; Temporary for x position
 | 
						|
csclxpos:	.BLOCK 2
 | 
						|
; Base address of the square
 | 
						|
csclsqad:	.BLOCK 2
 | 
						|
; Size of a side of the square
 | 
						|
csclsqsz:	.BLOCK 2
 | 
						|
; Sum of the column
 | 
						|
csclsum:	.BLOCK 2
 | 
						|
 | 
						|
; Computes the sum of the digits of a row
 | 
						|
; The square is supposed to contain integers only
 | 
						|
;
 | 
						|
; Parameters:	A: Size of a side of the square
 | 
						|
;		X: Base address of the square
 | 
						|
;		rwxpos: Row index (0-based)
 | 
						|
;
 | 
						|
; Returns:	A: Sum of the digits of the row
 | 
						|
rowsum:		STA	rwsqsz, d
 | 
						|
		STX	rwbsqadr, d
 | 
						|
		LDA	0,i
 | 
						|
		STA	rwsum, d
 | 
						|
		STA	rwypos, d
 | 
						|
rwsumlp:	LDA	rwypos, d
 | 
						|
		CPA	rwsqsz, d
 | 
						|
		BRGE	rwsumout
 | 
						|
		STA	ypos, d
 | 
						|
		LDA	rwxpos, d
 | 
						|
		STA	xpos, d
 | 
						|
		LDA	rwsqsz, d
 | 
						|
		LDX	rwbsqadr, d
 | 
						|
		CALL	elemat
 | 
						|
		ADDA	rwsum, d
 | 
						|
		STA	rwsum, d
 | 
						|
		LDA	rwypos, d
 | 
						|
		ADDA	1, i
 | 
						|
		STA	rwypos, d
 | 
						|
		BR	rwsumlp
 | 
						|
rwsumout:	LDA	rwsum, d
 | 
						|
		RET0
 | 
						|
; Square size (in elements)
 | 
						|
rwsqsz:		.BLOCK 2
 | 
						|
; Square base address
 | 
						|
rwbsqadr:	.BLOCK 2
 | 
						|
; Position of the row to compute
 | 
						|
rwxpos:		.BLOCK 2
 | 
						|
; Current column visited
 | 
						|
rwypos:		.BLOCK 2
 | 
						|
; Sum of the row
 | 
						|
rwsum:		.BLOCK 2
 | 
						|
 | 
						|
; Computes the sum for the antidiagonal of a square
 | 
						|
; The square is supposed to contain integers only
 | 
						|
;
 | 
						|
; Parameters:	A: Size of a side of the square (elements)
 | 
						|
;		X: Base address of the square
 | 
						|
;
 | 
						|
; Returns:	A: Sum of the antidiagonal
 | 
						|
cdiagsum:	STA	cdsqsz, d
 | 
						|
		SUBA	1,i
 | 
						|
		STA	cdtmpy, d
 | 
						|
		LDA	0, i
 | 
						|
		STA	cdtmpx, d
 | 
						|
		STA	cdsum, d
 | 
						|
		STX	cdsqaddr, d
 | 
						|
cdiaglp:	LDA	cdtmpx, d
 | 
						|
		STA	xpos, d
 | 
						|
		LDA	cdtmpy, d
 | 
						|
		STA	ypos, d
 | 
						|
		CPA	0, i
 | 
						|
		BRLT	cdout
 | 
						|
		LDA	cdsqsz, d
 | 
						|
		LDX	cdsqaddr, d
 | 
						|
		CALL	elemat
 | 
						|
		ADDA	cdsum, d
 | 
						|
		STA	cdsum,d
 | 
						|
		LDA	cdtmpx, d
 | 
						|
		ADDA	1, i
 | 
						|
		STA	cdtmpx, d
 | 
						|
		LDA	cdtmpy, d
 | 
						|
		SUBA	1, i
 | 
						|
		STA	cdtmpy, d
 | 
						|
		BR	cdiaglp
 | 
						|
cdout:		LDA	cdsum, d
 | 
						|
		RET0
 | 
						|
; Temporary handle for square size (elements)
 | 
						|
cdsqsz:		.BLOCK 2
 | 
						|
; Square address
 | 
						|
cdsqaddr:	.BLOCK 2
 | 
						|
; Keep x address
 | 
						|
cdtmpx:		.BLOCK 2
 | 
						|
; Keep y address
 | 
						|
cdtmpy:		.BLOCK 2
 | 
						|
; Sum of antidiagonal
 | 
						|
cdsum:		.BLOCK 2
 | 
						|
 | 
						|
; Computes the sum for the diagonal of a square
 | 
						|
; The square is supposed to contain integers only
 | 
						|
;
 | 
						|
; Parameters:	A: Size of a side of the square (elements)
 | 
						|
;		X: Base address of the square
 | 
						|
;
 | 
						|
; Returns:	A: Sum of the diagonal
 | 
						|
;
 | 
						|
diagsum:	STA	dsqsz, d
 | 
						|
		STX	dsqaddr, d
 | 
						|
		LDA 	0, i
 | 
						|
		STA	tmpsum, d
 | 
						|
		STA	curra, d
 | 
						|
dglp:		CPA	dsqsz, d
 | 
						|
		BRGE	dglpout
 | 
						|
		STA	xpos, d
 | 
						|
		STA	ypos, d
 | 
						|
		LDA	dsqsz, d
 | 
						|
		LDX	dsqaddr, d
 | 
						|
		CALL	elemat
 | 
						|
		ADDA	tmpsum, d
 | 
						|
		STA	tmpsum, d
 | 
						|
		LDA	curra, d
 | 
						|
		ADDA	1, i
 | 
						|
		STA	curra, d
 | 
						|
		BR	dglp
 | 
						|
dglpout:	LDA	tmpsum, d
 | 
						|
		RET0
 | 
						|
; Address of the square
 | 
						|
dsqaddr:	.BLOCK 2
 | 
						|
; Size of a side of the square (elements)
 | 
						|
dsqsz:		.BLOCK 2
 | 
						|
; Current value of the x and y indexes
 | 
						|
curra:		.BLOCK 2
 | 
						|
; Sum of the values
 | 
						|
tmpsum:		.BLOCK 2
 | 
						|
 | 
						|
; Muliplies two ints
 | 
						|
;
 | 
						|
; Parameters:
 | 
						|
; Register A : Left part of the multiplication
 | 
						|
; Register X : Right part of the multiplication
 | 
						|
;
 | 
						|
; Return:
 | 
						|
; Register A : Result of the multiplication
 | 
						|
;
 | 
						|
; Side-effects:
 | 
						|
; Uses multmp as a temporary value
 | 
						|
mult:		STA	multmp, d
 | 
						|
		LDA	0, i
 | 
						|
muloop:		CPX	0, i
 | 
						|
		BRLE	mulout
 | 
						|
		ADDA	multmp, d
 | 
						|
		SUBX 	1, i
 | 
						|
		BR	muloop
 | 
						|
mulout:		RET0
 | 
						|
; Temporary variable for mult function
 | 
						|
; Holds the initial value of A
 | 
						|
multmp:		.WORD 0
 | 
						|
 | 
						|
; For debugging purposes
 | 
						|
; Prints the content of the square to stdout
 | 
						|
;
 | 
						|
; Parameters: 	A: Size of a side
 | 
						|
;		X: Base address of square
 | 
						|
;
 | 
						|
; Side-effects:
 | 
						|
;		Consider variables sidesz, sqaddr, sqmaxa as local, they will be written
 | 
						|
;		Registers A and X will not be saved nor restored upon call
 | 
						|
printsq:	STA	sidesz, d
 | 
						|
		STX	sqaddr, d
 | 
						|
		LDX	sidesz, d
 | 
						|
		CALL	mult
 | 
						|
		ASLA
 | 
						|
		ADDA	sqaddr, d
 | 
						|
		STA	sqmaxa, d
 | 
						|
		LDX	sqaddr, d
 | 
						|
		LDA	0, i
 | 
						|
priloop:	DECO	0, x
 | 
						|
		CHARO	' ', i
 | 
						|
		ADDX	2, i
 | 
						|
		CPX	sqmaxa, d
 | 
						|
		BREQ	priout
 | 
						|
		ADDA	1, i
 | 
						|
		CPA	sidesz, d
 | 
						|
		BRLT	priloop
 | 
						|
		LDA 	0, i
 | 
						|
		CHARO	'\n', i
 | 
						|
		BR	priloop
 | 
						|
priout:		RET0
 | 
						|
; Size of a side of the square
 | 
						|
sidesz: 	.BLOCK 2
 | 
						|
; Address of the square
 | 
						|
sqaddr: 	.BLOCK 2
 | 
						|
; Maximum address to iterate upon
 | 
						|
sqmaxa: 	.BLOCK 2
 | 
						|
 | 
						|
; ------------------ GLOBALLY ACCESSIBLE SYMBOLS -------------------- ;
 | 
						|
;
 | 
						|
; Sum of the diagonal for the square
 | 
						|
; Reference value for magic-square
 | 
						|
dgsm:		.WORD 0
 | 
						|
; Sum of the counter-diagonal
 | 
						|
cdsm:		.WORD 0
 | 
						|
; Input error string
 | 
						|
stderr:		.ASCII "A number between 1 and 32 (both inclusive) must be entered as value for the size of the square for the program to work.\n\x00"
 | 
						|
		.END
 |