Using the C preprocessor from GCC to preprocess MMIXAL code
Work in progress! 9 year old files or so.
The file MMIX.mmS
below contains macros to ease switching between stuff that goes in the text segment (code segment) and stuff that goes in the data segment. The macros were given Norwegian names at the time. I might change the name of the macros to English once all files are made available in this post.
Copyright is, unless noted otherwise:
Copyright © 2004 Trond Endrestøl <Trond.Endrestol@ximalas.info> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
MMIX.mmS
: macros to ease switching between stuff that goes in the text segment and stuff that goes in the data segment:
#ifndef _MMIX_mmS #define _MMIX_mmS * VIKTIG: _Ikke_ bruk de lokale symbolene 9 og 0 til egne formål! 9H IS #100 0H IS Data_Segment LOC 0B GREG @ #define StartDatasegment \ 0H LOC 0B #define AvsluttDatasegment \ 0H IS @ #define StartKodesegment \ 9H LOC 9B #define AvsluttKodesegment \ 9H IS @ #define WydealignKodesegment \ 9H LOC (@+1)&-2 #define TetraalignKodesegment \ 9H LOC (@+3)&-4 #define OctaalignKodesegment \ 9H LOC (@+7)&-8 #define WydealignDatasegment \ 0H LOC (@+1)&-2 #define TetraalignDatasegment \ 0H LOC (@+3)&-4 #define OctaalignDatasegment \ 0H LOC (@+7)&-8 * Slutt på MMIX.mmS. #endif
abort.mmS
: MMIXAL implementation of abort()
:
#ifndef _abort_mmS #define _abort_mmS #include "MMIX.mmS" PREFIX :abort: * void abort(void); t IS $255 StartKodesegment tekst BYTE #0A,"!! abort trap !!",#0A,0 :abort GETA t,tekst t = &tekst; TRAP 0,:Fputs,:StdErr t = fputs(t, :StdErr); TRAP 0,:Fclose,:StdIn t = fclose(:StdIn); TRAP 0,:Fclose,:StdOut t = fclose(:StdOut); TRAP 0,:Fclose,:StdErr t = fclose(:StdErr); SET t,#FF t = 0xFF; TRAP 0,:Halt,0 _exit(t); AvsluttKodesegment * Slutt på abort.mmS. #endif
bzero.mmS
: MMIXAL implementation of bzero()
:
#ifndef _bzero_mmS #define _bzero_mmS #include "memset.mmS" PREFIX :bzero: * void bzero(void *b, size_t len); b IS $0 len IS $1 hole IS $2 bb IS $3 c IS $4 lenlen IS $5 StartKodesegment :bzero SET bb,b bb = b; SET c,0 c = 0; SET lenlen,len lenlen = len; PUSHJ hole,:memset hole = :memset(bb, c, lenlen); POP 0,0 return; AvsluttKodesegment * Slutt på bzero.mmS. #endif
errno.mmS
: errno
values based on FreeBSD 4.10, the operating system on my development system back in 2004:
#ifndef _errno_mmS #define _errno_mmS #include "MMIX.mmS" #if 0 /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)errno.h 8.5 (Berkeley) 1/21/94 * $FreeBSD: release/4.10.0/sys/sys/errno.h 128520 2004-04-21 11:08:56Z cvs2svn $ */ #endif PREFIX : errno GREG 0 EPERM IS 1 /* Operation not permitted */ ENOENT IS 2 /* No such file or directory */ ESRCH IS 3 /* No such process */ EINTR IS 4 /* Interrupted system call */ EIO IS 5 /* Input/output error */ ENXIO IS 6 /* Device not configured */ E2BIG IS 7 /* Argument list too long */ ENOEXEC IS 8 /* Exec format error */ EBADF IS 9 /* Bad file descriptor */ ECHILD IS 10 /* No child processes */ EDEADLK IS 11 /* Resource deadlock avoided */ /* 11 was EAGAIN */ ENOMEM IS 12 /* Cannot allocate memory */ EACCES IS 13 /* Permission denied */ EFAULT IS 14 /* Bad address */ ENOTBLK IS 15 /* Block device required */ EBUSY IS 16 /* Device busy */ EEXIST IS 17 /* File exists */ EXDEV IS 18 /* Cross-device link */ ENODEV IS 19 /* Operation not supported by device */ ENOTDIR IS 20 /* Not a directory */ EISDIR IS 21 /* Is a directory */ EINVAL IS 22 /* Invalid argument */ ENFILE IS 23 /* Too many open files in system */ EMFILE IS 24 /* Too many open files */ ENOTTY IS 25 /* Inappropriate ioctl for device */ ETXTBSY IS 26 /* Text file busy */ EFBIG IS 27 /* File too large */ ENOSPC IS 28 /* No space left on device */ ESPIPE IS 29 /* Illegal seek */ EROFS IS 30 /* Read-only file system */ EMLINK IS 31 /* Too many links */ EPIPE IS 32 /* Broken pipe */ /* math software */ EDOM IS 33 /* Numerical argument out of domain */ ERANGE IS 34 /* Result too large */ /* non-blocking and interrupt i/o */ EAGAIN IS 35 /* Resource temporarily unavailable */ EWOULDBLOCK IS EAGAIN /* Operation would block */ EINPROGRESS IS 36 /* Operation now in progress */ EALREADY IS 37 /* Operation already in progress */ /* ipc/network software -- argument errors */ ENOTSOCK IS 38 /* Socket operation on non-socket */ EDESTADDRREQ IS 39 /* Destination address required */ EMSGSIZE IS 40 /* Message too long */ EPROTOTYPE IS 41 /* Protocol wrong type for socket */ ENOPROTOOPT IS 42 /* Protocol not available */ EPROTONOSUPPORT IS 43 /* Protocol not supported */ ESOCKTNOSUPPORT IS 44 /* Socket type not supported */ EOPNOTSUPP IS 45 /* Operation not supported */ ENOTSUP IS EOPNOTSUPP /* Operation not supported */ EPFNOSUPPORT IS 46 /* Protocol family not supported */ EAFNOSUPPORT IS 47 /* Address family not supported by protocol family */ EADDRINUSE IS 48 /* Address already in use */ EADDRNOTAVAIL IS 49 /* Can't assign requested address */ /* ipc/network software -- operational errors */ ENETDOWN IS 50 /* Network is down */ ENETUNREACH IS 51 /* Network is unreachable */ ENETRESET IS 52 /* Network dropped connection on reset */ ECONNABORTED IS 53 /* Software caused connection abort */ ECONNRESET IS 54 /* Connection reset by peer */ ENOBUFS IS 55 /* No buffer space available */ EISCONN IS 56 /* Socket is already connected */ ENOTCONN IS 57 /* Socket is not connected */ ESHUTDOWN IS 58 /* Can't send after socket shutdown */ ETOOMANYREFS IS 59 /* Too many references: can't splice */ ETIMEDOUT IS 60 /* Operation timed out */ ECONNREFUSED IS 61 /* Connection refused */ ELOOP IS 62 /* Too many levels of symbolic links */ ENAMETOOLONG IS 63 /* File name too long */ /* should be rearranged */ EHOSTDOWN IS 64 /* Host is down */ EHOSTUNREACH IS 65 /* No route to host */ ENOTEMPTY IS 66 /* Directory not empty */ /* quotas & mush */ EPROCLIM IS 67 /* Too many processes */ EUSERS IS 68 /* Too many users */ EDQUOT IS 69 /* Disc quota exceeded */ /* Network File System */ ESTALE IS 70 /* Stale NFS file handle */ EREMOTE IS 71 /* Too many levels of remote in path */ EBADRPC IS 72 /* RPC struct is bad */ ERPCMISMATCH IS 73 /* RPC version wrong */ EPROGUNAVAIL IS 74 /* RPC prog. not avail */ EPROGMISMATCH IS 75 /* Program version wrong */ EPROCUNAVAIL IS 76 /* Bad procedure for program */ ENOLCK IS 77 /* No locks available */ ENOSYS IS 78 /* Function not implemented */ EFTYPE IS 79 /* Inappropriate file type or format */ EAUTH IS 80 /* Authentication error */ ENEEDAUTH IS 81 /* Need authenticator */ EIDRM IS 82 /* Identifier removed */ ENOMSG IS 83 /* No message of desired type */ EOVERFLOW IS 84 /* Value too large to be stored in data type */ ECANCELED IS 85 /* Operation canceled */ EILSEQ IS 86 /* Illegal byte sequence */ ELAST IS 86 /* Must be equal largest errno */ * Slutt på errno.mmS. #endif
isalnum.mmS
: MMIXAL implementation of isalnum()
:
#ifndef _isalnum_mmS #define _isalnum_mmS #include "isalpha.mmS" #include "isdigit.mmS" PREFIX :isalnum: * int isalnum(int c); c IS $0 rJ IS $1 hole1 IS $2 cc1 IS $3 hole2 IS $3 cc2 IS $4 t IS $255 StartKodesegment :isalnum GET rJ,:rJ rJ = :rJ; SET cc1,c cc1 = c; PUSHJ hole1,:isalpha hole1 = :isalpha(cc1); SET cc2,c cc2 = c; PUSHJ hole2,:isdigit hole2 = :isdigit(cc2); PUT :rJ,rJ :rJ = rJ; OR c,hole1,hole2 c = hole1 || hole2; POP 1,0 return c; AvsluttKodesegment * Slutt på isalnum.mmS. #endif
isalpha.mmS
: MMIXAL implementation of isalpha()
:
#ifndef _isalpha_mmS #define _isalpha_mmS #include "toupper.mmS" PREFIX :isalpha: * int isalpha(int c); c IS $0 rJ IS $1 hole IS $2 cc IS $3 t IS $255 StartKodesegment :isalpha SET cc,c cc = c; GET rJ,:rJ rJ = :rJ; PUSHJ hole,:toupper hole = :toupper(cc); PUT :rJ,rJ :rJ = rJ; SET c,hole c = hole; CMP t,c,'A' if (c < 'A') BN t,1F goto 1F; CMP t,c,'Z' if (c > 'Z') BP t,1F goto 1F; SET c,1 c = 1; POP 1,0 return c; 1H SET c,0 c = 0; POP 1,0 return c; AvsluttKodesegment * Slutt på isalpha.mmS. #endif
isascii.mmS
: MMIXAL implementation of isascii()
:
#ifndef _isascii_mmS #define _isascii_mmS #include "MMIX.mmS" PREFIX :isascii: * int isascii(int c); c IS $0 t IS $255 StartKodesegment :isascii CMP t,c,0 if (c < 0) BN t,1F goto 1F; CMP t,c,#7F if (c > 0x7F) BP t,1F goto 1F; SET c,1 c = 1; POP 1,0 return c; 1H SET c,0 c = 0; POP 1,0 return c; AvsluttKodesegment * Slutt på isascii.mmS. #endif
iscntrl.mmS
: MMIXAL implementation of iscntrl()
:
#ifndef _iscntrl_mmS #define _iscntrl_mmS #include "MMIX.mmS" PREFIX :iscntrl: * int iscntrl(int c); c IS $0 t IS $255 StartKodesegment :iscntrl CMP t,c,#7F if (c == 0x7F) BZ t,2F goto 2F; CMP t,c,0 if (c < 0) BN t,1F goto 1F; CMP t,c,#1F if (c > 0x1F) BP t,1F goto 1F; 2H SET c,1 c = 1; POP 1,0 return c; 1H SET c,0 c = 0; POP 1,0 return c; AvsluttKodesegment * Slutt på iscntrl.mmS. #endif
isdigit.mmS
: MMIXAL implementation of isdigit()
:
#ifndef _isdigit_mmS #define _isdigit_mmS #include "MMIX.mmS" PREFIX :isdigit: * int isdigit(int c); c IS $0 t IS $255 StartKodesegment :isdigit CMP t,c,'0' if (c < '0') BN t,1F goto 1F; CMP t,c,'9' if (c > '9') BP t,1F goto 1F; SET c,1 c = 1; POP 1,0 return c; 1H SET c,0 c = 0; POP 1,0 return c; AvsluttKodesegment * Slutt på isdigit.mmS. #endif
isgraph.mmS
: MMIXAL implementation of isgraph()
:
#ifndef _isgraph_mmS #define _isgraph_mmS #include "MMIX.mmS" PREFIX :isgraph: * int isgraph(int c); c IS $0 t IS $255 StartKodesegment :isgraph CMP t,c,'!' if (c < '!') BN t,1F goto 1F; CMP t,c,'~' if (c > '~') BP t,1F goto 1F; SET c,1 c = 1; POP 1,0 return c; 1H SET c,0 c = 0; POP 1,0 return c; AvsluttKodesegment * Slutt på isgraph.mmS. #endif
islower.mmS
: MMIXAL implementation of islower()
:
#ifndef _islower_mmS #define _islower_mmS #include "MMIX.mmS" PREFIX :islower: * int islower(int c); c IS $0 t IS $255 StartKodesegment :islower CMP t,c,'a' if (c < 'a') BN t,1F goto 1F; CMP t,c,'z' if (c > 'z') BP t,1F goto 1F; SET c,1 c = 1; POP 1,0 return c; 1H SET c,0 c = 0; POP 1,0 return c; AvsluttKodesegment * Slutt på islower.mmS. #endif
isspace.mmS
: MMIXAL implementation of isspace()
:
#ifndef _isspace_mmS #define _isspace_mmS #include "MMIX.mmS" PREFIX :isspace: * int isspace(int c); c IS $0 t IS $255 StartKodesegment :isspace CMP t,c,' ' if (c == ' ') BZ t,1F goto 1F; CMP t,c,#09 if (c < 0x09) BN t,2F goto 2F; CMP t,c,#0D if (c > 0x0D) BP t,2F goto 2F; 1H SET c,1 c = 1; POP 1,0 return c; 2H SET c,0 c = 0; POP 1,0 return c; AvsluttKodesegment * Slutt på isspace.mmS. #endif
isupper.mmS
: MMIXAL implementation of isupper()
:
#ifndef _isupper_mmS #define _isupper_mmS #include "MMIX.mmS" PREFIX :isupper: * int isupper(int c); c IS $0 t IS $255 StartKodesegment :isupper CMP t,c,'A' if (c < 'A') BN t,1F goto 1F; CMP t,c,'Z' if (c > 'Z') BP t,1F goto 1F; SET c,1 c = 1; POP 1,0 return c; 1H SET c,0 c = 0; POP 1,0 return c; AvsluttKodesegment * Slutt på isupper.mmS. #endif
memset.mmS
: MMIXAL implementation of memset()
:
#ifndef _memset_mmS #define _memset_mmS #include "MMIX.mmS" PREFIX :memset: * void *memset(void *b, int c, size_t len); b IS $0 c IS $1 len IS $2 t IS $255 StartKodesegment 1H STBU c,t *t = c; ADDU t,t,1 t++; SUBU len,len,1 len--; 1H PBNZ len,1B if (len != 0) goto 1B; POP 1,0 return b; :memset SET t,b t = b; JMP 1B goto 1B; AvsluttKodesegment * Slutt på memset.mmS. #endif
perror.mmS
: MMIXAL implementation of perror()
:
#ifndef _perror_mmS #define _perror_mmS #include "errno.mmS" #include "sys_errlist.mmS" #include "printX.mmS" PREFIX :perror: * void perror(const char *string); string IS $0 errno IS $1 rJ IS $2 hole IS $3 n IS $4 b IS $5 t IS $255 StartKodesegment colonspace BYTE ": ",0 TetraalignKodesegment newline BYTE #0A,0 :perror BZ string,1F if (string == 0) goto 1F; LDBU t,string t = *string; BZ t,1F if (t == 0) goto 1F; SET t,string t = string; TRAP 0,:Fputs,:StdErr t = fputs(t, stderr); GETA t,colonspace t = &colonspace; TRAP 0,:Fputs,:StdErr t = fputs(t, stderr); 1H SET errno,:errno errno = :errno; CMPU t,errno,:ELAST if (errno <= :ELAST) PBNP t,2F goto 2F; SET errno,:ELAST+2 errno = :ELAST + 2; 2H GETA t,:sys_errlist t = &:sys_errlist; 8ADDU t,errno,t t += 8 * errno; LDOU t,t t = *t TRAP 0,:Fputs,:StdErr t = fputs(t, stderr); BZ :errno,1F if (:errno == 0) goto 1F; CMPU t,:errno,:ELAST if (:errno > :ELAST) BP t,1F goto 1F; JMP 2F goto 2F; 1H GETA t,colonspace t = &colonspace; TRAP 0,:Fputs,:StdErr t = fputs(t, stderr); SET n,:errno n = :errno; SET b,10 b = 10; GET rJ,:rJ rJ = :rJ; PUSHJ hole,:printX hole = printX(n, b); PUT :rJ,rJ :rJ = rJ; 2H GETA t,newline t = &newline; TRAP 0,:Fputs,:StdErr t = fputs(t, stderr); POP 0,0 return; AvsluttKodesegment * Slutt på perror.mmS. #endif
printX.mmS
: MMIXAL implementation of printX()
:
#ifndef _printX_mmS #define _printX_mmS #include "MMIX.mmS" PREFIX :printX: * unsigned long long printX(unsigned long long n, unsigned long long b) n IS $0 b IS $1 nmodb IS $2 rJ IS $3 hole IS $4 ndivb IS $5 bb IS $6 t IS $255 StartDatasegment OctaalignDatasegment GREG @ digit BYTE 0,0 AvsluttDatasegment StartKodesegment :printX CMPU t,b,10 if (b == 10) PBZ t,1F goto 1F; CMPU t,b,16 if (b == 16) PBZ t,1F goto 1F; CMPU t,b,8 if (b == 8) PBZ t,1F goto 1F; CMPU t,b,2 if (b == 2) PBZ t,1F goto 1F; SET n,0 n = 0; POP 1,0 return n; 1H DIVU ndivb,n,b ndivb = n / b; GET nmodb,:rR nmodb = n % b; BZ ndivb,1F if (ndivb == 0) goto 1F; SET bb,b bb = b; GET rJ,:rJ rJ = :rJ; PUSHJ hole,1B 1B(ndivb, bb); PUT :rJ,rJ :rJ = rJ; 1H CMPU t,nmodb,9 if (nmodb > 9) BP t,1F goto 1F; ADDU nmodb,nmodb,'0' nmodb += '0'; JMP 2F goto 2F; 1H SUBU nmodb,nmodb,10 nmodb -= 10; ADDU nmodb,nmodb,'A' nmodb += 'A'; 2H STBU nmodb,digit *digit = (char)nmodb; LDA t,digit t = &digit; TRAP 0,:Fputs,:StdOut fputs(t, stdout); SET n,1 n = 1; POP 1,0 return n; AvsluttKodesegment * Slutt på printX.mmS. #endif
rc4.mmS
: MMIXAL implementation of ARC4:
#ifndef _rc4_mmS #define _rc4_mmS #include "MMIX.mmS" PREFIX :rc4: StartDatasegment OctaalignDatasegment GREG @ ii OCTA 0 jj OCTA 0 S IS @ LOC @+256 GREG @ AvsluttDatasegment StartKodesegment PREFIX :rc4:keyinit: * void keyinit(unsigned char *K, size_t n); K IS $0 n IS $1 i IS $2 tofemseks IS $3 p IS $4 j IS $5 k IS $6 Si IS $7 Sj IS $8 Kk IS $9 t IS $255 :rc4:keyinit SETL tofemseks,#0100 tofemseks = 0x0100; LDA p,:rc4:S p = &:rc4:S; 1H STBU i,p,i *(p + i) = (unsigned char)i; ADDU i,i,1 i++; CMPU t,i,tofemseks if (i != tofemseks) PBNZ t,1B goto 1B; SET i,0 i = 0; 1H DIVU k,i,n k = i / n, :rR = i % n; GET k,:rR k = :rR; LDBU Si,p,i Si = (unsigned char)*(p + i); LDBU Kk,K,k Kk = (unsigned char)K[k]; ADDU j,j,Si j += Si; ADDU j,j,Kk j += Kk; DIVU j,j,tofemseks j /= tofemseks, :rR = j % tofemseks; GET j,:rR j = :rR; LDBU Sj,p,j Sj = (unsigned char)*(p + j); STBU Si,p,j *(p + I) = (unsigned char)Sj; STBU Sj,p,i *(p + j) = (unsigned char)Si; ADDU i,i,1 i++; CMPU t,i,tofemseks if (i != tofemseks) PBNZ t,1B goto 1B; SET t,0 t = 0; LDA p,:rc4:ii p = ⅈ STBU t,p *p = (unsigned char)t; LDA p,:rc4:jj p = &jj; STBU t,p *p = (unsigned char)t; POP 0,0 return; PREFIX :rc4:transform: * void transform(unsigned char *B, size_t n); B IS $0 n IS $1 p IS $2 i IS $3 j IS $4 tofemseks IS $5 Si IS $6 Sj IS $7 bb IS $8 t IS $255 1H ADDU i,i,1 i++; DIVU i,i,tofemseks i /= tofemseks, :rR = i % tofemseks; GET i,:rR i = :rR; LDBU Si,p,i Si = (unsigned char)*(p + i); ADDU j,j,Si j += Si; DIVU j,j,tofemseks j /= tofemseks, :rR = j % tofemseks; GET j,:rR j = :rR; LDBU Sj,p,j Sj = (unsigned char)*(p + j); STBU Si,p,j *(p + j) = (unsigned char)Si; STBU Sj,p,i *(p + i) = (unsigned char)Sj; ADDU t,Si,Sj t = Si + Sj; DIVU t,t,tofemseks t /= tofemseks, :rR = t % tofemseks; GET t,:rR t = :rR; LDBU t,p,t t = (unsigned char)*(p + t); LDBU bb,B bb = (unsigned char)*B; XOR bb,bb,t bb ^= t; STBU bb,B *B = (unsigned char)bb; ADDU B,B,1 B++; SUBU n,n,1 n--; 1H PBNZ n,1B if (n != 0) goto 1B; LDA p,:rc4:ii p = &:rc4:ii; STBU i,p *p = (unsigned char)i; LDA p,:rc4:jj p = &:rc4:jj; STBU j,p *p = (unsigned char)j; SET t,0 t = 0; POP 0,0 return; :rc4:transform LDA p,:rc4:ii p = &:rc4:ii; LDBU i,p i = (unsigned char)*p; LDA p,:rc4:jj p = &:rc4:jj; LDBU j,p j = (unsigned char)*p; LDA p,:rc4:S p = &:rc4:S; SETL tofemseks,#0100 tofemseks = 0x0100; JMP 1B goto 1B; AvsluttKodesegment * Slutt på rc4.mmS. #endif
rotate.mmS
: MMIXAL implementations of rotl()
and rotr()
:
#ifndef _rotate_mmS #define _rotate_mmS #include "MMIX.mmS" PREFIX :rotate: * unsigned long long rotl(unsigned long long x, unsigned long long n, unsigned long long w); * unsigned long long rotr(unsigned long long x, unsigned long long n, unsigned long long w); x IS $0 n IS $1 w IS $2 StartKodesegment :rotl SUBU w,w,n w -= n; SRU w,x,w w = x >> w; SLU x,x,n x <<= n; OR x,x,w x |= w; POP 1,0 return x; :rotr SUBU w,w,n w -= n; SLU w,x,w w = x << w; SRU x,x,n x >>= n; OR x,x,w x |= w; POP 1,0 return x; AvsluttKodesegment * Slutt på rotate.mmS. #endif
strchr.mmS
: MMIXAL implementation of strchr()
:
#ifndef _strchr_mmS #define _strchr_mmS #include "MMIX.mmS" PREFIX :strchr: * char *strchr(const char *p, int c); p IS $0 c IS $1 cc IS $2 t IS $255 StartKodesegment 1H ADDU p,p,1 p++; :strchr LDBU cc,p cc = *p; CMPU t,cc,c if (cc == c) BZ t,1F goto 1F; BNZ cc,1B if (cc != 0) goto 1B; SET p,0 p = 0; 1H POP 1,0 return p; AvsluttKodesegment * Slutt på strchr.mmS. #endif
strcpy.mmS
: MMIXAL implementation of strcpy()
:
#ifndef _strcpy_mmS #define _strcpy_mmS #include "MMIX.mmS" PREFIX :strcpy: * char *strcpy(char *s1, const char *s2); s1 IS $0 s2 IS $1 s3 IS $2 t IS $255 StartKodesegment 2H ADDU s3,s3,1 s3++; ADDU s2,s2,1 s2++; 1H LDBU t,s2 t = *s2; STBU t,s3 *s3 = t; PBNZ t,2B if (t != 0) goto 2B; POP 1,0 return s1; :strcpy SET s3,s1 s3 = s1; JMP 1B goto 1B; AvsluttKodesegment * Slutt på strcpy.mmS. #endif
strerror.mmS
: MMIXAL implementation of strerror()
:
#ifndef _strerror_mmS #define _strerror_mmS #include "errno.mmS" #include "sys_errlist.mmS" PREFIX :strerror: * const char *strerror(int errnum); errnum IS $0 t IS $255 StartKodesegment :strerror GETA t,:sys_errlist t = &:sys_errlist; 8ADDU errnum,errnum,t errnum = 8 * errnum + t; LDOU errnum,errnum errnum = *errnum; POP 1,0 return errnum; AvsluttKodesegment * Slutt på strerror.mmS. #endif
strlen.mmS
: MMIXAL implementation of strlen()
:
#ifndef _strlen_mmS #define _strlen_mmS #include "MMIX.mmS" PREFIX :strlen: * unsigned long long strlen(const char *p); p IS $0 pp IS $1 t IS $255 StartKodesegment 2H ADDU pp,pp,1 pp++; 1H LDBU t,pp t = *pp; PBNZ t,2B if (t != 0) goto 2B; SUBU p,pp,p p = pp - p; POP 1,0 return p; :strlen SET pp,p pp = p; JMP 1B goto 1B; AvsluttKodesegment * Slutt på strlen.mmS. #endif
strncpy.mmS
: MMIXAL implementation of strncpy()
:
#ifndef _strncpy_mmS #define _strncpy_mmS #include "MMIX.mmS" PREFIX :strncpy: * char *strncpy(char *s1, const char *s2, unsigned long long len); s1 IS $0 s2 IS $1 len IS $2 s3 IS $3 t IS $255 StartKodesegment :strncpy SET s3,s1 s3 = s1; JMP 1F goto 1F; 2H ADDU s3,s3,1 s3++; ADDU s2,s2,1 s2++; SUBU len,len,1 len--; 1H BZ len,1F if (len == 0) goto 1F; LDBU t,s2 t = *s2; STBU t,s3 *s3 = t; PBNZ t,2B if (t != 0) goto 2B; 1H POP 1,0 return s1; AvsluttKodesegment * Slutt på strncpy.mmS. #endif
strrchr.mmS
: MMIXAL implementation of strrchr()
:
#ifndef _strrchr_mmS #define _strrchr_mmS #include "strlen.mmS" PREFIX :strrchr: * char *strrchr(const char *p, int c); p IS $0 c IS $1 rJ IS $2 len IS $3 pp IS $4 ppp IS $2 cc IS $3 t IS $255 StartKodesegment :strrchr SET pp,p pp = p; GET rJ,:rJ rJ = :rJ; PUSHJ len,:strlen len = :strlen(pp); PUT :rJ,rJ :rJ = rJ; SET ppp,p ppp = p; ADDU p,p,len p += len; JMP 1F goto 1F; 3H CMPU t,p,ppp if (p < ppp) BN t,4F goto 4F; 1H LDBU cc,p cc = *p; CMPU t,cc,c if (cc == c) BZ t,2F goto 2F; SUBU p,p,1 p--; JMP 3B goto 3B; 4H SET p,0 p = 0; 2H POP 1,0 return p; AvsluttKodesegment * Slutt på strrchr.mmS. #endif
strstr.mmS
: MMIXAL implementation of strstr()
:
#ifndef _strstr_mmS #define _strstr_mmS #include "MMIX.mmS" PREFIX :strstr: * char *strstr(const char *big, const char *little); big IS $0 little IS $1 cl IS $2 cb IS $3 big2 IS $4 i IS $5 t IS $255 StartKodesegment :strstr LDBU cl,little cl = *little; PBNZ cl,1F if (cl != 0) goto 1F; POP 1,0 return big; 1H LDBU cb,big cb = *big; CMPU t,cb,cl if (cb == cl) BZ t,2F goto 2F; BZ cb,6F if (cb == 0) goto 6F; ADDU big,big,1 big++; JMP 1B goto 1B; 2H ADDU big2,big,1 big2 = big + 1; SET i,1 i = 1; 4H LDBU cb,big2 cb = *big2; LDBU cl,little,i cl = little[i]; CMPU t,cb,cl if (cb != cl) BNZ t,3F goto 3F; ADDU i,i,1 i++; LDBU cl,little,i cl = little[i]; BZ cl,7F if (cl == 0) goto 7F; ADDU big2,big2,1 big2++; JMP 4B goto 4B; 3H LDBU cb,big2 cb = *big2; BZ cb,6F if (cb == 0) goto 6F; SET big,big2 big = big2; LDBU cl,little cl = *little; JMP 1B goto 1B; 6H SET big,0 big = 0; 7H POP 1,0 return big; AvsluttKodesegment * Slutt på strstr.mmS. #endif
sys_errlist.mmS
: MMIXAL implementation of sys_errlist[]
based on FreeBSD 4.10, the operating system on my development system back in 2004:
#ifndef _sys_errlist_mmS #define _sys_errlist_mmS #include "MMIX.mmS" #if 0 /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)errno.h 8.5 (Berkeley) 1/21/94 * $FreeBSD: release/4.10.0/sys/sys/errno.h 128520 2004-04-21 11:08:56Z cvs2svn $ */ #endif PREFIX :sys_errlist: StartKodesegment ENOERR BYTE "Undefined error",0 TetraalignKodesegment EPERM BYTE "Operation not permitted",0 TetraalignKodesegment ENOENT BYTE "No such file or directory",0 TetraalignKodesegment ESRCH BYTE "No such process",0 TetraalignKodesegment EINTR BYTE "Interrupted system call",0 TetraalignKodesegment EIO BYTE "Input/output error",0 TetraalignKodesegment ENXIO BYTE "Device not configured",0 TetraalignKodesegment E2BIG BYTE "Argument list too long",0 TetraalignKodesegment ENOEXEC BYTE "Exec format error",0 TetraalignKodesegment EBADF BYTE "Bad file descriptor",0 TetraalignKodesegment ECHILD BYTE "No child processes",0 TetraalignKodesegment EDEADLK BYTE "Resource deadlock avoided",0 TetraalignKodesegment ENOMEM BYTE "Cannot allocate memory",0 TetraalignKodesegment EACCES BYTE "Permission denied",0 TetraalignKodesegment EFAULT BYTE "Bad address",0 TetraalignKodesegment ENOTBLK BYTE "Block device required",0 TetraalignKodesegment EBUSY BYTE "Device busy",0 TetraalignKodesegment EEXIST BYTE "File exists",0 TetraalignKodesegment EXDEV BYTE "Cross-device link",0 TetraalignKodesegment ENODEV BYTE "Operation not supported by device",0 TetraalignKodesegment ENOTDIR BYTE "Not a directory",0 TetraalignKodesegment EISDIR BYTE "Is a directory",0 TetraalignKodesegment EINVAL BYTE "Invalid argument",0 TetraalignKodesegment ENFILE BYTE "Too many open files in system",0 TetraalignKodesegment EMFILE BYTE "Too many open files",0 TetraalignKodesegment ENOTTY BYTE "Inappropriate ioctl for device",0 TetraalignKodesegment ETXTBSY BYTE "Text file busy",0 TetraalignKodesegment EFBIG BYTE "File too large",0 TetraalignKodesegment ENOSPC BYTE "No space left on device",0 TetraalignKodesegment ESPIPE BYTE "Illegal seek",0 TetraalignKodesegment EROFS BYTE "Read-only file system",0 TetraalignKodesegment EMLINK BYTE "Too many links",0 TetraalignKodesegment EPIPE BYTE "Broken pipe",0 TetraalignKodesegment EDOM BYTE "Numerical argument out of domain",0 TetraalignKodesegment ERANGE BYTE "Result too large",0 TetraalignKodesegment EAGAIN BYTE "Resource temporarily unavailable",0 TetraalignKodesegment EWOULDBLOCK BYTE "Operation would block",0 TetraalignKodesegment EINPROGRESS BYTE "Operation now in progress",0 TetraalignKodesegment EALREADY BYTE "Operation already in progress",0 TetraalignKodesegment ENOTSOCK BYTE "Socket operation on non-socket",0 TetraalignKodesegment EDESTADDRREQ BYTE "Destination address required",0 TetraalignKodesegment EMSGSIZE BYTE "Message too long",0 TetraalignKodesegment EPROTOTYPE BYTE "Protocol wrong type for socket",0 TetraalignKodesegment ENOPROTOOPT BYTE "Protocol not available",0 TetraalignKodesegment EPROTONOSUPPORT BYTE "Protocol not supported",0 TetraalignKodesegment ESOCKTNOSUPPORT BYTE "Socket type not supported",0 TetraalignKodesegment EOPNOTSUPP BYTE "Operation not supported",0 TetraalignKodesegment EPFNOSUPPORT BYTE "Protocol family not supported",0 TetraalignKodesegment EAFNOSUPPORT BYTE "Address family not supported by protocol family",0 TetraalignKodesegment EADDRINUSE BYTE "Address already in use",0 TetraalignKodesegment EADDRNOTAVAIL BYTE "Can't assign requested address",0 TetraalignKodesegment ENETDOWN BYTE "Network is down",0 TetraalignKodesegment ENETUNREACH BYTE "Network is unreachable",0 TetraalignKodesegment ENETRESET BYTE "Network dropped connection on reset",0 TetraalignKodesegment ECONNABORTED BYTE "Software caused connection abort",0 TetraalignKodesegment ECONNRESET BYTE "Connection reset by peer",0 TetraalignKodesegment ENOBUFS BYTE "No buffer space available",0 TetraalignKodesegment EISCONN BYTE "Socket is already connected",0 TetraalignKodesegment ENOTCONN BYTE "Socket is not connected",0 TetraalignKodesegment ESHUTDOWN BYTE "Can't send after socket shutdown",0 TetraalignKodesegment ETOOMANYREFS BYTE "Too many references: can't splice",0 TetraalignKodesegment ETIMEDOUT BYTE "Operation timed out",0 TetraalignKodesegment ECONNREFUSED BYTE "Connection refused",0 TetraalignKodesegment ELOOP BYTE "Too many levels of symbolic links",0 TetraalignKodesegment ENAMETOOLONG BYTE "File name too long",0 TetraalignKodesegment EHOSTDOWN BYTE "Host is down",0 TetraalignKodesegment EHOSTUNREACH BYTE "No route to host",0 TetraalignKodesegment ENOTEMPTY BYTE "Directory not empty",0 TetraalignKodesegment EPROCLIM BYTE "Too many processes",0 TetraalignKodesegment EUSERS BYTE "Too many users",0 TetraalignKodesegment EDQUOT BYTE "Disc quota exceeded",0 TetraalignKodesegment ESTALE BYTE "Stale NFS file handle",0 TetraalignKodesegment EREMOTE BYTE "Too many levels of remote in path",0 TetraalignKodesegment EBADRPC BYTE "RPC struct is bad",0 TetraalignKodesegment ERPCMISMATCH BYTE "RPC version wrong",0 TetraalignKodesegment EPROGUNAVAIL BYTE "RPC prog. not avail",0 TetraalignKodesegment EPROGMISMATCH BYTE "Program version wrong",0 TetraalignKodesegment EPROCUNAVAIL BYTE "Bad procedure for program",0 TetraalignKodesegment ENOLCK BYTE "No locks available",0 TetraalignKodesegment ENOSYS BYTE "Function not implemented",0 TetraalignKodesegment EFTYPE BYTE "Inappropriate file type or format",0 TetraalignKodesegment EAUTH BYTE "Authentication error",0 TetraalignKodesegment ENEEDAUTH BYTE "Need authenticator",0 TetraalignKodesegment EIDRM BYTE "Identifier removed",0 TetraalignKodesegment ENOMSG BYTE "No message of desired type",0 TetraalignKodesegment EOVERFLOW BYTE "Value too large to be stored in data type",0 TetraalignKodesegment ECANCELED BYTE "Operation canceled",0 TetraalignKodesegment EILSEQ BYTE "Illegal byte sequence",0 TetraalignKodesegment EERR BYTE "Unknown error",0 :sys_errlist OCTA ENOERR OCTA EPERM OCTA ENOENT OCTA ESRCH OCTA EINTR OCTA EIO OCTA ENXIO OCTA E2BIG OCTA ENOEXEC OCTA EBADF OCTA ECHILD OCTA EDEADLK OCTA ENOMEM OCTA EACCES OCTA EFAULT OCTA ENOTBLK OCTA EBUSY OCTA EEXIST OCTA EXDEV OCTA ENODEV OCTA ENOTDIR OCTA EISDIR OCTA EINVAL OCTA ENFILE OCTA EMFILE OCTA ENOTTY OCTA ETXTBSY OCTA EFBIG OCTA ENOSPC OCTA ESPIPE OCTA EROFS OCTA EMLINK OCTA EPIPE OCTA EDOM OCTA ERANGE OCTA EAGAIN OCTA EWOULDBLOCK OCTA EINPROGRESS OCTA EALREADY OCTA ENOTSOCK OCTA EDESTADDRREQ OCTA EMSGSIZE OCTA EPROTOTYPE OCTA ENOPROTOOPT OCTA EPROTONOSUPPORT OCTA ESOCKTNOSUPPORT OCTA EOPNOTSUPP OCTA EPFNOSUPPORT OCTA EAFNOSUPPORT OCTA EADDRINUSE OCTA EADDRNOTAVAIL OCTA ENETDOWN OCTA ENETUNREACH OCTA ENETRESET OCTA ECONNABORTED OCTA ECONNRESET OCTA ENOBUFS OCTA EISCONN OCTA ENOTCONN OCTA ESHUTDOWN OCTA ETOOMANYREFS OCTA ETIMEDOUT OCTA ECONNREFUSED OCTA ELOOP OCTA ENAMETOOLONG OCTA EHOSTDOWN OCTA EHOSTUNREACH OCTA ENOTEMPTY OCTA EPROCLIM OCTA EUSERS OCTA EDQUOT OCTA ESTALE OCTA EREMOTE OCTA EBADRPC OCTA ERPCMISMATCH OCTA EPROGUNAVAIL OCTA EPROGMISMATCH OCTA EPROCUNAVAIL OCTA ENOLCK OCTA ENOSYS OCTA EFTYPE OCTA EAUTH OCTA ENEEDAUTH OCTA EIDRM OCTA ENOMSG OCTA EOVERFLOW OCTA ECANCELED OCTA EILSEQ OCTA EERR OCTA 0 AvsluttKodesegment * Slutt på sys_errlist.mmS. #endif
tolower.mmS
: MMIXAL implementation of tolower()
:
#ifndef _tolower_mmS #define _tolower_mmS #include "MMIX.mmS" PREFIX :tolower: * int tolower(int c); c IS $0 t IS $255 StartKodesegment :tolower CMPU t,c,'A' if (c < 'A') BN t,1F goto 1F; CMPU t,c,'Z' if (c > 'Z') BP t,1F goto 1F; ADDU c,c,'a'-'A' c += 'a' - 'A'; 1H POP 1,0 return c; AvsluttKodesegment * Slutt på tolower.mmS. #endif
toupper.mmS
: MMIXAL implementation of toupper()
:
#ifndef _toupper_mmS #define _toupper_mmS #include "MMIX.mmS" PREFIX :toupper: * int toupper(int c); c IS $0 t IS $255 StartKodesegment :toupper CMPU t,c,'a' if (c < 'a') BN t,1F goto 1F; CMPU t,c,'z' if (c > 'z') BP t,1F goto 1F; SUBU c,c,'a'-'A' c -= 'a' - 'A'; 1H POP 1,0 return c; AvsluttKodesegment * Slutt på toupper.mmS. #endif
Here's a small test program for the above code. It seems I was trying to test an unpublished malloc()
implementation. I might revisit that implementation someday (and maybe even publish it once I get it working correctly).
#include "abort.mmS" #include "bzero.mmS" #include "errno.mmS" #include "isalnum.mmS" #include "isalpha.mmS" #include "isascii.mmS" #include "iscntrl.mmS" #include "isdigit.mmS" #include "isgraph.mmS" #include "islower.mmS" #include "isspace.mmS" #include "isupper.mmS" #include "malloc.mmS" #include "memset.mmS" #include "perror.mmS" #include "printX.mmS" #include "rc4.mmS" #include "rotate.mmS" #include "strchr.mmS" #include "strcpy.mmS" #include "strlen.mmS" #include "strncpy.mmS" #include "strrchr.mmS" #include "strstr.mmS" #include "tolower.mmS" #include "toupper.mmS" PREFIX :Main: * StartDatasegment * OctaalignDatasegment * buffer LOC @+1024 * bufferslutt IS @ * bufferlengde IS bufferslutt-buffer * GREG @ * rc4key BYTE "Dette er nøkkelen!",0 * rc4buffer BYTE "Denne teksten skal krypteres med RC4!",#0A,0 * AvsluttDatasegment * int main(int argc, char **argv); argc IS $0 argv IS $1 * len IS $2 * p IS $3 * hole IS $3 * s1 IS $4 * s2 IS $5 * len2 IS $6 * n IS $4 * b IS $5 * rc4hole IS $2 * rc4arg1 IS $3 * rc4arg2 IS $4 len IS $2 p1 IS $3 size1 IS $4 p2 IS $4 size2 IS $5 t IS $255 StartKodesegment * tekst BYTE "Hei på deg, din gamle sei!",#0A,0 * TetraalignKodesegment * big BYTE "En lang tekststreng med mange ord",0 * TetraalignKodesegment * little BYTE "man",0 * TetraalignKodesegment * newline BYTE #0A,0 :Main SWYM * GETA p,tekst Beregne lengden av tekst. * PUSHJ len,:strlen * LDA s1,buffer Kopiere tekst til buffer. * GETA s2,tekst * ADDU len2,len,1 * PUSHJ hole,:strncpy * LDA t,buffer Skrive ut buffer på StdOut. * TRAP 0,:Fputs,:StdOut * SET n,2009 Skrive ut 2009 desimalt. * SET b,10 * PUSHJ hole,:printX * GETA t,newline Skrive ut et linjeskift. * TRAP 0,:Fputs,:StdOut * SET n,2009 Skrive ut 2009 heksadesimalt. * SET b,16 * PUSHJ hole,:printX * GETA t,newline Skrive ut et linjeskift. * TRAP 0,:Fputs,:StdOut * SET n,2009 Skrive ut 2009 binært. * SET b,2 * PUSHJ hole,:printX * GETA t,newline Skrive ut et linjeskift. * TRAP 0,:Fputs,:StdOut * GETA s1,big Søke etter substreng. * GETA s2,little * PUSHJ hole,:strstr * GETA s1,big Skrive ut en feilmelding. * PUSHJ hole,:perror * SET :errno,34 * GETA s1,big * PUSHJ hole,:perror * SET :errno,2009 * GETA s1,big * PUSHJ hole,:perror * PUSHJ hole,:abort Teste abort(). * Først skrive ut teksten og kryptere den: * LDA t,rc4buffer * TRAP 0,:Fputs,:StdOut * LDA rc4arg1,rc4key * PUSHJ rc4hole,:strlen * SET rc4arg2,rc4hole * LDA rc4arg1,rc4key * PUSHJ rc4hole,:rc4:keyinit * LDA rc4arg1,rc4buffer * PUSHJ rc4hole,:strlen * SUBU rc4arg2,rc4hole,1 * LDA rc4arg1,rc4buffer * PUSHJ rc4hole,:rc4:transform * Ta sjansen på å skrive ut kryptoteksten: * LDA t,rc4buffer * TRAP 0,:Fputs,:StdOut * Deretter dekryptere den og skrive den ut: * LDA rc4arg1,rc4key * PUSHJ rc4hole,:strlen * SET rc4arg2,rc4hole * LDA rc4arg1,rc4key * PUSHJ rc4hole,:rc4:keyinit * LDA rc4arg1,rc4buffer * PUSHJ rc4hole,:strlen * SUBU rc4arg2,rc4hole,1 * LDA rc4arg1,rc4buffer * PUSHJ rc4hole,:rc4:transform * LDA t,rc4buffer * TRAP 0,:Fputs,:StdOut SET size1,1800 PUSHJ p1,:malloc SETH size2,#2000 PUSHJ p2,:malloc SET t,0 t = 0; TRAP 0,:Halt,0 _exit(t); AvsluttKodesegment * Slutt på main.mmS.
Finally, here's a GNUmakefile
driving the assembler:
# GNU Makefile for forhåndsbehandling av MMIX assemblykode. # # Copyright © 2004 Trond Endrestøl <Trond.Endrestol@ximalas.info> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # CPP= cpp MMIXAL= mmixal MMIX= mmix RM= rm %.mms: %.mmS GNUmakefile $(CPP) -nostdinc - - < $< > $@ %.mmo: %.mms GNUmakefile $(MMIXAL) -l $(basename $<).mml -b 1024 $< %.mmb: %.mmo GNUmakefile $(MMIX) -D$(basename $>).mmb $< || true all: main.mmb rc4transform.mmb main.mmb: main.mmo main.mmo: main.mms main.mms: main.mmS \ MMIX.mmS \ abort.mmS \ bzero.mmS \ errno.mmS \ isalnum.mmS \ isalpha.mmS \ isascii.mmS \ iscntrl.mmS \ isdigit.mmS \ isgraph.mmS \ islower.mmS \ isspace.mmS \ isupper.mmS \ malloc.mmS \ memset.mmS \ perror.mmS \ printX.mmS \ rc4.mmS \ rotate.mmS \ strchr.mmS \ strcpy.mmS \ strlen.mmS \ strncpy.mmS \ strrchr.mmS \ strstr.mmS \ sys_errlist.mmS \ tolower.mmS \ toupper.mmS rc4transform.mmb: rc4transform.mmo rc4transform.mmo: rc4transform.mms rc4transform.mms: rc4transform.mmS MMIX.mmS strlen.mmS rc4.mmS clean: $(RM) -f *.mmb *.mml *.mmo *.mms # Slutt på GNUmakefile.