Add Pep8 Assembly language (#2070)

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>
This commit is contained in:
Lucas Bajolet
2017-05-15 04:02:06 -04:00
committed by Colin Seymour
parent acbab53198
commit ded651159d
12 changed files with 1536 additions and 0 deletions

34
samples/Pep8/div.pep Normal file
View File

@@ -0,0 +1,34 @@
main: SUBSP 8, i
DECI 0, s
DECI 2, s
CALL div
DECO 4, s
CHARO '\n', i
DECO 6, s
CHARO '\n', i
STOP
; Divides two numbers following the euclidian method
;
; Parameters:
; SP + 2: Dividend
; SP + 4: Divider
; Returns:
; SP + 6: Quotient
; SP + 8: Remain
div: LDX 0, i
LDA dividend, s
divlp: CPA divider, s
BRLT divout
ADDX 1, i
SUBA divider, s
BR divlp
divout: STX quot, s
STA rem, s
RET0
dividend: .EQUATE 2
divider: .EQUATE 4
quot: .EQUATE 6
rem: .EQUATE 8
.END

23
samples/Pep8/flag.pep Normal file
View File

@@ -0,0 +1,23 @@
_start: LDA 0,i
LDX 0,i
LDA 20, i
ADDA 51, i
CPA 0,i
BRLT s3
BR s4
s1: LDBYTEA s3, x
NOTA
STBYTEA s3, x
ADDX 1,i
CPX 12, i
BRNE s1
s2: STOP
s4: LDA 31, d
LDX 50, d
RET0
STOP
s3: CPX -27746, d
ANDX -8241, i
SUBA -12337, sxf
LDX -12289, sx
.END

675
samples/Pep8/linked.pep Normal file
View File

@@ -0,0 +1,675 @@
; Linked list of integers API
;
; Contains the basis of the structure and a
; variety of available functions to call on it.
;
; Calling conventions:
;
; - When the number of arguments is <= 2, the fastcall convention will be used:
; Arguments will be passed by registers, no assumption is made concerning the
; state of the registers during execution, they will need to be saved.
;
; - When the number of arguments exceeds 2, the cdecl convention will be used:
; Arguments will be passed on the stack, no assumption is made concerning the
; state of the registers during execution, they will need to be saved.
; Simple test program, do no include when using the library
main: SUBSP 4, i
DECI mnelmt, s
CALL newlst
LDX mnlst, s
CALL lstgetst
LDX mnlst, s
CALL lstsetst
LDX mnlst, s
CALL lstgetst
LDX mnlst, s
CALL shftest
LDX mnlst, s
CALL ushftest
LDX mnlst, s
CALL shftest
ADDSP 4, i
STOP
; Pointer to the list
mnlst: .EQUATE 0
; Element read
mnelmt: .EQUATE 2
; TESTS
; Simple test for the get operation
; Gets the first element of the list and prints it
;
; REQUIRES: Non-empty list
;
; Parameters:
; - X: Pointer to the list
;
; Returns:
; void
lstgetst: SUBSP 2, i
LDA 0, i
CALL lstget
STA 0, s
DECO 0, s
CHARO '\n', i
ADDSP 2, i
RET0
; Test for the set operation
; Sets the first element of the list to a given value
; The value is read from stdin
;
; REQUIRES: Non-empty list
;
; Parameters:
; - X: Pointer to the list
;
; Returns:
; void
lstsetst: SUBSP 6, i
STX 0, s
DECI 4, s
LDA 0, i
STA 2, s
CALL lstset
ADDSP 6, i
RET0
; Tests shift operation on a list
; Gets the last element of the list and prints it
;
; REQUIRES: Non-empty list
;
; Parameters:
; - X: Pointer to the list
;
; Returns:
; void
shftest: SUBSP 2, i
CALL lstshft
STA 0, s
DECO 0, s
CHARO '\n', i
ADDSP 2, i
RET0
; Tests unshift operation on a list
; Unshifts a new element read from keyboard
;
; Parameters:
; - X: Pointer to the list
;
; Returns:
; void
ushftest: SUBSP 2, i
DECI 0, s
LDA 0, s
CALL lstunshf
ADDSP 2, i
RET0
; LIBRARY
; Creates a new list with `element` as head
;
; Parameters:
; SP + 4: Element
;
; Returns:
; SP + 2: Pointer to the list
newlst: LDA lstlen, i
CALL new
STX 2, s
CALL newnode
SUBSP 2, i
STX 0, s
LDX nodeelmt, i
LDA 6, s
STA 0, sxf
LDA 0, s
LDX lsthead, i
STA 4, sxf
ADDSP 2, i
RET0
; Gets a node at specified index in a list
;
; Parameters:
; - A: Index
; - X: Pointer to the list
;
; Returns:
; - A: Error code (0 if no error was produced)
; - X: Pointer to the node
;
; Errors:
; -1: Index < 0
; -2: Index >= list.length
nodeat: SUBSP 10, i
STA ndaind, s
STX ndalst, s
LDX lsthead, i
LDA ndalst, sxf
STA ndanode, s
LDA ndaind, s
CPA 0, i
LDA 0, i
STA ndacurri, s
BRGE ndagez
LDA -1, i
ADDSP 10, i
RET0
ndagez: LDX ndalst, s
CALL listlen
STA ndalstln, s
LDA ndaind, s
CPA ndalstln, s
BRLT ndalp
LDA -2, i
ADDSP 10, i
RET0
ndalp: LDA ndacurri, s
CPA ndaind, s
BREQ ndaout
LDX nodenxt, i
LDA ndanode, sxf
STA ndanode, s
LDA ndacurri, s
ADDA 1, i
STA ndacurri, s
BR ndalp
ndaout: LDX ndanode, s
LDA 0, i
ADDSP 10, i
RET0
ndaind: .EQUATE 0
ndanode: .EQUATE 2
ndalst: .EQUATE 4
ndalstln: .EQUATE 6
ndacurri: .EQUATE 8
; Length of the list passed as a parameter
;
; Parameters:
; - X: List
;
; Returns:
; - A: Length
listlen: SUBSP 4, i
STX lenode, s
LDX lenode, sf
STX lenode, s
LDA 0, i
STA lencpt, s
llenlp: LDA lenode, s
CPA 0, i
BREQ lenout
LDA lencpt, s
ADDA 1, i
STA lencpt, s
LDX nodenxt, i
LDA lenode, sxf
STA lenode, s
BR llenlp
lenout: LDA lencpt, s
ADDSP 4, i
RET0
lenode: .EQUATE 0
lencpt: .EQUATE 2
; Gets an element in a list at a specified index
;
; Parameters:
; - A: Index
; - X: Address of the list
;
; Returns:
; - A: Element value
;
; Error:
; If out of bounds, prints an error message and stops the program
lstget: SUBSP 2, i
STA 0, s
CALL nodeat
CPA 0, i
BRNE getoob
LDA 0, x
ADDSP 2, i
RET0
; Out of bounds
getoob: STRO getstrob, d
DECO 0, s
CHARO '\n', i
STOP
; String for out of bounds error
getstrob: .ASCII "Invalid index on get, index = \x00"
; Sets an element in a list at a specified index to a new value
;
; Parameters:
; - SP + 2: Pointer to the list
; - SP + 4: Index
; - SP + 6: Element
;
; Returns:
; - A: 0 if all went well, an error code otherwise (analogous to the error codes in nodeat)
lstset: CHARO '\n', i
DECO lstsetlp, s
CHARO ' ', i
DECO lstsetin, s
CHARO ' ', i
DECO lstsetel, s
CHARO '\n', i
SUBSP 2, i
LDX lstsetlp, s
LDA lstsetin, s
CALL nodeat
CPA 0, i
BRNE lstsetrt
STX lstsetnp, s
LDA lstsetel, s
LDX nodeelmt, i
STA lstsetnp, sxf
LDA 0, i
lstsetrt: ADDSP 2, i
RET0
; Pointer to the list
lstsetlp: .EQUATE 4
; Element to set the value at
lstsetel: .EQUATE 8
; Index of the node
lstsetin: .EQUATE 6
; Pointer to the node
lstsetnp: .EQUATE 0
; Removes the first element of the list in parameter and returns its value
;
; REQUIRES: Non-empty list
;
; Parameters:
; ⁻ X: Pointer to the list
;
; Returns :
; - A: Element removed
lstshft: SUBSP 8, i
STX lshflp, s
LDX lsthead, i
LDA lshflp, sxf
CPA 0, i
BREQ shfterr
STA lshfohd, s
LDX nodenxt, i
LDA lshfohd, sxf
STA lshfnhd, s
LDX lsthead, i
STA lshflp, sxf
LDX nodeelmt, i
LDA lshfohd, sxf
ADDSP 8, i
RET0
shfterr: STRO shfterrm, d
STOP
; Pointer to the list
lshflp: .EQUATE 0
; Pointer to the old head
lshfohd: .EQUATE 2
; Old head's element
lshfhdel: .EQUATE 4
; Pointer to the new head
lshfnhd: .EQUATE 6
; Error message on shift
shfterrm: .ASCII "Cannot do shift on empty list.\n\x00"
; Inserts a new element at the beginning of a list
;
; Parameters:
; - X: Pointer to the list
; - A: Element to add to the list
;
; Returns:
; - A: Error code, 0 if all right, a code otherwise
lstunshf: SUBSP 8, i
STA lunshelm, s
STX lunslp, s
CALL newnode
STX lunsnhd, s
LDX lsthead, i
LDA lunslp, sxf
STA lunsohd, s
LDX nodenxt, i
LDA lunsohd, s
STA lunsnhd, sxf
LDA lunshelm, s
LDX nodeelmt, i
STA lunsohd, sxf
LDX lsthead, i
LDA lunsnhd, s
STA lunslp, sxf
ADDSP 8, i
RET0
; Pointer to the list
lunslp: .EQUATE 0
; Pointer to the old head
lunsohd: .EQUATE 2
; Pointer to the new head
lunsnhd: .EQUATE 4
; Element to add
lunshelm: .EQUATE 6
; Finds whether or not an element is present in a list
;
; Parameters:
; - X: Pointer to the list
; - A: Element to be found
;
; Returns:
; - A: 0 if element was not found, 1 if it was
lstfnd: SUBSP 6, i
STX lstfndlp, s
STA lstfndel, s
LDX lsthead, i
LDA lstfndlp, sxf
STA lstfndnd, s
fndloop: CPA 0, i
BREQ notfnd
LDX nodeelmt, i
LDA lstfndnd, sxf
CPA lstfndel, s
BREQ found
LDX nodenxt, i
LDA lstfndnd, sxf
STA lstfndnd, s
BR fndloop
notfnd: LDA 0, i
ADDSP 6, i
RET0
found: LDA 1, i
ADDSP 6, i
RET0
; Pointer to the list
lstfndlp: .EQUATE 0
; Element to search
lstfndel: .EQUATE 2
; Current node
lstfndnd: .EQUATE 4
; Pushes a new element at the end of the list
;
; Parameters:
; - X: Pointer to the list
; - A: Element to push
;
; Returns:
; - A: 0 if all went well, an error code otherwise
lstpsh: SUBSP 8, i
STX lpshlp, s
STA lpshel, s
CALL newnode
STX lpshnd, s
LDX lpshlp, s
CALL listlen
CPA 0, i
BREQ lpshshft
SUBA 1, i
LDX lpshlp, s
CALL nodeat
STX lpshlnd, s
LDX nodenxt, i
LDA lpshnd, s
STA lpshlnd, sxf
LDA lpshel, s
LDX nodeelmt, i
STA lpshnd, sxf
ADDSP 8, i
RET0
lpshshft: LDX lpshlp, s
LDA lpshel, s
CALL lstunshf
ADDSP 8, i
RET0
; Pointer to the list
lpshlp: .EQUATE 0
; Element to add to the list
lpshel: .EQUATE 2
; Node to add to the list
lpshnd: .EQUATE 4
; Node to append
lpshlnd: .EQUATE 6
; Pops the last element of a list
;
; Parameters:
; - X: Pointer to the list
;
; Returns:
; - A: Element removed from the list
lstpop: SUBSP 6, i
STX lpoplp, s
CALL listlen
CPA 0, i
BRNE poperrem
CPA 1, i
BREQ popshft
SUBA 2, i
LDX lpoplp, s
CALL nodeat
STX lpopndpr, s
LDX nodenxt, i
LDA lpopndpr, sxf
LDA 0, i
LDX nodenxt, i
STA lpopndpr, sxf
STA lpoplnd, s
LDX nodeelmt, i
LDA lpoplnd, s
ADDSP 6, i
RET0
poperrem: STRO poperrsm, d
STOP
popshft: LDX lpoplp, s
CALL lstshft
ADDSP 6, i
RET0
; Pointer to the list
lpoplp: .EQUATE 0
; Node to remove
lpoplnd: .EQUATE 2
;New last node
lpopndpr: .EQUATE 4
; Message to print when popping an empty list
poperrsm: .ASCII "Error: cannot pop an empty list.\n\x00"
; Inserts an element in a list at a given position
;
; REQUIRES: Non-empty list
;
; Parameters:
; - SP + 2: Pointer to the list
; - SP + 4: Index to insert at
; - SP + 6: Element to add
;
; Returns:
; - A: Error code: 0 if all went well, -1 if index < 0, -2 if index > list.length
lstinsat: SUBSP 6, i
LDA lstinsid, s
CPA 0, i
BRLT lstinslz
BREQ lstinush
LDX lstinslp, s
CALL listlen
CPA lstinsel, s
BRLT lstinsgl
BREQ lstinpsh
LDX lstinslp, s
LDA lstinsel, s
SUBA 1, i
CALL nodeat
STX lstinsnd, s
LDX nodenxt, i
LDA lstinsnd, sxf
STA lstinscx, s
CALL newnode
STX lstinscn, s
LDX nodeelmt, i
LDA lstinsel, s
STA lstinscn, sxf
LDX nodenxt, i
LDA lstinscx, s
STA lstinscn, sxf
LDA lstinscn, s
LDX nodenxt, i
STA lstinsnd, sxf
ADDSP 6, i
RET0
lstinush: LDX lstinslp, s
LDA lstinsel, s
CALL lstunshf
ADDSP 6, i
RET0
lstinpsh: LDX lstinslp, s
LDA lstinsel, s
CALL lstpsh
ADDSP 6, i
RET0
; Insert with index < 0
lstinslz: LDA -1, i
ADDSP 6, i
RET0
; Insert with index > list.length
lstinsgl: LDA -2, i
ADDSP 6, i
RET0
; List pointer
lstinslp: .EQUATE 8
; Index of the newly created node
lstinsid: .EQUATE 10
; Element to add
lstinsel: .EQUATE 12
; Node to change the pointer to the next
lstinsnd: .EQUATE 0
; Node to insert
lstinscn: .EQUATE 2
; Pointer to the node after the created one (might be null)
lstinscx: .EQUATE 4
; Removes a node at a given index in a list,
; returns the element previously contained
;
; Parameters:
; - X: Pointer to the list
; - A: Index of the element
;
; Returns:
; - A: Element removed
;
; Error:
; In case of error, the program aborts with an error message
lstremat: SUBSP 8, i
STX lremlp, s
STA lremid, s
CPA 0, i
BRLT lstremob
BREQ lstremz
CALL listlen
CPA lremid, s
BRGE lstremob
SUBA 1, i
CPA lremid, s
BREQ lrempop
LDA lremid, s
LDX lremlp, s
CALL nodeat
STX lremnd, s
LDA lremid, s
SUBA 1, i
LDX lremlp, s
CALL nodeat
STX lrempnd, s
LDX nodenxt, i
LDA lremnd, sxf
STA lrempnd, sxf
LDX nodeelmt, i
LDA lremnd, sxf
ADDSP 8, i
RET0
lstremz: LDX lremlp, s
CALL lstshft
ADDSP 8, i
RET0
lrempop: LDX lremlp, s
CALL lstpop
ADDSP 8, i
RET0
lstremob: STRO lremobst, d
DECO lremid, s
CHARO '\n', i
STOP
; Pointer to the list
lremlp: .EQUATE 0
; Index to remove an element at
lremid: .EQUATE 2
; Pointer to the node before the removed element
lrempnd: .EQUATE 4
; Pointer to the node to remove
lremnd: .EQUATE 6
; Error out of bounds string for remove_at
lremobst: .ASCII "Error: Out of bounds in remove_at, index = \x00"
; Creates a new node from scratch
; Sets its content to 0/NULL
;
; Parameters:
; void
;
; Return:
; - X: Address of the node
newnode: LDA nodeln, i
SUBSP 2, i
CALL new
STX 0, s
LDA 0, i
LDX nodenxt, i
STA 0, sxf
LDX nodeelmt, i
STA 0, sxf
LDX 0, s
ADDSP 2, i
RET0
; Allocates a new structure in the heap
;
; Parameters:
; - A: Length of the structure to allocate (bytes)
;
; Returns:
; - X: Address of the allocated structure
new: ADDA hpptr, d
LDX hpptr, d
STA hpptr, d
RET0
; Node in a linked list
;
; Contains two fields:
; - Element: Offset 0
; - Next: Offset 2
;
nodeln: .EQUATE 4
nodeelmt: .EQUATE 0
nodenxt: .EQUATE 2
; Linked list capsule
;
; Contains one field:
; - Head: Offset 0
;
lstlen: .EQUATE 2
lsthead: .EQUATE 0
; Pointer to the next available byte on the heap
hpptr: .ADDRSS heap
; Start of the heap
heap: .BLOCK 1
.END

434
samples/Pep8/msq.pep Normal file
View File

@@ -0,0 +1,434 @@
; 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

227
samples/Pep8/qsort.pep Normal file
View File

@@ -0,0 +1,227 @@
; Sorts a statically defined array using the recursive implementation
; of the quicksort algorithm.
;
; In this implementation, the pivot is supposed to be the rightmost
; value of the slice of the array being sorted.
;
; Note that the code presented below should work on any array,
; whether defined statically or dynamically.
;
; Calling conventions:
; Except when mentionned otherwise, every parameter is to be passed on the stack.
; The return values are also on the stack.
; No assumption is to be made on the content of a register on a function call.
; The values of the registers are to be locally saved for further use if necessary.
main: SUBSP 4, i
LDA 11, i
ASLA
STA 2, s
LDA arr, i
STA 0, s
CALL printarr
SUBSP 2, i
LDA arr, i
STA 0, s
LDA 0, i
STA 2, s
LDA 10, i
STA 4, s
CALL qsort
ADDSP 2, i
CHARO '\n', i
LDA 11, i
ASLA
STA 2, s
LDA arr, i
STA 0, s
CALL printarr
STOP
; Sorts an array using the quicksort algorithm
;
; Parameters:
; - SP + 2: Address of the array
; - SP + 4: Left bound
; - SP + 6: Right bound
; Returns:
; void
qsort: SUBSP 2, i
LDA qsarrlb, s
CPA qsarrrb, s
BRGE qsortout
SUBSP 6, i
LDA 10, s
STA 0, s
LDA 12, s
STA 2, s
LDA 14, s
STA 4, s
CALL part
LDA 10, s
STA 0, s
LDA 12, s
STA 2, s
LDA 6, s
SUBA 1, i
STA 4, s
CALL qsort
LDA 10, s
STA 0, s
LDA 6, s
ADDA 1, i
STA 2, s
LDA 14, s
STA 4, s
CALL qsort
ADDSP 6, i
qsortout: ADDSP 2, i
RET0
; Address of the array
qsarradd: .EQUATE 4
; Left bound
qsarrlb: .EQUATE 6
; Right bound
qsarrrb: .EQUATE 8
; Pivot value returned by the part command
qsortp: .EQUATE 0
; Partitions an array in two following the quicksort rules.
;
; All the lower values compared to the pivot will be on the left
; All the upper values compared to the pivot will be on the right
; The pivot's final index is then returned
;
; Parameters:
; - SP + 2: Address of the array
; - SP + 4: Left bound
; - SP + 6: Right bound
;
; Returns:
; - SP + 8: Pivot final index
part: SUBSP 8, i
LDA parrrb, s
STA partpiv, s
LDA parrlb, s
STA pstind, s
STA piter, s
partflp: CPA parrrb, s
BRGE partout
LDX piter, s
ASLX
LDA paraddr, sxf
STA parrival, s
LDX partpiv, s
ASLX
LDA paraddr, sxf
CPA parrival, s
BRLT parlpinc
SUBSP 6, i ; Call swap(arr, i, st_index)
LDA 16, s
STA 0, s
LDA 8, s
STA 2, s
LDA 10, s
STA 4, s
CALL swap
ADDSP 6, i
LDA pstind, s
ADDA 1, i
STA pstind, s
parlpinc: LDA piter, s
ADDA 1, i
STA piter, s
BR partflp
partout: SUBSP 6, i ; Call swap(arr, piv, st_index)
LDA 16, s
STA 0, s
LDA 12, s
STA 2, s
LDA 10, s
STA 4, s
CALL swap
ADDSP 6, i
LDA pstind, s
ADDSP 8, i
STA 8, s
RET0
; Address of the array
paraddr: .EQUATE 10
; Left bound
parrlb: .EQUATE 12
; Right bound
parrrb: .EQUATE 14
; Pivot value
partpiv: .EQUATE 6
; st_index
pstind: .EQUATE 4
; For iterator value
piter: .EQUATE 2
; arr[i] value
parrival: .EQUATE 0
; Swaps the value of two elements of an array of integers
;
; Parameters:
; - SP + 2: Address of the array
; - SP + 4: Index of the 1st element to swap
; - SP + 6: Index of the 2nd element to swap
;
; Returns:
; void
swap: SUBSP 2, i
LDX fstelind, s
ASLX
LDA arraddr, sxf
STA swaptmp, s
LDX secelind, s
ASLX
LDA arraddr, sxf
LDX fstelind, s
ASLX
STA arraddr, sxf
LDA swaptmp, s
LDX secelind, s
ASLX
STA arraddr, sxf
ADDSP 2, i
RET0
; Temporary value for the swap
swaptmp: .EQUATE 0
; Address of the array on which the swap is done
arraddr: .EQUATE 4
; Index of the first element
fstelind: .EQUATE 6
; Index of the second element
secelind: .EQUATE 8
; Prints the content of an array
;
; Parameters:
; SP + 2: Address of the array
; SP + 4: Length of the array
;
; Returns:
; void
printarr: LDX 0, i
parrlp: CPX 4, s
BRGE parrout
DECO 2, sxf
CHARO ' ', i
ADDX 2, i
BR parrlp
parrout: RET0
; Unsorted array for testing purposes
arr: .WORD 9
.WORD 5
.WORD 8
.WORD 10
.WORD 4
.WORD 7
.WORD 0
.WORD 3
.WORD 2
.WORD 1
.WORD 6
.END

61
samples/Pep8/stri_buf.pep Normal file
View File

@@ -0,0 +1,61 @@
main:
; Reads a string in stdin, returns the buffer it was read in
; Stops reading at the first encounter of a \n character.
;
; Parameters:
; void
;
; Returns:
; - X: Address of the buffer
stri: SUBSP 2, i
LDA 32, i
CALL new
CPX buflen, s
BRGE strinlrg
strinlrg: LDA buflen, d
LDX 2, i
CALL mult
STA buflen
CALL new
buflen: .EQUATE 0
; Copies the content of a buffer to another one
;
; Parameters:
; - SP + 2: Destination buffer
; - SP + 4: Source buffer
; - SP + 6: Length to copy
memcpy: LDX 0, i
memcplp: CPX cpylen, s
BREQ memcpout
LDBYTEA srcbuf, sxf
STBYTEA dstbuf, sxf
ADDX 1, i
BR memcplp
memcpout: RET0
; Destination buffer
dtsbuf: .EQUATE 2
; Source buffer
srcbuf: .EQUATE 4
; Copy length
cpylen: .EQUATE 6
; Allocates a new structure in the heap
;
; Parameters:
; - A: Length of the structure to allocate (bytes)
;
; Returns:
; - X: Address of the allocated structure
new: ADDA hpptr, d
LDX hpptr, d
STA hpptr, d
RET0
; Pointer to the next available byte on the heap
hpptr: .ADDRSS heap
; Start of the heap
heap: .BLOCK 1
.END

View File

@@ -0,0 +1,50 @@
main: SUBSP 34, i
LDA 31, i
STA 0, s
CALL fgets
ADDSP 2, i
CALL ststro
STOP
; Reads a string from stdin, stops reading when one of the following is true:
; - Read a \n
; - Read a maximum of `max` chars
;
; Parameters:
; - SP + 2: `max`, the maximum number of chars to read
; - SP + 4: `buffer` of length `max` + 1
; Returns:
; void
fgets: LDX 0, i
LDA 0, i
fgetslp: CHARI buffer, sx
LDBYTEA buffer, sx
CPA '\n', i
BREQ fout
CPX max, s
BREQ fout
ADDX 1, i
BR fgetslp
fout: LDA '\x00', i
STBYTEA buffer, sx
RET0
max: .EQUATE 2
buffer: .EQUATE 4
; Prints a string stored in stack
;
; Parameters:
; SP + 2: `string`
; Returns:
; void
ststro: LDX 0, i
LDA 0, i
strolp: LDBYTEA string, sx
CPA '\x00', i
BREQ strout
CHARO string, sx
ADDX 1, i
BR strolp
strout: RET0
string: .EQUATE 2
.END