#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>

#define DOUBLE_SPACE 1

#if DOUBLE_SPACE
#	define SPC "　"
#else
#	define SPC " "
#endif

wchar_t glyph[] = L""SPC"│││─┘┐┤─└┌├─┴┬┼"SPC"┆┆┆┄╯╮ ┄╰╭ ┄";

typedef unsigned char byte;
enum { N = 1, S = 2, W = 4, E = 8, V = 16 };

byte **cell;
int w, h, avail;
#define each(i, x, y) for (i = x; i <= y; i++)

int irand(int n)
{
	int r, rmax = n * (RAND_MAX / n);
	while ((r = rand()) >= rmax);
	return r / (RAND_MAX/n);
}

void show()
{
	int i, j, c;
	each(i, 0, 2 * h) {
		each(j, 0, 2 * w) {
			c = cell[i][j];
			if (c > V) printf("\033[31m");
			printf("%lc", glyph[c]);
			if (c > V) printf("\033[m");
		}
		putchar('\n');
	}
}

inline int max(int a, int b) { return a >= b ? a : b; }
inline int min(int a, int b) { return b >= a ? a : b; }

static int dirs[4][2] = {{-2, 0}, {0, 2}, {2, 0}, {0, -2}};
void walk(int x, int y)
{
	int i, t, x1, y1, d[4] = { 0, 1, 2, 3 };

	cell[y][x] |= V;
	avail--;

	for (x1 = 3; x1; x1--)
		if (x1 != (y1 = irand(x1 + 1)))
			i = d[x1], d[x1] = d[y1], d[y1] = i;

	for (i = 0; avail && i < 4; i++) {
		x1 = x + dirs[ d[i] ][0], y1 = y + dirs[ d[i] ][1];

		if (cell[y1][x1] & V) continue;

		/* break walls */
		if (x1 == x) {
			t = (y + y1) / 2;
			cell[t][x+1] &= ~W, cell[t][x] &= ~(E|W), cell[t][x-1] &= ~E;
		} else if (y1 == y) {
			t = (x + x1)/2;
			cell[y-1][t] &= ~S, cell[y][t] &= ~(N|S), cell[y+1][t] &= ~N;
		}
		walk(x1, y1);
	}
}

int solve(int x, int y, int tox, int toy)
{
	int i, t, x1, y1;

	cell[y][x] |= V;
	if (x == tox && y == toy) return 1;

	each(i, 0, 3) {
		x1 = x + dirs[i][0], y1 = y + dirs[i][1];
		if (cell[y1][x1]) continue;

		/* mark path */
		if (x1 == x) {
			t = (y + y1)/2;
			if (cell[t][x] || !solve(x1, y1, tox, toy)) continue;

			cell[t-1][x] |= S, cell[t][x] |= V|N|S, cell[t+1][x] |= N;
		} else if (y1 == y) {
			t = (x + x1)/2;
			if (cell[y][t] || !solve(x1, y1, tox, toy)) continue;

			cell[y][t-1] |= E, cell[y][t] |= V|E|W, cell[y][t+1] |= W;
		}
		return 1;
	}

	/* backtrack */
	cell[y][x] &= ~V;
	return 0;
}

void make_maze()
{
	int i, j;
	int h2 = 2 * h + 2, w2 = 2 * w + 2;
	byte **p;

	p = calloc(sizeof(byte*) * (h2 + 2) + w2 * h2 + 1, 1);

	p[1] = (byte*)(p + h2 + 2) + 1;
	each(i, 2, h2) p[i] = p[i-1] + w2;
	p[0] = p[h2];
	cell = &p[1];

	each(i, -1, 2 * h + 1) cell[i][-1] = cell[i][w2 - 1] = V;
	each(j, 0, 2 * w) cell[-1][j] = cell[h2 - 1][j] = V;
	each(i, 0, h) each(j, 0, 2 * w) cell[2*i][j] |= E|W;
	each(i, 0, 2 * h) each(j, 0, w) cell[i][2*j] |= N|S;
	each(j, 0, 2 * w) cell[0][j] &= ~N, cell[2*h][j] &= ~S;
	each(i, 0, 2 * h) cell[i][0] &= ~W, cell[i][2*w] &= ~E;

	avail = w * h;
	walk(irand(2) * 2 + 1, irand(h) * 2 + 1);

	/* reset visited marker (it's also used by path finder) */
	each(i, 0, 2 * h) each(j, 0, 2 * w) cell[i][j] &= ~V;
	solve(1, 1, 2 * w - 1, 2 * h - 1);

	show();
}

int main(int c, char **v)
{
	setlocale(LC_ALL, "");
	if (c < 2 || (w = atoi(v[1])) <= 0) w = 16;
	if (c < 3 || (h = atoi(v[2])) <= 0) h = 8;

	make_maze();

	return 0;
}

Sample output:
┌───┬─────┬─────────┬───────┬───┐
│┄┄╮│╭┄┄┄╮│　　╭┄┄┄┄┄╮│　　╭┄┄┄╮│╭┄╮│
│　│┆│┆──┐┆│　│┆──┬─┐┆└──┆┌─┐┆│┆│┆│
│　│┆│╰┄╮│┆│　│╰┄╮│　│╰┄┄┄╯│　│╰┄╯│┆│
│　│┆└──┆│┆└─┼──┆│　└─────┤　└─┬─┘┆│
│　│╰┄┄┄╯│╰┄╮│╭┄╯│　　　　　　　│　　　│╭┄╯│
│　└─────┴─┐┆│┆┌─┴───┐　│　│　│　│┆──┤
│　　　　　　　　　│┆│┆│╭┄┄┄╮│　│　　　│　│╰┄╮│
│　──────┐　│┆│┆│┆──┐┆└─┤　┌─┘　└─┐┆│
│　　　　　　　│　│┆│╰┄╯　　│╰┄╮│　│　　　　　│┆│
│　┌─────┘　│┆├─────┴─┐┆│　│　──┬─┘┆│
│　│　　　　　　　│┆│╭┄┄┄┄┄╮│┆│　│　　　│╭┄╯│
├─┤　──┬─┬─┘┆│┆┌─┬──┆│┆└─┴─┐　│┆┌─┤
│　│　　　│　│╭┄╯│┆│　│╭┄╯│╰┄┄┄╮│　│┆│　│
│　└──　│　│┆──┘┆│　│┆──┴────┆│　│┆│　│
│　　　　　│　　╰┄┄┄╯│　　╰┄┄┄┄┄┄┄╯│　　╰┄┄│
└─────┴───────┴───────────┴─────┘

generate and display a maze using the Depth-first search algorithm. It starts at a random cell, marks it as visited, and processes its neighbors. If a neighbor has not been visited, it removes the wall between the current cell and the neighbor, then recursively repeats the process with the neighbor as the current cell. The code requires a UTF8 locale and a unicode capable console. If the console font line-drawing characters are single width, it sets DOUBLE_SPACE to 0.


Digits

Spigot 1

Spigot 2

Machin 1

Machin 2

AGM

Chudnovsky

1,000

0.008

0.009

0.001

0.001

0.000

0.000

10,000

0.402

0.589

0.020

0.016

0.003

0.002

100,000

39.400

85.600

1.740

1.480

0.084

0.002

1,000,000

177.900

156.800

1.474

0.333

10,000,000

25.420

5.715

Spigot 1: plain C (no GMP), modified Winter/Flammenkamp, correct to 1+M digits
Spigot 2: C+GMP, as used in Computer Language Benchmarks Game
Machin 1: C+GMP, shown below
Machin 2: C+GMP, as below but using Chien-Lih 1997 formula
AGM: C+GMP, essentially from the Arithmetic-geometric mean/Calculate Pi task.  This has performance only slightly slower than MPFR.
Chudnovsky: Hanhong Xue's code from GMP web site.

#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>

mpz_t tmp1, tmp2, t5, t239, pows;
void actan(mpz_t res, unsigned long base, mpz_t pows)
{
	int i, neg = 1;
	mpz_tdiv_q_ui(res, pows, base);
	mpz_set(tmp1, res);
	for (i = 3; ; i += 2) {
		mpz_tdiv_q_ui(tmp1, tmp1, base * base);
		mpz_tdiv_q_ui(tmp2, tmp1, i);
		if (mpz_cmp_ui(tmp2, 0) == 0) break;
		if (neg) mpz_sub(res, res, tmp2);
		else	  mpz_add(res, res, tmp2);
		neg = !neg;
	}
}

char * get_digits(int n, size_t* len)
{
	mpz_ui_pow_ui(pows, 10, n + 20);

	actan(t5, 5, pows);
	mpz_mul_ui(t5, t5, 16);

	actan(t239, 239, pows);
	mpz_mul_ui(t239, t239, 4);

	mpz_sub(t5, t5, t239);
	mpz_ui_pow_ui(pows, 10, 20);
	mpz_tdiv_q(t5, t5, pows);

	*len = mpz_sizeinbase(t5, 10);
	return mpz_get_str(0, 0, t5);
}

int main(int c, char **v)
{
	unsigned long accu = 16384, done = 0;
	size_t got;
	char *s;

	mpz_init(tmp1);
	mpz_init(tmp2);
	mpz_init(t5);
	mpz_init(t239);
	mpz_init(pows);

	while (1) {
		s = get_digits(accu, &got);

		/* write out digits up to the last one not preceding a 0 or 9*/
		got -= 2; /* -2: length estimate may be longer than actual */
		while (s[got] == '0' || s[got] == '9') got--;

		printf("%.*s", (int)(got - done), s + done);
		free(s);

		done = got;

		/* double the desired digits; slows down at least cubically */
		accu *= 2;
	}

	return 0;
}

The code continually calculates and outputs the next decimal digit of Pi, starting from 3.14159265 and continuing indefinitely until the user aborts the program. It uses Machin's formula for the calculation and is designed to handle a preset number of digits, recalculating Pi with increasing length and removing already displayed leading digits. The performance is faster than the unbounded Spigot method, especially for the first 100k digits.


int list_cmp(int *a, int la, int *b, int lb)
{
	int i, l = la;
	if (l > lb) l = lb;
	for (i = 0; i < l; i++) {
		if (a[i] == b[i]) continue;
		return (a[i] > b[i]) ? 1 : -1;
	}
	if (la == lb) return 0;
	return la > lb ? 1 : -1;
}

This funciton returns one of three states, not a boolean.  One can define boolean comparisons, such as list_less_or_eq, based on it:#define list_less_or_eq(a,b,c,d) (list_cmp(a,b,c,d) != 1)

"Function to compare and order two numerical lists lexicographically, returning true if the first list should be ordered before the second, and false otherwise."


#include <stdio.h>

int ackermann(int m, int n)
{
        if (!m) return n + 1;
        if (!n) return ackermann(m - 1, 1);
        return ackermann(m - 1, ackermann(m, n - 1));
}

int main()
{
        int m, n;
        for (m = 0; m <= 4; m++)
                for (n = 0; n < 6 - m; n++)
                        printf("A(%d, %d) = %d\n", m, n, ackermann(m, n));

        return 0;
}

Implement the Ackermann function, a non-primitive recursive function. The function takes two non-negative arguments and returns a value based on the conditions defined in the Ackermann function. The function is expected to terminate and return a value, with a preference for arbitrary precision due to the rapid growth of the function. The implementation also includes simple caching to handle the large number of recursive calls. However, for large m values, the function may result in a stack overflow due to the depth of recursion. Alternative iterative techniques and further optimizations may be possible.


Library: GNU Scientific Library

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gsl/gsl_sf_gamma.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

/* very simple approximation */
double st_gamma(double x)
{
  return sqrt(2.0*M_PI/x)*pow(x/M_E, x);
}

#define A 12
double sp_gamma(double z)
{
  const int a = A;
  static double c_space[A];
  static double *c = NULL;
  int k;
  double accm;

  if ( c == NULL ) {
    double k1_factrl = 1.0; /* (k - 1)!*(-1)^k with 0!==1*/
    c = c_space;
    c[0] = sqrt(2.0*M_PI);
    for(k=1; k < a; k++) {
      c[k] = exp(a-k) * pow(a-k, k-0.5) / k1_factrl;
	  k1_factrl *= -k;
    }
  }
  accm = c[0];
  for(k=1; k < a; k++) {
    accm += c[k] / ( z + k );
  }
  accm *= exp(-(z+a)) * pow(z+a, z+0.5); /* Gamma(z+1) */
  return accm/z;
}

int main()
{
  double x;

  printf("%15s%15s%15s%15s\n", "Stirling", "Spouge", "GSL", "libm");
  for(x=1.0; x <= 10.0; x+=1.0) {
    printf("%15.8lf%15.8lf%15.8lf%15.8lf\n", st_gamma(x/3.0), sp_gamma(x/3.0),
	   gsl_sf_gamma(x/3.0), tgamma(x/3.0));
  }
  return 0;
}

implement the Gamma function using numerical integration, Lanczos approximation, and Stirling's approximation. It also compares the results of the custom implementation with the built-in/library function if available.


C99, compiled with gcc -std=c99 -Wall.  Take one commandline argument: size of board, or default to 8. Shows the board layout for each solution.#include <stdio.h>
#include <stdlib.h>

int count = 0;
void solve(int n, int col, int *hist)
{
	if (col == n) {
		printf("\nNo. %d\n-----\n", ++count);
		for (int i = 0; i < n; i++, putchar('\n'))
			for (int j = 0; j < n; j++)
				putchar(j == hist[i] ? 'Q' : ((i + j) & 1) ? ' ' : '.');

		return;
	}

#	define attack(i, j) (hist[j] == i || abs(hist[j] - i) == col - j)
	for (int i = 0, j = 0; i < n; i++) {
		for (j = 0; j < col && !attack(i, j); j++);
		if (j < col) continue;

		hist[col] = i;
		solve(n, col + 1, hist);
	}
}

int main(int n, char **argv)
{
	if (n <= 1 || (n = atoi(argv[1])) <= 0) n = 8;
	int hist[n];
	solve(n, 0, hist);
}

Similiar to above, but using bits to save board configurations and quite a bit faster:#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef uint32_t uint;
uint full, *qs, count = 0, nn;

void solve(uint d, uint c, uint l, uint r)
{
	uint b, a, *s;
	if (!d) {
		count++;
#if 0
		printf("\nNo. %d\n===========\n", count);
		for (a = 0; a < nn; a++, putchar('\n'))
			for (b = 0; b < nn; b++, putchar(' '))
				putchar(" -QQ"[((b == qs[a])<<1)|((a + b)&1)]);
#endif
		return;
	}

	a = (c | (l <<= 1) | (r >>= 1)) & full;
	if (a != full)
		for (*(s = qs + --d) = 0, b = 1; b <= full; (*s)++, b <<= 1)
			if (!(b & a)) solve(d, b|c, b|l, b|r);
}

int main(int n, char **argv)
{
	if (n <= 1 || (nn = atoi(argv[1])) <= 0) nn = 8;

	qs = calloc(nn, sizeof(int));
	full = (1U << nn) - 1;

	solve(nn, 0, 0, 0);
	printf("\nSolutions: %d\n", count);
	return 0;
}

#include <stdio.h>
#include <stdlib.h>

typedef unsigned int uint;
uint count = 0;

#define ulen sizeof(uint) * 8

/* could have defined as int solve(...), but void may have less
   chance to confuse poor optimizer */
void solve(int n)
{
	int cnt = 0;
	const uint full = -(int)(1 << (ulen - n));
	register uint bits, pos, *m, d, e;

	uint b0, b1, l[32], r[32], c[32], mm[33] = {0};
	n -= 3;
	/* require second queen to be left of the first queen, so
	   we ever only test half of the possible solutions. This
	   is why we can't handle n=1 here */
	for (b0 = 1U << (ulen - n - 3); b0; b0 <<= 1) {
		for (b1 = b0 << 2; b1; b1 <<= 1) {
			d = n;
			/* c: columns occupied by previous queens.
			   l: columns attacked by left diagonals
			   r: by right diagnoals */
			c[n] = b0 | b1;
			l[n] = (b0 << 2) | (b1 << 1);
			r[n] = (b0 >> 2) | (b1 >> 1);

			/* availabe columns on current row. m is stack */
			bits = *(m = mm + 1) = full & ~(l[n] | r[n] | c[n]);

			while (bits) {
				/* d: depth, aka row. counting backwards
				   because !d is often faster than d != n */
				while (d) {
					/* pos is right most nonzero bit */
					pos = -(int)bits & bits;

					/* mark bit used. only put current bits
					   on stack if not zero, so backtracking
					   will skip exhausted rows (because reading
					   stack variable is sloooow compared to
					   registers) */
					if ((bits &= ~pos))
						*m++ = bits | d;

					/* faster than l[d+1] = l[d]... */
					e = d--;
					l[d] = (l[e] | pos) << 1;
					r[d] = (r[e] | pos) >> 1;
					c[d] =  c[e] | pos;

					bits = full & ~(l[d] | r[d] | c[d]);

					if (!bits) break;
					if (!d) { cnt++; break; }
				}
				/* Bottom of stack m is a zero'd field acting
				   as sentinel.  When saving to stack, left
				   27 bits are the available columns, while
				   right 5 bits is the depth. Hence solution
				   is limited to size 27 board -- not that it
				   matters in foreseeable future. */
				d = (bits = *--m) & 31U;
				bits &= ~31U;
			}
		}
	}
	count = cnt * 2;
}

int main(int c, char **v)
{
	int nn;
	if (c <= 1 || (nn = atoi(v[1])) <= 0) nn = 8;

	if (nn > 27) {
		fprintf(stderr, "Value too large, abort\n");
		exit(1);
	}

	/* Can't solve size 1 board; might as well skip 2 and 3 */
	if (nn < 4) count = nn == 1;
	else	    solve(nn);

	printf("\nSolutions: %d\n", count);
	return 0;
}

#include <stdio.h>
#define MAXN 31

int nqueens(int n)
{
  int q0,q1;
  int cols[MAXN], diagl[MAXN], diagr[MAXN], posibs[MAXN]; // Our backtracking 'stack'
  int num=0;
  //
  // The top level is two fors, to save one bit of symmetry in the enumeration by forcing second queen to
  // be AFTER the first queen.
  //
  for (q0=0; q0<n-2; q0++) {
    for (q1=q0+2; q1<n; q1++){
      int bit0 = 1<<q0;
      int bit1 = 1<<q1;
      int d=0; // d is our depth in the backtrack stack
      cols[0] = bit0 | bit1 | (-1<<n); // The -1 here is used to fill all 'coloumn' bits after n ...
      diagl[0]= (bit0<<1 | bit1)<<1;
      diagr[0]= (bit0>>1 | bit1)>>1;

      //  The variable posib contains the bitmask of possibilities we still have to try in a given row ...
      int posib = ~(cols[0] | diagl[0] | diagr[0]);

      while (d >= 0) {
        while(posib) {
          int bit = posib & -posib; // The standard trick for getting the rightmost bit in the mask
          int ncols= cols[d] | bit;
          int ndiagl = (diagl[d] | bit) << 1;
          int ndiagr = (diagr[d] | bit) >> 1;
          int nposib = ~(ncols | ndiagl | ndiagr);
          posib^=bit; // Eliminate the tried possibility.

          // The following is the main additional trick here, as recognizing solution can not be done using stack level (d),
          // since we save the depth+backtrack time at the end of the enumeration loop. However by noticing all coloumns are
          // filled (comparison to -1) we know a solution was reached ...
          // Notice also that avoiding an if on the ncols==-1 comparison is more efficient!
          num += ncols==-1;

          if (nposib) {
            if (posib) { // This if saves stack depth + backtrack operations when we passed the last possibility in a row.
              posibs[d++] = posib; // Go lower in stack ..
            }
            cols[d] = ncols;
            diagl[d] = ndiagl;
            diagr[d] = ndiagr;
            posib = nposib;
          }
        }
        posib = posibs[--d]; // backtrack ...
      }
    }
  }
  return num*2;
}

main(int ac , char **av)
{
  if(ac != 2) {
    printf("usage: nq n\n");
    return 1;
  }
  int n = atoi(av[1]);
  if(n<1 || n > MAXN) {
    printf("n must be between 2 and 31!\n");
  }
  printf("Number of solution for %d is %d\n",n,nqueens(n));
}

"Implement a highly optimized solution to solve the N-queens problem, with a focus on speed and efficiency. The code also includes a version with redundant optimizations removed, resulting in a 15% performance improvement on modern compilers."


#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define ARRAY_CONCAT(TYPE, A, An, B, Bn) \
  (TYPE *)array_concat((const void *)(A), (An), (const void *)(B), (Bn), sizeof(TYPE));

void *array_concat(const void *a, size_t an,
                   const void *b, size_t bn, size_t s)
{
  char *p = malloc(s * (an + bn));
  memcpy(p, a, an*s);
  memcpy(p + an*s, b, bn*s);
  return p;
}

// testing
const int a[] = { 1, 2, 3, 4, 5 };
const int b[] = { 6, 7, 8, 9, 0 };

int main(void)
{
  unsigned int i;

  int *c = ARRAY_CONCAT(int, a, 5, b, 5);

  for(i = 0; i < 10; i++)
    printf("%d\n", c[i]);

  free(c);
  return EXIT_SUCCCESS;
}

demonstrate how to concatenate two arrays in C language when their size is known.


#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char *name;
    int weight;
    int value;
} item_t;

item_t items[] = {
    {"map",                      9,   150},
    {"compass",                 13,    35},
    {"water",                  153,   200},
    {"sandwich",                50,   160},
    {"glucose",                 15,    60},
    {"tin",                     68,    45},
    {"banana",                  27,    60},
    {"apple",                   39,    40},
    {"cheese",                  23,    30},
    {"beer",                    52,    10},
    {"suntan cream",            11,    70},
    {"camera",                  32,    30},
    {"T-shirt",                 24,    15},
    {"trousers",                48,    10},
    {"umbrella",                73,    40},
    {"waterproof trousers",     42,    70},
    {"waterproof overclothes",  43,    75},
    {"note-case",               22,    80},
    {"sunglasses",               7,    20},
    {"towel",                   18,    12},
    {"socks",                    4,    50},
    {"book",                    30,    10},
};

int *knapsack (item_t *items, int n, int w) {
    int i, j, a, b, *mm, **m, *s;
    mm = calloc((n + 1) * (w + 1), sizeof (int));
    m = malloc((n + 1) * sizeof (int *));
    m[0] = mm;
    for (i = 1; i <= n; i++) {
        m[i] = &mm[i * (w + 1)];
        for (j = 0; j <= w; j++) {
            if (items[i - 1].weight > j) {
                m[i][j] = m[i - 1][j];
            }
            else {
                a = m[i - 1][j];
                b = m[i - 1][j - items[i - 1].weight] + items[i - 1].value;
                m[i][j] = a > b ? a : b;
            }
        }
    }
    s = calloc(n, sizeof (int));
    for (i = n, j = w; i > 0; i--) {
        if (m[i][j] > m[i - 1][j]) {
            s[i - 1] = 1;
            j -= items[i - 1].weight;
        }
    }
    free(mm);
    free(m);
    return s;
}

int main () {
    int i, n, tw = 0, tv = 0, *s;
    n = sizeof (items) / sizeof (item_t);
    s = knapsack(items, n, 400);
    for (i = 0; i < n; i++) {
        if (s[i]) {
            printf("%-22s %5d %5d\n", items[i].name, items[i].weight, items[i].value);
            tw += items[i].weight;
            tv += items[i].value;
        }
    }
    printf("%-22s %5d %5d\n", "totals:", tw, tv);
    return 0;
}

The code determines the optimal combination of items a tourist can carry in his knapsack, given a maximum weight limit of 4kg (400 dag), such that the total value of the items is maximized. The items cannot be divided or diminished.


#include <stdio.h>

int verbose = 0;
enum {
	clown = -1,
	abe, bob, col, dan, ed, fred, gav, hal, ian, jon,
	abi, bea, cath, dee, eve, fay, gay, hope, ivy, jan,
};
const char *name[] = {
	"Abe", "Bob", "Col",  "Dan", "Ed",  "Fred", "Gav", "Hal",  "Ian", "Jon",
	"Abi", "Bea", "Cath", "Dee", "Eve", "Fay",  "Gay", "Hope", "Ivy", "Jan"
};
int pref[jan + 1][jon + 1] = {
	{ abi, eve, cath, ivy, jan, dee, fay, bea, hope, gay },
	{ cath, hope, abi, dee, eve, fay, bea, jan, ivy, gay },
	{ hope, eve, abi, dee, bea, fay, ivy, gay, cath, jan },
	{ ivy, fay, dee, gay, hope, eve, jan, bea, cath, abi },
	{ jan, dee, bea, cath, fay, eve, abi, ivy, hope, gay },
	{ bea, abi, dee, gay, eve, ivy, cath, jan, hope, fay },
	{ gay, eve, ivy, bea, cath, abi, dee, hope, jan, fay },
	{ abi, eve, hope, fay, ivy, cath, jan, bea, gay, dee },
	{ hope, cath, dee, gay, bea, abi, fay, ivy, jan, eve },
	{ abi, fay, jan, gay, eve, bea, dee, cath, ivy, hope },

	{ bob, fred, jon, gav, ian, abe, dan, ed, col, hal   },
	{ bob, abe, col, fred, gav, dan, ian, ed, jon, hal   },
	{ fred, bob, ed, gav, hal, col, ian, abe, dan, jon   },
	{ fred, jon, col, abe, ian, hal, gav, dan, bob, ed   },
	{ jon, hal, fred, dan, abe, gav, col, ed, ian, bob   },
	{ bob, abe, ed, ian, jon, dan, fred, gav, col, hal   },
	{ jon, gav, hal, fred, bob, abe, col, ed, dan, ian   },
	{ gav, jon, bob, abe, ian, dan, hal, ed, col, fred   },
	{ ian, col, hal, gav, fred, bob, abe, ed, jon, dan   },
	{ ed, hal, gav, abe, bob, jon, col, ian, fred, dan   },
};
int pairs[jan + 1], proposed[jan + 1];

void engage(int man, int woman)
{
	pairs[man] = woman;
	pairs[woman] = man;
	if (verbose) printf("%4s is engaged to %4s\n", name[man], name[woman]);
}

void dump(int woman, int man)
{
	pairs[man] = pairs[woman] = clown;
	if (verbose) printf("%4s dumps %4s\n", name[woman], name[man]);
}

/* how high this person ranks that: lower is more preferred */
int rank(int this, int that)
{
	int i;
	for (i = abe; i <= jon && pref[this][i] != that; i++);
	return i;
}

void propose(int man, int woman)
{
	int fiance = pairs[woman];
	if (verbose) printf("%4s proposes to %4s\n", name[man], name[woman]);

	if (fiance == clown) {
		engage(man, woman);
	} else if (rank(woman, man) < rank(woman, fiance)) {
		dump(woman, fiance);
		engage(man, woman);
	}
}

int covet(int man1, int wife2)
{
	if (rank(man1, wife2) < rank(man1, pairs[man1]) &&
			rank(wife2, man1) < rank(wife2, pairs[wife2])) {
		printf( "    %4s (w/ %4s) and %4s (w/ %4s) prefer each other"
			" over current pairing.\n",
			name[man1], name[pairs[man1]], name[wife2], name[pairs[wife2]]
		);
		return 1;
	}
	return 0;
}

int thy_neighbors_wife(int man1, int man2)
{	/* +: force checking all pairs; "||" would shortcircuit */
	return covet(man1, pairs[man2]) + covet(man2, pairs[man1]);
}

int unstable()
{
	int i, j, bad = 0;
	for (i = abe; i < jon; i++) {
		for (j = i + 1; j <= jon; j++)
			if (thy_neighbors_wife(i, j)) bad = 1;
	}
	return bad;
}

int main()
{
	int i, unengaged;
	/* init: everyone marries the clown */
	for (i = abe; i <= jan; i++)
		pairs[i] = proposed[i] = clown;

	/* rounds */
	do {
		unengaged = 0;
		for (i = abe; i <= jon; i++) {
		//for (i = abi; i <= jan; i++) { /* could let women propose */
			if (pairs[i] != clown) continue;
			unengaged = 1;
			propose(i, pref[i][++proposed[i]]);
		}
	} while (unengaged);

	printf("Pairing:\n");
	for (i = abe; i <= jon; i++)
		printf("  %4s - %s\n", name[i],
			pairs[i] == clown ? "clown" : name[pairs[i]]);

	printf(unstable()
		? "Marriages not stable\n" /* draw sad face here */
		: "Stable matchup\n");

	printf("\nBut if Bob and Fred were to swap:\n");
	i = pairs[bob];
	engage(bob, pairs[fred]);
	engage(fred, i);
	printf(unstable() ? "Marriages not stable\n" : "Stable matchup\n");

	return 0;
}

The code implements the Gale/Shapley algorithm to solve the Stable Marriage Problem. It takes as input the preferences of ten men and ten women for potential partners. The algorithm finds a stable set of engagements where no man prefers a woman over his current partner and vice versa. The code then perturbs this stable set to create an unstable set of engagements and checks the stability of this new set.


#include <stdio.h>
#include <stdbool.h>

bool a(bool in)
{
  printf("I am a\n");
  return in;
}

bool b(bool in)
{
  printf("I am b\n");
  return in;
}

#define TEST(X,Y,O)						\
  do {								\
    x = a(X) O b(Y);						\
    printf(#X " " #O " " #Y " = %s\n\n", x ? "true" : "false");	\
  } while(false);

int main()
{
  bool x;

  TEST(false, true, &&); // b is not evaluated
  TEST(true, false, ||); // b is not evaluated
  TEST(true, false, &&); // b is evaluated
  TEST(false, false, ||); // b is evaluated

  return 0;
}

The code defines two functions, 'a' and 'b', which accept and return the same boolean value and print their names when called. It then calculates and assigns the values of two equations, 'x' and 'y', using short-circuit evaluation to ensure function 'b' is only called when necessary. If the programming language doesn't support short-circuit evaluation, nested 'if' statements are used instead. The boolean operators used are && and ||.


The code converts a given string into audible Morse code and sends it to an audio device, such as the PC speaker. It handles unknown characters by either ignoring them or indicating them with a different pitch. The program can be substituted with the Ubuntu beep command.


#include <stdio.h>
#include <ctype.h>

int can_make_words(char **b, char *word)
{
	int i, ret = 0, c = toupper(*word);

#define SWAP(a, b) if (a != b) { char * tmp = a; a = b; b = tmp; }

	if (!c) return 1;
	if (!b[0]) return 0;

	for (i = 0; b[i] && !ret; i++) {
		if (b[i][0] != c && b[i][1] != c) continue;
		SWAP(b[i], b[0]);
		ret = can_make_words(b + 1, word + 1);
		SWAP(b[i], b[0]);
	}

	return ret;
}

int main(void)
{
	char* blocks[] = {
		"BO", "XK", "DQ", "CP", "NA",
		"GT", "RE", "TG", "QD", "FS",
		"JW", "HU", "VI", "AN", "OB",
		"ER", "FS", "LY", "PC", "ZM",
		0 };

	char *words[] = {
		"", "A", "BARK", "BOOK", "TREAT", "COMMON", "SQUAD", "Confuse", 0
	};

	char **w;
	for (w = words; *w; w++)
		printf("%s\t%d\n", *w, can_make_words(blocks, *w));

	return 0;
}

The code defines a function that checks if a given word can be spelled using a specific collection of ABC blocks. Each block contains two letters and can only be used once. The function is case-insensitive. It tests the function with 7 example words and returns the results. An empty string input returns true.


Library: OpenSSL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/md5.h>

const char *string = "The quick brown fox jumped over the lazy dog's back";

int main()
{
  int i;
  unsigned char result[MD5_DIGEST_LENGTH];

  MD5(string, strlen(string), result);

  // output
  for(i = 0; i < MD5_DIGEST_LENGTH; i++)
    printf("%02x", result[i]);
  printf("\n");

  return EXIT_SUCCESS;
}

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

typedef union uwb {
    unsigned w;
    unsigned char b[4];
} WBunion;

typedef unsigned Digest[4];

unsigned f0( unsigned abcd[] ){
    return ( abcd[1] & abcd[2]) | (~abcd[1] & abcd[3]);}

unsigned f1( unsigned abcd[] ){
    return ( abcd[3] & abcd[1]) | (~abcd[3] & abcd[2]);}

unsigned f2( unsigned abcd[] ){
    return  abcd[1] ^ abcd[2] ^ abcd[3];}

unsigned f3( unsigned abcd[] ){
    return abcd[2] ^ (abcd[1] |~ abcd[3]);}

typedef unsigned (*DgstFctn)(unsigned a[]);

unsigned *calcKs( unsigned *k)
{
    double s, pwr;
    int i;

    pwr = pow( 2, 32);
    for (i=0; i<64; i++) {
        s = fabs(sin(1+i));
        k[i] = (unsigned)( s * pwr );
    }
    return k;
}

// ROtate v Left by amt bits
unsigned rol( unsigned v, short amt )
{
    unsigned  msk1 = (1<<amt) -1;
    return ((v>>(32-amt)) & msk1) | ((v<<amt) & ~msk1);
}

unsigned *md5( const char *msg, int mlen)
{
    static Digest h0 = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 };
//    static Digest h0 = { 0x01234567, 0x89ABCDEF, 0xFEDCBA98, 0x76543210 };
    static DgstFctn ff[] = { &f0, &f1, &f2, &f3 };
    static short M[] = { 1, 5, 3, 7 };
    static short O[] = { 0, 1, 5, 0 };
    static short rot0[] = { 7,12,17,22};
    static short rot1[] = { 5, 9,14,20};
    static short rot2[] = { 4,11,16,23};
    static short rot3[] = { 6,10,15,21};
    static short *rots[] = {rot0, rot1, rot2, rot3 };
    static unsigned kspace[64];
    static unsigned *k;

    static Digest h;
    Digest abcd;
    DgstFctn fctn;
    short m, o, g;
    unsigned f;
    short *rotn;
    union {
        unsigned w[16];
        char     b[64];
    }mm;
    int os = 0;
    int grp, grps, q, p;
    unsigned char *msg2;

    if (k==NULL) k= calcKs(kspace);

    for (q=0; q<4; q++) h[q] = h0[q];   // initialize

    {
        grps  = 1 + (mlen+8)/64;
        msg2 = malloc( 64*grps);
        memcpy( msg2, msg, mlen);
        msg2[mlen] = (unsigned char)0x80;
        q = mlen + 1;
        while (q < 64*grps){ msg2[q] = 0; q++ ; }
        {
//            unsigned char t;
            WBunion u;
            u.w = 8*mlen;
//            t = u.b[0]; u.b[0] = u.b[3]; u.b[3] = t;
//            t = u.b[1]; u.b[1] = u.b[2]; u.b[2] = t;
            q -= 8;
            memcpy(msg2+q, &u.w, 4 );
        }
    }

    for (grp=0; grp<grps; grp++)
    {
        memcpy( mm.b, msg2+os, 64);
        for(q=0;q<4;q++) abcd[q] = h[q];
        for (p = 0; p<4; p++) {
            fctn = ff[p];
            rotn = rots[p];
            m = M[p]; o= O[p];
            for (q=0; q<16; q++) {
                g = (m*q + o) % 16;
                f = abcd[1] + rol( abcd[0]+ fctn(abcd) + k[q+16*p] + mm.w[g], rotn[q%4]);

                abcd[0] = abcd[3];
                abcd[3] = abcd[2];
                abcd[2] = abcd[1];
                abcd[1] = f;
            }
        }
        for (p=0; p<4; p++)
            h[p] += abcd[p];
        os += 64;
    }

    if( msg2 )
        free( msg2 );

    return h;
}

int main( int argc, char *argv[] )
{
    int j,k;
    const char *msg = "The quick brown fox jumps over the lazy dog.";
    unsigned *d = md5(msg, strlen(msg));
    WBunion u;

    printf("= 0x");
    for (j=0;j<4; j++){
        u.w = d[j];
        for (k=0;k<4;k++) printf("%02x",u.b[k]);
    }
    printf("\n");

    return 0;
}

implement the MD5 algorithm to encode a string. They also optionally validate the implementation using test values from IETF RFC 1321. The codes also consider the known weaknesses of MD5 and suggest using stronger alternatives for production-grade cryptography. The solution might be a library solution, and differences may be observed for the last 8 characters when compared with the openssl implementation.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct oid_tag {
    char* str_;
    int* numbers_;
    int length_;
} oid;

// free memory, no-op if p is null
void oid_destroy(oid* p) {
    if (p != 0) {
        free(p->str_);
        free(p->numbers_);
        free(p);
    }
}

int char_count(const char* str, char ch) {
    int count = 0;
    for (const char* p = str; *p; ++p) {
        if (*p == ch)
            ++count;
    }
    return count;
}

// construct an OID from a string
// returns 0 on memory allocation failure or parse error
oid* oid_create(const char* str) {
    oid* ptr = calloc(1, sizeof(oid));
    if (ptr == 0)
        return 0;
    ptr->str_ = strdup(str);
    if (ptr->str_ == 0) {
        oid_destroy(ptr);
        return 0;
    }
    int dots = char_count(str, '.');
    ptr->numbers_ = malloc(sizeof(int) * (dots + 1));
    if (ptr->numbers_ == 0) {
        oid_destroy(ptr);
        return 0;
    }
    ptr->length_ = dots + 1;
    const char* p = str;
    for (int i = 0; i <= dots && *p;) {
        char* eptr = 0;
        int num = strtol(p, &eptr, 10);
        if (*eptr != 0 && *eptr != '.') {
            // TODO: check for overflow/underflow
            oid_destroy(ptr);
            return 0;
        }
        ptr->numbers_[i++] = num;
        p = eptr;
        if (*p)
            ++p;
    }
    return ptr;
}

// compare two OIDs
int oid_compare(const void* p1, const void* p2) {
    const oid* o1 = *(oid* const*)p1;
    const oid* o2 = *(oid* const*)p2;
    int i1 = 0, i2 = 0;
    for (; i1 < o1->length_ && i2 < o2->length_; ++i1, ++i2) {
        if (o1->numbers_[i1] < o2->numbers_[i2])
            return -1;
        if (o1->numbers_[i1] > o2->numbers_[i2])
            return 1;
    }
    if (o1->length_ < o2->length_)
        return -1;
    if (o1->length_ > o2->length_)
        return 1;
    return 0;
}

int main() {
    const char* input[] = {
        "1.3.6.1.4.1.11.2.17.19.3.4.0.10",
        "1.3.6.1.4.1.11.2.17.5.2.0.79",
        "1.3.6.1.4.1.11.2.17.19.3.4.0.4",
        "1.3.6.1.4.1.11150.3.4.0.1",
        "1.3.6.1.4.1.11.2.17.19.3.4.0.1",
        "1.3.6.1.4.1.11150.3.4.0"
    };
    const int len = sizeof(input)/sizeof(input[0]);
    oid* oids[len];
    memset(oids, 0, sizeof(oids));
    int i;
    for (i = 0; i < len; ++i) {
        oids[i] = oid_create(input[i]);
        if (oids[i] == 0)
        {
            fprintf(stderr, "Out of memory\n");
            goto cleanup;
        }
    }
    qsort(oids, len, sizeof(oid*), oid_compare);
    for (i = 0; i < len; ++i)
        puts(oids[i]->str_);
cleanup:
    for (i = 0; i < len; ++i)
        oid_destroy(oids[i]);
    return 0;
}

sort a list of Object Identifiers (OIDs). OIDs are strings consisting of one or more non-negative integers separated by dots. The sorting is done lexicographically based on the dot-separated fields using numeric comparison. A C99 or later compiler is required for this task.


Works with: POSIX version .1-2001
Works with: gcc version 4.2.2

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

const char *msg = "hello socket world";

int main()
{
   int i, sock, len, slen;

   struct addrinfo hints, *addrs;
   memset(&hints, 0, sizeof(struct addrinfo));
   hints.ai_family = AF_UNSPEC;
   hints.ai_socktype = SOCK_STREAM;

   if (0 == getaddrinfo("localhost", "256", &hints, &addrs))
   {
       sock = socket(addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
       if ( sock >= 0 )
       {
           if ( connect(sock, addrs->ai_addr, addrs->ai_addrlen) >= 0 )
           {
               const char *pm = msg;
               do
               {
                  len = strlen(pm);
                  slen = send(sock, pm, len, 0);
                  pm += slen;
               } while ((0 <= slen) && (slen < len));
           }
           close(sock);
       }
       freeaddrinfo(addrs);
   }
}

Open a socket to localhost on port 256, send the message "hello socket world", and then close the socket. The code may also be adaptable for MS Windows.


Library: libcurl
#include <curl/curl.h>
#include <string.h>
#include <stdio.h>

#define from    "<sender@duniya.com>"
#define to      "<addressee@gmail.com>"
#define cc      "<info@example.org>"

static const char *payload_text[] = {
  "Date: Mon, 13 Jun 2018 11:30:00 +0100\r\n",
  "To: " to "\r\n",
  "From: " from " (Example User)\r\n",
  "Cc: " cc " (Another example User)\r\n",
  "Message-ID: <ecd7db36-10ab-437a-9g3a-e652b9458efd@"
  "rfcpedant.example.org>\r\n",
  "Subject: Sanding mail via C\r\n",
  "\r\n",
  "This mail is being sent by a C program.\r\n",
  "\r\n",
  "It connects to the GMail SMTP server, by far, the most popular mail program of all.\r\n",
  "Which is also probably written in C.\r\n",
  "To C or not to C..............\r\n",
  "That is the question.\r\n",
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }

  data = payload_text[upload_ctx->lines_read];

  if(data) {
    size_t len = strlen(data);
    memcpy(ptr, data, len);
    upload_ctx->lines_read++;

    return len;
  }

  return 0;
}

int main(void)
{
  CURL *curl;
  CURLcode res = CURLE_OK;
  struct curl_slist *recipients = NULL;
  struct upload_status upload_ctx;

  upload_ctx.lines_read = 0;

  curl = curl_easy_init();
  if(curl) {

    curl_easy_setopt(curl, CURLOPT_USERNAME, "user");
    curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret");

    curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:465");

    curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);

    curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/certificate.pem");

    curl_easy_setopt(curl, CURLOPT_MAIL_FROM, from);

    recipients = curl_slist_append(recipients, to);
    recipients = curl_slist_append(recipients, cc);
    curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);

    curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
    curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    res = curl_easy_perform(curl);

    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res));

    curl_slist_free_all(recipients);

    curl_easy_cleanup(curl);
  }

  return (int)res;
}

The code sends an email using a function that takes parameters for From, To, Cc addresses, Subject, message text, and optionally server name and login details. It uses the GMail SMTP server and requires libcurl library. The code also handles notifications for problems/success and is portable across different operating systems. Sensitive data used in examples is obfuscated.


#include <stdio.h>

int main()
{
        unsigned int i = 0;
        do { printf("%o\n", i++); } while(i);
        return 0;
}

generate a sequential count in octal, starting from zero and incrementing by one on each line until the program is terminated or the maximum numeric type value is reached.


void swap(void *va, void *vb, size_t s)
{
  char t, *a = (char*)va, *b = (char*)vb;
  while(s--)
    t = a[s], a[s] = b[s], b[s] = t;
}

Works with: gcc

Caution: __typeof__ is a gcc extension, not part of standard C. __typeof__ does not conflict with C89 because the standard allows compilers to add keywords with underscores like __typeof__.
#define Swap(X,Y)  do{ __typeof__ (X) _T = X; X = Y; Y = _T; }while(0)

#include <stdio.h>

#define Swap(X,Y)  do{ __typeof__ (X) _T = X; X = Y; Y = _T; }while(0)

struct test
{
  int a, b, c;
};

int main()
{
  struct test t = { 1, 2, 3 };
  struct test h = { 4, 5, 6 };
  double alfa = 0.45, omega = 9.98;

  struct test *pt = &t;
  struct test *th = &h;

  printf("%d %d %d\n", t.a, t.b, t.c );
  Swap(t, h);
  printf("%d %d %d\n", t.a, t.b, t.c );
  printf("%d %d %d\n", h.a, h.b, h.c );

  printf("%lf\n", alfa);
  Swap(alfa, omega);
  printf("%lf\n", alfa);

  printf("%d\n", pt->a);
  Swap(pt, th);
  printf("%d\n", pt->a);
}

implement a generic swap function that exchanges the values of two variables of any type. The function ensures type compatibility between variables to prevent type violation. It handles issues related to programming language semantics, including challenges in dynamically typed languages and static languages with limited support for parametric polymorphism. The function also includes a restriction for variables to be of the same size and demonstrates usage with GCC using the -std=c89 option.


#include <string.h>

int palindrome(const char *s)
{
   int i,l;
   l = strlen(s);
   for(i=0; i<l/2; i++)
   {
     if ( s[i] != s[l-i-1] ) return 0;
   }
   return 1;
}

int palindrome(const char *s)
{
   const char *t; /* t is a pointer that traverses backwards from the end */
   for (t = s; *t != '\0'; t++) ; t--; /* set t to point to last character */
   while (s < t)
   {
     if ( *s++ != *t-- ) return 0;
   }
   return 1;
}

int palindrome_r(const char *s, int b, int e)
{
   if ( (e - 1) <= b ) return 1;
   if ( s[b] != s[e-1] ) return 0;
   return palindrome_r(s, b+1, e-1);
}

#include <stdio.h>
#include <string.h>
/* testing */
int main()
{
   const char *t = "ingirumimusnocteetconsumimurigni";
   const char *template = "sequence \"%s\" is%s palindrome\n";
   int l = strlen(t);

   printf(template,
          t, palindrome(t) ? "" : "n't");
   printf(template,
          t, palindrome_r(t, 0, l) ? "" : "n't");
   return 0;
}

The code includes a function that checks if a given sequence of characters is a palindrome. It supports Unicode characters and can detect inexact palindromes by ignoring white-space, punctuation, and case. The function compares each character from the start and end of the sequence until the middle. If all pairs are equal, it returns true; otherwise, it returns false. The code also includes a recursive version of the function that checks if the first and last characters are the same and if the remaining string is a palindrome.


#include <stdlib.h>
#include <stdio.h>

int main() {
  puts(getenv("HOME"));
  puts(getenv("PATH"));
  puts(getenv("USER"));
  return 0;
}

"Demonstrates how to retrieve a process's environment variables such as PATH, HOME, or USER in a Unix system."


//Aamrun, 11th July 2022

#include <stdio.h>

int F(int n,int x,int y) {
  if (n == 0) {
    return x + y;
  }

  else if (y == 0) {
    return x;
  }

  return F(n - 1, F(n, x, y - 1), F(n, x, y - 1) + y);
}

int main() {
  printf("F1(3,3) = %d",F(1,3,3));
  return 0;
}

F1(3,3) = 35

implement the Sudan function, a non-primitive recursive function. The function takes two parameters, x and y, and returns their sum if the recursion depth is zero. If the recursion depth is greater than zero and y is zero, it returns x. Otherwise, it recursively calls itself with updated parameters.


; x86_64 linux nasm

struc Stack
  maxSize: resb 8
  currentSize: resb 8
  contents:
endStruc

section .data

soError: db "Stack Overflow Exception", 10
seError: db "Stack Empty Error", 10

section .text

createStack:
; IN: max number of elements (rdi)
; OUT: pointer to new stack (rax)
  push rdi
  xor rdx, rdx
  mov rbx, 8
  mul rbx
  mov rcx, rax
  mov rax, 12
  mov rdi, 0
  syscall
  push rax
  mov rdi, rax
  add rdi, rcx
  mov rax, 12
  syscall
  pop rax
  pop rbx
  mov qword [rax + maxSize], rbx
  mov qword [rax + currentSize], 0
  ret

push:
; IN: stack to operate on (stack argument), element to push (rdi)
; OUT: void
  mov rax, qword [rsp + 8]
  mov rbx, qword [rax + currentSize]
  cmp rbx, qword [rax + maxSize]
  je stackOverflow
  lea rsi, [rax + contents + 8*rbx]
  mov qword [rsi], rdi
  add qword [rax + currentSize], 1
  ret

pop:
; pop
; IN: stack to operate on (stack argument)
; OUT: element from stack top
  mov rax, qword [rsp + 8]
  mov rbx, qword [rax + currentSize]
  cmp rbx, 0
  je stackEmpty
  sub rbx, 1
  lea rsi, [rax + contents + 8*rbx]
  mov qword [rax + currentSize], rbx
  mov rax, qword [rsi]
  ret

; stack operation exceptions
stackOverflow:
  mov rsi, soError
  mov rdx, 25
  jmp errExit
stackEmpty:
  mov rsi, seError
  mov rdx, 18
errExit:
  mov rax, 1
  mov rdi, 1
  syscall
  mov rax, 60
  mov rdi, 1
  syscall

implement a stack data structure with basic operations such as push (to add elements), pop (to remove and return the last added element), and empty (to check if the stack is empty). This stack follows a Last-In-First-Out (LIFO) access policy.


EAX - the youngest part of the transformed block (N1);
EDX - leading part transformed block (N2);
ESI - address of the first element of the key;
EBX - table address changes;
ECX - the number of major steps.

EDX = N1, EAX = N2 for cycles 32-З, 32-Р;
EAX = N1, EDX = N2 for cycle 16-З.

At the end of the run the registers as follows:
EBX (pointer to table of changes) - the same as that in the early
ESI (pointer to key) - points to the first byte of the key - it's N * 4 larger than the initial values for the SI cycle reps N (for encryption cycles N = 32 => 4 * N = 128, for authentication code generation cycle N = 16 => 4 * N = 64), larger than the initial values for the authentication code generation cycle.
ECX = 0
The contents of the segment registers unchanged.
        .386
        .model  flat
        .code
_gost32 proc    near32
        public  _gost32
; The inner loop of a subroutine
; 1. Beginning of the cycle, and preservation of the old N1
iloop:  mov     EBP,EAX
; 2. Adding to the S key modulo 2^32
        add     EAX,[ESI] ; add the key
        add     ESI,4   ; the next element of the key.
; 3. Block-replace in the rotation of S by 8 bits to the left
REPT    3
        xlat            ; recoding byte
        ror     EAX,8   ; AL <- next byte
        add     EBX,100h; next node changes
ENDM
        xlat            ; recoding byte
        sub     EBX,300h; BX -> 1st node changes
; 4. Complete rotation of the S at 3 bits to the left
        rol     EAX,3
; 5. The calculation of the new values of N1,N2
        xor     EAX,EDX
        mov     EDX,EBP
; The completion of the inner loop
        loop    iloop
        ret
_gost32 endp
        end

implement the main step of the GOST 28147-89 encryption algorithm. This involves taking a 64-bit block of text and one of the eight 32-bit encryption key elements, using a replacement table (8x16 matrix of 4-bit values), and returning an encrypted block. The code does not use the EDI register.


section .text
	global _start

	_print:
		mov ebx, 1
		mov eax, 4
		int 0x80
		ret

	_start:
		;print out our byte array. ergo, String.
		mov edx, sLen
		mov ecx, sArray
		call _print
		mov edx, f_len
		mov ecx, f_msg
		call _print
		mov edx, 6			;our array members length.
		xor ecx, ecx
		mov ecx, 4
		;turnicate through the array and print all it's members.
		;At an offset of *4, each array member is referenced
		;at 1,2,3 and so on.
		_out_loops:
			push ecx
			mov ecx, [fArray+esi*4]
			call _print
			inc esi
			pop ecx
		loop _out_loops
		mov edx, u_len
		mov ecx, u_msg
		call _print
		;Let's populate 'uArray' with something from sArray.
		;mov edi, uArray
		mov ecx, 4
		xor esi, esi
		_read_loops:
			push dword [fArray+esi*4]
			pop dword [uArray+esi*4]
			inc esi
		loop _read_loops
		mov ecx, 4
		xor esi, esi
		_out_loops2:
			push ecx
			mov ecx, [uArray+esi*4]
			call _print
			inc esi
			pop ecx
		loop _out_loops2
		push 0x1
		mov eax, 1
		push eax
		int 0x80

section .data
sArray	db 'a','r','r','a','y','s',' ','a','r','e',' ','f','u','n',0xa
sLen		equ $-sArray

crap1		db "crap1",0xa
crap2		db "crap2",0xa
crap3		db "crap3",0xa
crap4		db "crap4",0xa

fArray	dd crap1,crap2
	dd crap3,crap4

f_msg		db "fArray contents",0xa,"----------------------",0xa
f_len		equ $-f_msg
u_msg		db "uArray now holds fArray contents.. dumping..",0xa,"----------------------",0xa
u_len		equ $-u_msg

section .bss
uArray	resd 1
        resd 1
	resd 1
	resd 1

demonstrate the basic syntax of arrays in a specific programming language. They include the creation of an array, assigning a value to it, and retrieving an element from it. The codes also showcase the use of both fixed-length and dynamic arrays, and the process of pushing a value into the array. The codes do not support multidimensional arrays in assembly, instead, they use a specific format to reference one. The functionality of the codes is discussed in the Village Pump: Arrays. The codes also integrate elements from obsolete tasks such as creating an array, assigning values to an array, and retrieving an element of an array.


%define TRUE 1
%define FALSE 0

global main,foursquares,acd,ge,bf,print_output
extern printf

segment .data

a dq 0
b dq 0
c dq 0
d dq 0
e dq 0
f dq 0
g dq 0

lo dq 0
hi dq 0
unique dq 0
show dq 0
solutions dq 0

output_fmt db `%ld %ld %ld %ld %ld %ld %ld
`,0

segment .text

main:
    push rbp
    mov rbp,rsp

    mov rdi,1
    mov rsi,7
    mov rdx,TRUE
    mov rcx,TRUE
    call foursquares

    mov rdi,3
    mov rsi,9
    mov rdx,TRUE
    mov rcx,TRUE
    call foursquares

    mov rdi,0
    mov rsi,9
    mov rdx,FALSE
    mov rcx,FALSE
    call foursquares

    xor rax,rax
    leave
    ret

segment .data

newlinefmt db `
`,0
uniquefmt db `
%ld unique solutions in %ld to %ld
`,0
nonuniquefmt db `
%ld non-unique solutions in %ld to %ld
`,0

segment .text

foursquares:
    push rbp
    mov rbp,rsp

    mov qword [lo],rdi
    mov qword [hi],rsi
    mov qword [unique],rdx
    mov qword [show],rcx
    mov qword [solutions],0

    lea rdi,[newlinefmt]
    xor rax,rax
    call printf

    call acd

    mov rax,qword [unique]
    mov rbx,TRUE
    cmp rax,rbx
    je .isunique

    lea rdi,[nonuniquefmt]
    mov rsi,qword [solutions]
    mov rdx,qword [lo]
    mov rcx,qword [hi]
    xor rax,rax
    call printf
    jmp .done

.isunique:
    lea rdi,[uniquefmt]
    mov rsi,qword [solutions]
    mov rdx,qword [lo]
    mov rcx,qword [hi]
    xor rax,rax
    call printf

.done:
    xor rax,rax
    leave
    ret

segment .text

acd:
    push rbp
    mov rbp,rsp

    mov rax,qword [lo] ; c = lo
    mov qword [c],rax

.nextouterfor:
    mov rax,qword [c]  ; c <= hi
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .doneouterfor

    mov rax,qword [lo] ; d = lo
    mov qword [d],rax

.nextinnerfor:
    mov rax,qword [d]  ; d <= hi
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .doneinnerfor

    mov rax,qword [unique]
    mov rcx,FALSE
    cmp rax,rcx
    je .inif

    mov rax,qword [c]
    mov rcx,qword [d]
    cmp rax,rcx
    jne .inif
    jmp .iffails

.inif:
    mov rax,qword [c]
    mov rcx,qword [d]
    add rax,rcx
    mov qword [a],rax

; ((a >= lo) &&
;  (a <= hi) &&
;  ((!unique) ||
;   ((c != 0) &&
;    (d != 0)
;   )
;  )
; )
    mov rax,qword [a]  ;(a >= lo)
    mov rcx,qword [lo]
    cmp rax,rcx
    jl .iffails

    mov rax,qword [a]  ;(a <= hi)
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .iffails

    mov rax,qword [unique] ;(!unique)
    mov rcx,FALSE
    cmp rax,rcx
    je .ifsucceeds

    mov rax,qword [c]  ;(c != 0)
    mov rcx,0
    cmp rax,rcx
    je .iffails

    mov rax,qword [d]  ;(d != 0)
    mov rcx,0
    cmp rax,rcx
    je .iffails

.ifsucceeds:

    call ge

.iffails:
    mov rax,qword [d] ; d++
    inc rax
    mov qword [d],rax
    jmp .nextinnerfor

.doneinnerfor:
    mov rax,qword [c] ; c++
    inc rax
    mov qword [c],rax
    jmp .nextouterfor

.doneouterfor:
    xor rax,rax
    leave
    ret

ge:
    push rbp
    mov rbp,rsp

    mov rax,qword [lo] ; e = lo
    mov qword [e],rax

.nextfor:
    mov rax,qword [e]  ; e <= hi
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .donefor

    mov rax,qword [unique]
    mov rcx,FALSE
    cmp rax,rcx
    je .inif

; ((e != a) && (e != c) && (e != d))

    mov rax,qword [e]

    mov rcx,qword [a] ; (e != a)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [c] ; (e != c)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [d] ; (e != d)
    cmp rax,rcx
    je .skipif

.inif:
    mov rax,qword [d] ; g = d + e
    mov rcx,qword [e]
    add rax,rcx
    mov qword [g],rax

; ((g >= lo) &&
;  (g <= hi) &&
;  ((!unique) ||
;   ((g != a) &&
;    (g != c) &&
;    (g != d) &&
;    (g != e)
;   )
;  )
; )

    mov rax,qword [g]  ;(g >= lo)
    mov rcx,qword [lo]
    cmp rax,rcx
    jl .skipif

    mov rax,qword [g]  ;(g <= hi)
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .skipif

    mov rax,qword [unique] ;(!unique)
    mov rcx,FALSE
    cmp rax,rcx
    je .innerifsucceeds

    mov rax,qword [g]  ;(g != a)
    mov rcx,qword [a]
    cmp rax,rcx
    je .skipif

    mov rcx,qword [c]  ;(g != c)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [d]  ;(g != d)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [e]  ;(g != e)
    cmp rax,rcx
    je .skipif

.innerifsucceeds:
    call bf

.skipif:
    mov rax,qword [e] ; e++
    inc rax
    mov qword [e],rax
    jmp .nextfor

.donefor:
    xor rax,rax
    leave
    ret

segment .text

bf:
    push rbp
    mov rbp,rsp

    mov rax,qword [lo] ; f = lo
    mov qword [f],rax

.nextfor:
    mov rax,qword [f]  ; f <= hi
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .donefor

    mov rax,qword [unique]
    mov rcx,FALSE
    cmp rax,rcx
    je .inif

; ((f != a) && (f != c) && (f != d) && (f != g) && (f != e))

    mov rax,qword [f]

    mov rcx,qword [a] ; (f != a)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [c] ; (f != c)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [d] ; (f != d)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [g] ; (f != g)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [e] ; (f != e)
    cmp rax,rcx
    je .skipif

.inif:
    mov rax,qword [e] ; b = e + f - c;
    mov rcx,qword [f]
    add rax,rcx
    mov rcx,qword [c]
    sub rax,rcx
    mov qword [b],rax

; ((b >= lo) &&
;  (b <= hi) &&
;  ((!unique) ||
;   ((b != a) &&
;    (b != c) &&
;    (b != d) &&
;    (b != g) &&
;    (b != e) &&
;    (b != f)
;   )
;  )
; )

    mov rax,qword [b]  ;(b >= lo)
    mov rcx,qword [lo]
    cmp rax,rcx
    jl .skipif

    mov rax,qword [b]  ;(b <= hi)
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .skipif

    mov rax,qword [unique] ;(!unique)
    mov rcx,FALSE
    cmp rax,rcx
    je .innerifsucceeds

    mov rax,qword [b]  ;(b != a)
    mov rcx,qword [a]
    cmp rax,rcx
    je .skipif

    mov rcx,qword [c]  ;(b != c)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [d]  ;(b != d)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [g]  ;(b != g)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [e]  ;(b != e)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [f]  ;(b != f)
    cmp rax,rcx
    je .skipif

.innerifsucceeds:
    mov rax,qword [solutions] ; solutions++
    inc rax
    mov qword [solutions],rax

    mov rax,qword [show]
    cmp rax,TRUE
    jne .skipif

    call print_output

.skipif:
    mov rax,qword [f] ; f++
    inc rax
    mov qword [f],rax
    jmp .nextfor

.donefor:
    xor rax,rax
    leave
    ret

print_output:
    push rbp
    mov rbp,rsp

; printf("%d %d %d %d %d %d %d
",a,b,c,d,e,f,g);

    lea rdi,[output_fmt]
    mov rsi,qword [a]
    mov rdx,qword [b]
    mov rcx,qword [c]
    mov r8,qword [d]
    mov r9,qword [e]
    mov rax,qword [g]
    push rax
    mov rax,qword [f]
    push rax
    xor rax,rax
    call printf

    xor rax,rax
    leave
    ret

The code replaces the variables a, b, c, d, e, f, and g with decimal digits from a given range (LOW to HIGH) to make the sum of variables in each of the four large squares equal. It generates all unique solutions for ranges 1-7 and 3-9, and counts the number of solutions (including non-unique) for the range 0-9. It also includes a solution for a related no connection puzzle.


        .MODEL  TINY
        .CODE
        .486
        ORG     100H            ;.COM FILES START HERE
YEAR    EQU     1969            ;DISPLAY CALENDAR FOR SPECIFIED YEAR
START:  MOV     CX, 61          ;SPACE(61);  TEXT(0, "[SNOOPY]");  CRLF(0)
        CALL    SPACE
        MOV     DX, OFFSET SNOOPY
        CALL    TEXT
        MOV     CL, 63          ;SPACE(63);  INTOUT(0, YEAR);  CRLF(0);  CRLF(0)
        CALL    SPACE
        MOV     AX, YEAR
        CALL    INTOUT
        CALL    CRLF
        CALL    CRLF

        MOV     DI, 1           ;FOR MONTH:= 1 TO 12 DO         DI=MONTH
L22:    XOR     SI, SI          ; FOR COL:= 0 TO 6-1 DO         SI=COL
L23:    MOV     CL, 5           ;  SPACE(5)
        CALL    SPACE
        MOV     DX, DI          ;  TEXT(0, MONAME(MONTH+COL-1));  SPACE(7);
        DEC     DX              ;  DX:= (MONTH+COL-1)*10+MONAME
        ADD     DX, SI
        IMUL    DX, 10
        ADD     DX, OFFSET MONAME
        CALL    TEXT
        MOV     CL, 7
        CALL    SPACE
        CMP     SI, 5           ;  IF COL<5 THEN SPACE(1);
        JGE     L24
         MOV    CL, 1
         CALL   SPACE
         INC    SI
         JMP    L23
L24:    CALL    CRLF

        MOV     SI, 6           ; FOR COL:= 0 TO 6-1 DO
L25:    MOV     DX, OFFSET SUMO ;  TEXT(0, "SU MO TU WE TH FR SA");
        CALL    TEXT
        DEC     SI              ;   IF COL<5 THEN SPACE(2);
        JE      L27
         MOV    CL, 2
         CALL   SPACE
         JMP    L25
L27:    CALL    CRLF

        XOR     SI, SI          ;FOR COL:= 0 TO 6-1 DO
L28:    MOV     BX, DI          ;DAY OF FIRST SUNDAY OF MONTH (CAN BE NEGATIVE)
        ADD     BX, SI          ;DAY(COL):= 1 - WEEKDAY(YEAR, MONTH+COL, 1);
        MOV     BP, YEAR

;DAY OF WEEK FOR FIRST DAY OF THE MONTH (0=SUN 1=MON..6=SAT)
        CMP     BL, 2           ;IF MONTH<=2 THEN
        JG      L3
         ADD    BL, 12          ; MONTH:= MONTH+12;
         DEC    BP              ; YEAR:= YEAR-1;
L3:
;REM((1-1 + (MONTH+1)*26/10 + YEAR + YEAR/4 + YEAR/100*6 + YEAR/400)/7)
        INC     BX              ;MONTH
        IMUL    AX, BX, 26
        MOV     CL, 10
        CWD
        IDIV    CX
        MOV     BX, AX
        MOV     AX, BP          ;YEAR
        ADD     BX, AX
        SHR     AX, 2
        ADD     BX, AX
        MOV     CL, 25
        CWD
        IDIV    CX
        IMUL    DX, AX, 6       ;YEAR/100*6
        ADD     BX, DX
        SHR     AX, 2           ;YEAR/400
        ADD     AX, BX
        MOV     CL, 7
        CWD
        IDIV    CX
        NEG     DX
        INC     DX
        MOV     [SI+DAY], DL    ;COL+DAY
        INC     SI
        CMP     SI, 5
        JLE     L28

        MOV     BP, 6           ;FOR LINE:= 0 TO 6-1 DO         BP=LINE
L29:    XOR     SI, SI          ; FOR COL:= 0 TO 6-1 DO         SI=COL
L30:    MOV     BX, DI          ;  DAYMAX:= DAYS(MONTH+COL);
        MOV     BL, [BX+SI+DAYS]

;IF MONTH+COL=2 & (REM(YEAR/4)=0 & REM(YEAR/100)#0 ! REM(YEAR/400)=0) THEN
        MOV     AX, DI          ;MONTH
        ADD     AX, SI
        CMP     AL, 2
        JNE     L32
        MOV     AX, YEAR
        TEST    AL, 03H
        JNE     L32
        MOV     CL,100
        CWD
        IDIV    CX
        TEST    DX, DX
        JNE     L31
        TEST    AL, 03H
        JNE     L32
L31:     INC    BX              ;IF FEBRUARY AND LEAP YEAR THEN ADD A DAY
L32:
        MOV     DX, 7           ;FOR WEEKDAY:= 0 TO 7-1 DO
L33:    MOVZX   AX, [SI+DAY]    ; IF DAY(COL)>=1 & DAY(COL)<=DAYMAX THEN
        CMP     AL, 1
        JL      L34
        CMP     AL, BL
        JG      L34
        CALL    INTOUT          ; INTOUT(0, DAY(COL));
        CMP     AL, 10          ; IF DAY(COL)<10 THEN SPACE(1); LEFT JUSTIFY
        JGE     L36
         MOV    CL, 1
         CALL   SPACE
        JMP     L36
L34:    MOV     CL, 2           ; ELSE SPACE(2);
        CALL    SPACE           ; SUPPRESS OUT OF RANGE DAYS
L36:    MOV     CL, 1           ; SPACE(1);
        CALL    SPACE
        INC     BYTE PTR [SI+DAY] ; DAY(COL):= DAY(COL)+1;
        DEC     DX              ;NEXT WEEKDAY
        JNE     L33

        CMP     SI, 5           ;IF COL<5 THEN SPACE(1);
        JGE     L37
         MOV    CL, 1
         CALL   SPACE
         INC    SI
         JMP    L30
L37:    CALL    CRLF

        DEC     BP              ;NEXT LINE DOWN
        JNE     L29
        CALL    CRLF

        ADD     DI, 6           ;NEXT 6 MONTHS
        CMP     DI, 12
        JLE     L22
        RET

;DISPLAY POSITIVE INTEGER IN AX
INTOUT: PUSHA
        MOV     BX, 10
        XOR     CX, CX
NO10:   CWD
        IDIV    BX
        PUSH    DX
        INC     CX
        TEST    AX, AX
        JNE     NO10
NO20:   MOV     AH, 02H
        POP     DX
        ADD     DL, '0'
        INT     21H
        LOOP    NO20
        POPA
        RET

;DISPLAY CX SPACE CHARACTERS
SPACE:  PUSHA
SP10:   MOV     AH, 02H
        MOV     DL, 20H
        INT     21H
        LOOP    SP10
        POPA
        RET

;START A NEW LINE
CRLF:   MOV     DX, OFFSET LCRLF

;DISPLAY STRING AT DX
TEXT:   MOV     AH, 09H
        INT     21H
        RET

SNOOPY  DB      "[SNOOPY]"
LCRLF   DB      0DH, 0AH, '$'
MONAME  DB      " JANUARY $ FEBRUARY$  MARCH  $  APRIL  $   MAY   $   JUNE  $"
        DB      "   JULY  $  AUGUST $SEPTEMBER$  OCTOBER$ NOVEMBER$ DECEMBER$"
SUMO    DB      "SU MO TU WE TH FR SA$"
DAYS    DB      0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
DAY     DB      ?, ?, ?, ?, ?, ?
        END     START

The code provides an algorithm for a calendar task, formatted to fit a 132-character wide page, mimicking the style of 1969 era line printers. The entire code is written in uppercase, inspired by the practices of real programmers in the 1960s. It does not include Snoopy generation, instead, it outputs a placeholder. The code is assembled with TASM CALENDAR and TLINK /t CALENDAR.


Library: GTK
Works with: NASM
;GTK imports and defines etc.
%define GTK_WINDOW_TOPLEVEL 0

extern gtk_init
extern gtk_window_new
extern gtk_widget_show
extern gtk_signal_connect
extern gtk_main
extern g_print
extern gtk_main_quit

bits 32

section .text
	global _main

        ;exit signal
	sig_main_exit:
		push exit_sig_msg
		call g_print
		add esp, 4
		call gtk_main_quit
		ret

	_main:
		mov ebp, esp
		sub esp, 8
		push argv
		push argc
		call gtk_init
		add esp, 8				;stack alignment.
		push GTK_WINDOW_TOPLEVEL
		call gtk_window_new
		add esp, 4
		mov [ebp-4], eax		;ebp-4 now holds our GTKWindow pointer.
		push 0
		push sig_main_exit
		push gtk_delete_event
		push dword [ebp-4]
		call gtk_signal_connect
		add esp, 16
		push dword [ebp-4]
		call gtk_widget_show
		add esp, 4
		call gtk_main

section .data
;sudo argv
argc                dd 1
argv                dd args
args                dd title
						  dd 0

title               db "GTK Window",0
gtk_delete_event   db 'delete_event',0
exit_sig_msg      db "-> Rage quitting..",10,0

Works with: MASM
.586
.model flat, stdcall
option casemap:none

include /masm32/include/windows.inc
include /masm32/include/kernel32.inc
include /masm32/include/user32.inc

includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/user32.lib

WinMain proto :dword,:dword,:dword,:dword

.data
   ClassName db "WndClass",0
   AppName   db "Window!",0
.data?
   hInstance   dd ?
   CommandLine dd ?

.code
start:
   invoke GetModuleHandle, NULL
   mov hInstance, eax
   invoke GetCommandLine
   mov CommandLine, eax
   invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT

   WinMain proc hInst:dword, hPervInst:dword, CmdLine:dword, CmdShow:dword
   LOCAL wc:WNDCLASSEX
   LOCAL msg:MSG
   LOCAL hwnd:HWND

   wc.cbSize, sizeof WNDCLASSEX
   wc.style, CS_HREDRAW or CS_VREDRAW
   wc.lpfnWndPRoc, offset WndProc
   wc.cbClsExtra,NULL
   wc.cbWndExtra, NULL
   push hInstance
   pop wc.hInstance
   mov wc.hbrBackground, COLOR_BTNFACE+1
   mov wc.lpszMenuName NULL
   mov wc.lpszClassName, offset ClassName
   invoke LoadIcon, NULL, IDI_APPLICATION
   mov wc.hIcon, eax
   mov wc.hIconSm, eax
   invoke LoadCursor, NULL, IDC_ARROW
   mov wc.hCursor, eax
   invoke RegisterClassEx, addr wc
   invoke CreateWindowEx, NULL, addr ClassName, addr AppName, WS_OVERLAPPEDWINDOW, CS_USEDEFAULT, CW_USEDEFAUT,\
   CW_USEDEFAUT, CW_USEDEFAUT, NULL, NULL, hInst, NULL
   mov hwnd, eax
   invoke ShowWindow, hwnd, SW_SHOWNORMAL
   invoke UpdateWindow, hwnd
   .while TRUE
      invoke GetMessage, addr msg, NULL, 0,0
      .break .if (!eax)
      invoke TranslateMessage, addr msg
      invoke DispatchMessage, addr msg
   .endw
   mov eax, msg.wParam
   ret
   WinMain endp

   WndProc proc hWnd:dword, uMsg:dword, wParam:dword, lParam:dword
   mov eax, uMsg
   .if eax==WM_DESTROY
      invoke PostQuitMessage, NULL
   .else
      invoke DefWindowProc, hWnd, uMsg, wParam, lParam
   .endif
   xor eax, eax
   ret
   WndProc endp
end start

Create an empty GUI window that can respond to close requests.


; x86_64 Linux NASM
; Linked_List_Definition.asm

%ifndef LinkedListDefinition
%define LinkedListDefinition

struc link
  value: resd 1
  next: resq 1
  linkSize:
endstruc

%endif

Works with: NASM
struct link
.next: resd 1
.data: resd 1
endstruc

link resb 16

Works with: MASM
link struct
next dd ?
data dd ?
link ends

Works with: FASM
struc link next,data
{
    .next dd next
    .data dd data
}

define a data structure for a singly-linked list element. This element contains a numeric data member and a mutable link to the next element. The code is part of the implementations for singly-linked list operations. The structure is thought of in terms of 16 bytes (2 dwords) due to the lack of native structures in ASM.


Works with: nasm
section .bss
    factorArr resd 250 ;big buffer against seg fault

section .text
global _main
_main:
    mov ebp, esp; for correct debugging
    mov eax, 0x7ffffffe ;number of which we want to know the factors, max num this program works with
    mov ebx, eax ;save eax
    mov ecx, 1 ;n, factor we test for
    mov [factorArr], dword 0
    looping:
        mov eax, ebx ;restore eax
        xor edx, edx ;clear edx
        div ecx
        cmp edx, 0 ;test if our number % n == 0
        jne next
        mov edx, [factorArr] ;if yes, we increment the size of the array and append n
        inc edx
        mov [factorArr+edx*4], ecx ;appending n
        mov [factorArr], edx ;storing the new size
    next:
        mov eax, ecx
        cmp eax, ebx ;is n bigger then our number ?
        jg end ;if yes we end
        inc ecx
        jmp looping
    end:
        mov ecx, factorArr ;pass arr address by ecx
        xor eax, eax ;clear eax
        mov esp, ebp ;garbage collecting
        ret

compute the factors of a given positive integer, excluding zero and negative numbers. The factors are the positive integers that can divide the input number to yield a positive integer. For prime numbers, the factors are 1 and the number itself.


      1                                  ;Assemble with: tasm, tlink /t
      2     0000                                 .model  tiny
      3     0000                                 .code
      4                                          .386
      5                                          org     100h
      6                                  ;assume: ax=0000h, bx=0000h, cx=00ff, and
      7                                  ; direction bit is clear (so di increments)
      8                                                                  ;                  ____
      9           =0050                  X0      equ     80              ;                 /   /|
     10           =0050                  Y0      equ     80              ;                /   / |
     11           =0050                  wide    equ     2*40            ;         X0,Y0 +---+  |
     12           =0064                  tall    equ     3*40*200/240    ;               |   |  |
     13           =0035                  deep    equ     4*40/3          ;               |   | /
     14                                                                  ;               |___|/
     15
     16     0100  B0 13                  start:  mov     al, 13h         ;set 320x200x8 graphic screen
     17     0102  CD 10                          int     10h
     18     0104  68 A000                        push    0A000h          ;point es to graphic memory segment
     19     0107  07                             pop     es
     20
     21                                  ;Draw front of cuboid using horizontal lines
     22     0108  B3 64                          mov     bl, tall
     23     010A  BF E150                        mov     di, X0+(Y0+tall)*320 ;set pen at lower-left corner
     24     010D  B0 04                          mov     al, 4           ;use red ink
     25     010F  B1 50                  dc10:   mov     cl, wide        ;draw horizontal line
     26     0111  F3> AA                         rep     stosb           ;es:[di++], al; cx--
     27     0113  81 EF 0190                     sub     di, wide+320    ;move up to start of next line
     28     0117  4B                             dec     bx              ;at top of face?
     29     0118  75 F5                          jne     dc10            ;loop if not
     30
     31     011A  B3 35                          mov     bl, deep
     32                                  ;Draw top using horizontal lines
     33     011C  B0 02                  dc20:   mov     al, 2           ;use green ink
     34     011E  B1 50                          mov     cl, wide        ;draw horizontal line
     35     0120  F3> AA                         rep     stosb           ;es:[di++], al; cx--
     36
     37                                  ;Draw side using vertical lines
     38     0122  B0 01                          mov     al, 1           ;use blue ink
     39     0124  B1 64                          mov     cl, tall        ;draw vertical line
     40     0126  AA                     dc30:   stosb                   ;es:[di++], al
     41     0127  81 C7 013F                     add     di, 320-1       ;move down a pixel
     42     012B  E2 F9                          loop    dc30
     43
     44     012D  81 EF 7E8F                     sub     di, wide+(tall+1)*320-1 ;move to start of next top line
     45     0131  4B                             dec     bx              ;at deep limit?
     46     0132  75 E8                          jne     dc20            ;loop if not
     47
     48     0134  CD 16                          int     16h             ;wait for keystroke (ah=0)
     49     0136  B8 0003                        mov     ax, 0003h       ;restore normal text-mode screen
     50     0139  CD 10                          int     10h
     51     013B  C3                             ret                     ;return to DOS
     52
     53                                          end     start

draw a cuboid with dimensions 2x3x4, representing it graphically or in ASCII art based on language capabilities, showing three visible faces, and allowing either static or rotational projection. The code is optimized to be within sixty bytes.


format 	ELF 	executable 3
entry 	start

segment	readable writeable
buf	rb	1

segment	readable executable
start:	mov	eax, 3		; syscall "read"
	mov	ebx, 0		; stdin
	mov	ecx, buf	; buffer for read byte
	mov	edx, 1		; len (read one byte)
	int	80h

	cmp	eax, 0		; EOF?
	jz	exit

	xor 	eax, eax	; load read char to eax
	mov	al, [buf]
	cmp	eax, "A"	; see if it is in ascii a-z or A-Z
	jl	print
	cmp	eax, "z"
	jg	print
	cmp	eax, "Z"
	jle	rotup
	cmp	eax, "a"
	jge	rotlow
	jmp	print

rotup:	sub	eax, "A"-13	; do rot 13 for A-Z
	cdq
	mov	ebx, 26
	div	ebx
	add	edx, "A"
	jmp	rotend

rotlow:	sub	eax, "a"-13	; do rot 13 for a-z
	cdq
	mov	ebx, 26
	div	ebx
	add	edx, "a"

rotend:	mov	[buf], dl

print: 	mov	eax, 4		; syscall write
	mov	ebx, 1		; stdout
	mov	ecx, buf	; *char
	mov	edx, 1		; string length
	int	80h

	jmp	start

exit: 	mov     eax,1		; syscall exit
	xor     ebx,ebx		; exit code
	int     80h

implement a rot-13 function that can be optionally wrapped in a utility program. This function replaces every ASCII alphabet letter with the letter that is 13 characters away from it in the 26 letter alphabet, wrapping from z to a as necessary. It works on both upper and lower case letters, preserves case, and passes all non-alphabetic characters without alteration. This function is used for obfuscating text to prevent casual reading of spoilers or offensive material. It is implemented in a Linux/FASM environment.


;x86-64 assembly code for Microsoft Windows
;Tested in windows 7 Enterprise Service Pack 1 64 bit
;With the AMD FX(tm)-6300 processor
;Assembled with NASM version 2.11.06
;Linked to C library with gcc version 4.9.2 (x86_64-win32-seh-rev1, Built by MinGW-W64 project)

;Assembled and linked with the following commands:
;nasm -f win64 <filename>.asm -o <filename>.obj
;gcc <filename>.obj -o <filename>

;Takes number of iterations to run RNG loop as command line parameter.

extern printf,puts,atoi,exit,time,malloc

section .data
align 64
errmsg_argnumber: db "There should be no more than one argument.",0
align 64
errmsg_noarg: db "Number of iterations was not specified.",0
align 64
errmsg_zeroiterations: db "Zero iterations of RNG loop specified.",0

align 64
errmsg_timefail: db "Unable to retrieve calender time.",0
align 64
errmsg_mallocfail: db "Unable to allocate memory for array of random numbers.",0

align 64
fmt_random: db "The %u number generated is %d",0xa,0xd,0

section .bss

section .text
global main

main:

;check for argument
cmp rcx,1
jle err_noarg

;ensure that only one argument was entered
cmp rcx,2
jg err_argnumber

;get number of times to iterate get_random
mov rcx,[rdx + 8]
call atoi

;ensure that number of iterations is greater than 0
cmp rax,0
jle err_zeroiterations
mov rcx,rax

;calculate space needed for an array containing the random numbers
shl rcx,2

;move size of array into r14
mov r14,rcx

;reserve memory for array of random numbers with malloc
call malloc

cmp rax,0
jz err_mallocfail

;pointer to array in r15
mov r15,rax

;seed the RNG using time()
xor rcx,rcx
call time

;ensure that time returns valid output
cmp rax,-1
jz err_timefail

;calculate address of end of array in r14
add r14,r15

;pointer to array of random numbers in r15
;address of end of array in r14
;current address in array in rdi
;multiplier in rbx
;seed in rax
;current random number in rcx

;prepare random number generator

mov rdi,r15

mov rbx,214013

get_random:

;multiply by 214013 and add 2561011 to get next state
mul ebx
add eax,2531011

;shr by 16 and AND with 0x7FFF to get current random number
mov ecx,eax
shr ecx,16
and ecx,0x7fff

;store random number in array
mov [rdi],ecx

add rdi,4
cmp rdi,r14
jl get_random

;pointer to array of random numbers in r15
;address of end of array in r14
;current address in array in rdi
;array index in rsi

xor rsi,rsi
mov rdi,r15

print_random:

mov rcx,fmt_random
mov rdx,rsi
mov r8d,[rdi]
call printf

add rsi,1
add rdi,4
cmp rdi,r14
jl print_random

xor rcx,rcx
call exit

;;;;;;;;;;ERROR MESSAGES;;;;;;;;;;;;;;;;

err_argnumber:

mov rcx,errmsg_argnumber
call puts

jmp exit_one

err_noarg:

mov rcx,errmsg_noarg
call puts

jmp exit_one

err_zeroiterations:

mov rcx,errmsg_zeroiterations
call puts

jmp exit_one

err_timefail:

mov rcx,errmsg_timefail
call puts

jmp exit_one

err_mallocfail:

mov rcx,errmsg_mallocfail
call puts

exit_one:

mov rcx,1
call exit

This example is incorrect.  Please fix the code and remove this message.Details: It will not produce output identical to that of the Microsoft rand() function.

;x86-64 assembly code for Microsoft Windows
;Tested in windows 7 Enterprise Service Pack 1 64 bit
;With the AMD FX(tm)-6300 processor
;Assembled with NASM version 2.11.06
;Linked to C library with gcc version 4.9.2 (x86_64-win32-seh-rev1, Built by MinGW-W64 project)

;Assembled and linked with the following commands:
;nasm -f win64 <filename>.asm -o <filename>.obj
;gcc <filename>.obj -o <filename>

;Takes number of iterations to run RNG loop as command line parameter.

extern printf,puts,atoi,exit,time,_aligned_malloc

section .data
align 64
errmsg_argnumber: db "There should be no more than one argument.",0
align 64
errmsg_noarg: db "Number of iterations was not specified.",0
align 64
errmsg_zeroiterations: db "Zero iterations of RNG loop specified.",0

align 64
errmsg_timefail: db "Unable to retrieve calender time.",0
align 64
errmsg_mallocfail: db "Unable to allocate memory for array of random numbers.",0

align 64
fmt_random: db "The %u number generated is %d",0xa,0xd,0

align 16
multiplier: dd 214013,17405,214013,69069
align 16
addend: dd 2531011, 10395331, 13737667, 1
align 16
mask: dd  0xffffffff,0,0xffffffff,0
align 16
masklo: dd 0x7fff,0x7fff,0x7fff,0x7fff

section .bss

section .text
global main

main:

;check for argument
cmp rcx,1
jle err_noarg

;ensure that only one argument was entered
cmp rcx,2
jg err_argnumber

;get number of times to iterate get_random
mov rcx,[rdx + 8]
call atoi

;ensure that number of iterations is greater than 0
cmp rax,0
jle err_zeroiterations
mov rcx,rax

;calculate space needed for an array containing the random numbers
shl rcx,4

;move size of array into r14
mov r14,rcx

;16 byte alignment boundary
mov rdx,16

;reserve memory aligned to 16 byte boundary for array with _aligned_malloc
call _aligned_malloc

cmp rax,0
jz err_mallocfail

;pointer to array in r15
mov r15,rax

;seed the RNG using time()
xor rcx,rcx
call time

;ensure that time returns valid output
cmp rax,-1
jz err_timefail

;pointer to array of random numbers in r15
;address of end of array at in r14
;states stored in xmm0

;calculate address of end of array in r14
add r14,r15

;load seed,seed+1,seed,seed+1 into xmm0
lea rbx,[rax - 1]
shl rax,32
or rax,rbx

movq xmm0,rax
vpslldq xmm1,xmm0,8
vpor xmm0,xmm0,xmm1

;pointer to array of random numbers in r15
;address of end of array in r14
;current address in array in rdi
;current states in xmm0
;multiplier in xmm1
;addened in xmm2
;mask in xmm3
;masklo in xmm4
;split seed in xmm5
;current set of random numbers in xmm6

;prepare random number generator

mov rdi,r15

vmovdqa xmm1,[multiplier]
vmovdqa xmm2,[addend]
vmovdqa xmm3,[mask]
vmovdqa xmm4,[masklo]

get_random:

;arrange order of current states to 2,3,0,1 and store in split seed
vpshufd xmm5,xmm0,10110001b

;multiply current states by multiplier
vpmulld xmm0,xmm0,xmm1

;set order of multiplier to 2,3,0,1
vpshufd xmm1,xmm1,10110001b

;multiply split seed by multiplier
vpmulld xmm5,xmm5,xmm1

;and current states with mask
vpand xmm0,xmm0,xmm3

;and current split seed with mask
vpand xmm5,xmm5,xmm3

;set order of split seed to 2,3,0,1
vpshufd xmm5,xmm5,10110001b

;or current states with split seed
vpor xmm0,xmm0,xmm5

;add adder to current states
vpaddd xmm0,xmm0,xmm2

;shift vector right by two bytes
vpsrldq xmm6,xmm0,2

;and each state with 0x7fff
vpand xmm6,xmm6,xmm4

vmovdqa [rdi],xmm6

add rdi,16
cmp rdi,r14
jl get_random

;pointer to array of random numbers in r15
;address of end of array in r14
;current address in array in rdi
;array index in rsi

xor rsi,rsi
mov rdi,r15

print_random:

mov rcx,fmt_random
mov rdx,rsi
mov r8d,[rdi]
call printf

add rsi,1
add rdi,4
cmp rdi,r14
jl print_random

xor rcx,rcx
call exit

;;;;;;;;;;ERROR MESSAGES;;;;;;;;;;;;;;;;

err_argnumber:

mov rcx,errmsg_argnumber
call puts

jmp exit_one

err_noarg:

mov rcx,errmsg_noarg
call puts

jmp exit_one

err_zeroiterations:

mov rcx,errmsg_zeroiterations
call puts

jmp exit_one

err_timefail:

mov rcx,errmsg_timefail
call puts

jmp exit_one

err_mallocfail:

mov rcx,errmsg_mallocfail
call puts

exit_one:

mov rcx,1
call exit

Sample:

F:\>lcgint.exe 20
The 0 number generated is 20272
The 1 number generated is 4467
The 2 number generated is 8618
The 3 number generated is 1587
The 4 number generated is 2687
The 5 number generated is 21398
The 6 number generated is 29522
The 7 number generated is 27724
The 8 number generated is 23875
The 9 number generated is 2399
The 10 number generated is 4086
The 11 number generated is 923
The 12 number generated is 23002
The 13 number generated is 11586
The 14 number generated is 13200
The 15 number generated is 22090
The 16 number generated is 26528
The 17 number generated is 14271
The 18 number generated is 10476
The 19 number generated is 9981

F:\>

F:\>lcgavx.exe 5
The 0 number generated is 20370
The 1 number generated is 45
The 2 number generated is 20541
The 3 number generated is 15699
The 4 number generated is 23637
The 5 number generated is 30131
The 6 number generated is 26151
The 7 number generated is 27319
The 8 number generated is 26933
The 9 number generated is 28417
The 10 number generated is 16647
The 11 number generated is 14840
The 12 number generated is 29228
The 13 number generated is 16968
The 14 number generated is 1027
The 15 number generated is 12099
The 16 number generated is 17170
The 17 number generated is 23893
The 18 number generated is 18556
The 19 number generated is 16434

F:\>

The code replicates two historic random number generators: the rand() function from BSD libc and the rand() function from the Microsoft C Runtime (MSCVRT.DLL). The generators use the linear congruential generator formula with specific constants and seeds. The BSD version generates random numbers in the range 0 to 2147483647, while the Microsoft version generates numbers in the range 0 to 32767. The sequence of generated numbers can be reproduced given the same seed.


; x86_64 Linux NASM
; Linked_List_Insert.asm

%ifndef INSERT
%define INSERT

%include "Linked_List_Definition.asm" ; see LL def task
%include "Heap_Alloc.asm" ; see memory allocation task

section .text

; rdi - link to insert after
; rsi - value that the new link will hold
Insert_After:
  push rdi
  push rsi
  mov rdi, linkSize
  call alloc
  cmp rax, 0
  je Memory_Allocation_Failure_Exception
  pop rdi
  mov dword [rax + value], edi
  pop rdi
  mov rsi, qword [rdi + next]
  mov qword [rax + next], rsi
  mov qword [rdi + next], rax
  ret

%endif

"Defines a method to insert an element into a singly-linked list after a specified element. Specifically, it inserts element C into a list of elements A->B, after element A."


format PE64 console
entry start

    include 'win64a.inc'

section '.text' code readable executable

    start:
        stdcall dotProduct, vA, vB
        invoke printf, msg_num, rax

        stdcall dotProduct, vA, vC
        invoke printf, msg_num, rax

        invoke ExitProcess, 0

    proc dotProduct vectorA, vectorB
        mov rax, [rcx]
        cmp rax, [rdx]
        je .calculate

        invoke printf, msg_sizeMismatch
        mov rax, 0
        ret

        .calculate:
        mov r8, rcx
        add r8, 8
        mov r9, rdx
        add r9, 8
        mov rcx, rax
        mov rax, 0
        mov rdx, 0

        .next:
            mov rbx, [r9]
            imul rbx, [r8]
            add rax, rbx
            add r8, 8
            add r9, 8
            loop .next

        ret
    endp

section '.data' data readable

    msg_num db "%d", 0x0D, 0x0A, 0
    msg_sizeMismatch db "Size mismatch; can't calculate.", 0x0D, 0x0A, 0

    struc Vector [symbols] {
        common
        .length dq (.end - .symbols) / 8
        .symbols dq symbols
        .end:
    }

    vA Vector 1, 3, -5
    vB Vector 4, -2, -1
    vC Vector 7, 2, 9, 0

section '.idata' import data readable writeable

    library kernel32, 'KERNEL32.DLL',\
            msvcrt, 'MSVCRT.DLL'

    include 'api/kernel32.inc'

    import  msvcrt,\
            printf, 'printf'

The code calculates the dot product of two vectors of arbitrary length. It ensures both vectors are of the same length, multiplies corresponding terms from each vector, and sums the products to produce the final result. Implemented using FASM and targets x64 Microsoft Windows.


        .model  tiny
        .code
        .486
        org     100h            ;assume ax=0, bx=0, sp=-2
start:  mov     al, 13h         ;(ah=0) set 320x200 video graphics mode
        int     10h
        push    0A000h
        pop     es
        mov     si, 8000h       ;color

        mov     cx, 75*256+100  ;coordinates of initial horizontal line segment
        mov     dx, 75*256+164  ;use power of 2 for length

        call    dragon
        mov     ah, 0           ;wait for keystroke
        int     16h
        mov     ax, 0003h       ;restore normal text mode
        int     10h
        ret

dragon: cmp     sp, -100        ;at maximum recursion depth?
        jne     drag30          ;skip if not
        mov     bl, dh          ;draw at max depth to get solid image
        imul    di, bx, 320     ;(bh=0) plot point at X=dl, Y=dh
        mov     bl, dl
        add     di, bx
        mov     ax, si          ;color
        shr     ax, 13
        or      al, 8           ;use bright colors 8..F
        stosb                   ;es:[di++]:= al
        inc     si
        ret
drag30:
        push    cx              ;preserve points P and Q
        push    dx

        xchg    ax, dx          ;DX:= Q(0)-P(0);
        sub     al, cl
        sub     ah, ch          ;DY:= Q(1)-P(1);

        mov     dx, ax          ;new point
        sub     dl, ah          ;R(0):= P(0) + (DX-DY)/2
        jns     drag40
         inc    dl
drag40: sar     dl, 1           ;dl:= (al-ah)/2 + cl
        add     dl, cl

        add     dh, al          ;R(1):= P(1) + (DX+DY)/2;
        jns     drag45
         inc    dh
drag45: sar     dh, 1           ;dh:= (al+ah)/2 + ch
        add     dh, ch

        call    dragon          ;Dragon(P, R);
        pop     cx              ;get Q
        push    cx
        call    dragon          ;Dragon(Q, R);

        pop     dx              ;restore points
        pop     cx
        ret
        end     start

The code generates a Dragon Curve fractal, either displaying it directly or writing it to an image file. It utilizes various algorithms to create the fractal, including recursive, successive approximation, iterative, and Lindenmayer system methods. The code also includes functionality to calculate the absolute direction and X,Y coordinates of a point, and to test whether a given point or segment is on the curve. The curve can be limited to a specific number of points or a subsection. The code is translated from XPL0 and assembled with tasm, tlink /t.


Works with: NASM version Linux
 segment .data

      random  dd  0   ; Where the random number will be stored
      guess   dd  0   ; Where the user input will be stored

     instructions    db  10, "Welcome user! The game is simple: Guess a random number (1-10)!", 10, 10
     len1 equ $ - instructions   ; 1 \n before and 2 \n after instructions for better appearance

     wrong           db  "Not the number :(", 10
     len2 equ $ - wrong

     correct         db  "You guessed right, congratulations :D", 10
     len3 equ $ - correct

 segment .bss

 segment .text
     global  main

 main:
     push    rbp
     mov     rbp, rsp
     ; ********** CODE STARTS HERE **********

     ;;;;; Random number generator ;;;;;

     mov     eax, 13
     mov     ebx, random
     int     80h
     mov     eax, [ebx]
     mov     ebx, 10
     xor     edx, edx
     div     ebx
     inc     edx
     mov     [random], edx

     ;;;;; Print the instructions ;;;;;

     mov     eax, 4
     mov     ebx, 1
     mov     ecx, instructions
     mov     edx, len1
     int     80h

 userInput:

     ;;;;; Ask user for input ;;;;;

     mov     eax, 3
     xor     ebx, ebx
     mov     ecx, instructions
     mov     edx, 1
     int     80h
     mov     al, [ecx]
     cmp     al, 48
     jl      valCheck
     cmp     al, 57
     jg      valCheck

     ;;;;; If number ;;;;;

     sub     al, 48
     xchg    eax, [guess]
     mov     ebx, 10
     mul     ebx
     add     [guess], eax
     jmp     userInput

 valCheck:

     ;;;;; Else check number ;;;;;

     mov     eax, 4
     inc     ebx
     mov     ecx, [guess]
     cmp     ecx, [random]
     je      correctResult

     ;;;;; If not equal, "not the number :(" ;;;;;

     mov     ecx, wrong
     mov     edx, len2
     mov     DWORD [guess], 0
     int     80h
     jmp     userInput

 correctResult:

     ;;;;; If equal, "congratulations :D" ;;;;;

     mov     ecx, correct
     mov     edx, len3
     int     80h

     ;;;;; EXIT ;;;;;

     mov     rax, 0
     mov     rsp, rbp
     pop     rbp
     ret

; "Guess my number" program by Randomboi (8/8/2021)

"Implement a number guessing game where the computer selects a number between 1 and 10. The player is repeatedly prompted to guess the number until the correct number is guessed, upon which a 'Well guessed!' message is displayed and the program terminates. A conditional loop is used to facilitate repeated guessing."


        .model  tiny
        .code
        .486
        org     100h
start:  mov     ax, 5
        call    binout
        call    crlf
        mov     ax, 50
        call    binout
        call    crlf
        mov     ax, 9000
        call    binout

crlf:   mov     al, 0Dh         ;new line
        int     29h
        mov     al, 0Ah
        int     29h
        ret

binout: push    ax
        shr     ax, 1
        je      bo10
         call   binout
bo10:   pop     ax
        and     al, 01h
        or      al, '0'
        int     29h             ;display character
        ret
        end     start

generate a sequence of binary digits for a given non-negative integer. The output is strictly binary digits with no whitespace, radix, sign markers, or leading zeros. The binary sequence is followed by a newline. The conversion from decimal to binary can be achieved using built-in radix functions or a user-defined function.


        .model  tiny
        .code
        org     100h

start:  mov     ax, 0013h       ;set 320x200x8 graphic screen
        int     10h
        push    0A000h          ;point to graphic memory segment
        pop     es
        mov     byte ptr es:[320*100+100], 28h  ;draw bright red pixel

        mov     ah, 0           ;wait for keystroke
        int     16h
        mov     ax, 0003h       ;restore normal text mode screen
        int     10h
        ret                     ;return to OS
        end     start

The code creates a 320x240 window and draws a red pixel at the position (x=100, y=100). It also includes a feature to wait for a keystroke before returning to the operating system, allowing the pixel to be visible. The executable program is 32 bytes long, created using Borland's tasm and tlink /t.


0000                                 .model  tiny
0000                                 .code
                                     .486
                                     org     100h            ;.com files start here
0100  9B DB E3               start:  finit                   ;initialize floating-point unit (FPU)
                             ;Great circle distance =
                             ; 2.0*Radius * ASin( sqrt( Haversine(Lat2-Lat1) +
                             ;                          Haversine(Lon2-Lon1)*Cos(Lat1)*Cos(Lat2) ) )
0103  D9 06 0191r                    fld     Lat2            ;push real onto FPU stack
0107  D8 26 018Dr                    fsub    Lat1            ;subtract real from top of stack (st(0) = st)
010B  E8 0070                        call    Haversine       ;(1.0-cos(st)) / 2.0
010E  D9 06 0199r                    fld     Lon2            ;repeat for longitudes
0112  D8 26 0195r                    fsub    Lon1
0116  E8 0065                        call    Haversine       ;st(1)=Lats; st=Lons
0119  D9 06 018Dr                    fld     Lat1
011D  D9 FF                          fcos                    ;replace st with its cosine
011F  D9 06 0191r                    fld     Lat2
0123  D9 FF                          fcos            ;st=cos(Lat2); st(1)=cos(Lat1); st(2)=Lats; st(3)=Lons
0125  DE C9                          fmul            ;st=cos(Lat2)*cos(Lat1); st(1)=Lats; st(2)=Lons
0127  DE C9                          fmul            ;st=cos(Lat2)*cos(Lat1)*Lats; st(1)=Lons
0129  DE C1                          fadd            ;st=cos(Lat2)*cos(Lat1)*Lats + Lons
012B  D9 FA                          fsqrt                   ;replace st with its square root
                             ;asin(x) = atan(x/sqrt(1-x^2))
012D  D9 C0                          fld     st              ;duplicate tos
012F  D8 C8                          fmul    st, st          ;x^2
0131  D9 E8                          fld1                    ;get 1.0
0133  DE E1                          fsubr                   ;1 - x^2
0135  D9 FA                          fsqrt                   ;sqrt(1-x^2)
0137  D9 F3                          fpatan                  ;take atan(st(1)/st)
0139  D8 0E 019Dr                    fmul    Radius2         ;*2.0*Radius

                             ;Display value in FPU's top of stack (st)
      =0004                  before  equ     4               ;places before
      =0002                  after   equ     2               ; and after decimal point
      =0001                  scaler  =       1               ;"=" allows scaler to be redefined, unlike equ
                                     rept    after           ;repeat block "after" times
                             scaler  =       scaler*10
                                     endm                    ;scaler now = 10^after

013D  66| 6A 64                      push    dword ptr scaler;use stack for convenient memory location
0140  67| DA 0C 24                   fimul   dword ptr [esp] ;st:= st*scaler
0144  67| DB 1C 24                   fistp   dword ptr [esp] ;round st to nearest integer
0148  66| 58                         pop     eax             ; and put it into eax

014A  66| BB 0000000A                mov     ebx, 10         ;set up for idiv instruction
0150  B9 0006                        mov     cx, before+after;set up loop counter
0153  66| 99                 ro10:   cdq                     ;convert double to quad; i.e: edx:= 0
0155  66| F7 FB                      idiv    ebx             ;eax:= edx:eax/ebx; remainder in edx
0158  52                             push    dx              ;save least significant digit on stack
0159  E2 F8                          loop    ro10            ;cx--; loop back if not zero

015B  B1 06                          mov     cl, before+after;(ch=0)
015D  B3 00                          mov     bl, 0           ;used to suppress leading zeros
015F  58                     ro20:   pop     ax              ;get digit
0160  0A D8                          or      bl, al          ;turn off suppression if not a zero
0162  80 F9 03                       cmp     cl, after+1     ;is digit immediately to left of decimal point?
0165  75 01                          jne     ro30            ;skip if not
0167  43                              inc    bx              ;turn off leading zero suppression
0168  04 30                  ro30:   add     al, '0'         ;if leading zero then ' ' else add 0
016A  84 DB                          test    bl, bl
016C  75 02                          jne     ro40
016E  B0 20                           mov    al, ' '
0170  CD 29                  ro40:   int     29h             ;display character in al register
0172  80 F9 03                       cmp     cl, after+1     ;is digit immediately to left of decimal point?
0175  75 04                          jne     ro50            ;skip if not
0177  B0 2E                           mov    al, '.'         ;display decimal point
0179  CD 29                           int    29h
017B  E2 E2                  ro50:   loop    ro20            ;loop until all digits displayed
017D  C3                             ret                     ;return to OS

017E                         Haversine:                      ;return (1.0-Cos(Ang)) / 2.0 in st
017E  D9 FF                          fcos
0180  D9 E8                          fld1
0182  DE E1                          fsubr
0184  D8 36 0189r                    fdiv    N2
0188  C3                             ret

0189  40000000               N2      dd       2.0
018D  3F21628D               Lat1    dd       0.63041        ;36.12*pi/180
0191  3F17A4E8               Lat2    dd       0.59236        ;33.94*pi/180
0195  BFC19F80               Lon1    dd      -1.51268        ;-86.67*pi/180
0199  C004410B               Lon2    dd      -2.06647        ;-118.40*pi/180
019D  46472666               Radius2 dd      12745.6         ;6372.8 average radius of Earth (km) times 2
                             ;(TASM isn't smart enough to do floating point constant calculations)
                                     end     start

The code implements the Haversine formula to calculate the great-circle distance between two points on a sphere using their longitudes and latitudes. The points used in this case are the Nashville International Airport (BNA) and the Los Angeles International Airport (LAX). The code also considers the earth's radius, with two possible values (6371.0 km and 6372.8 km) leading to slightly different distance results. The recommended radius value for practical precision is 6372.8 km, although for real applications, the mean earth radius of 6371 km is suggested.


Works with: nasm
Works with: windows
extern _printf

section .data
    output db 0,0

section .text
global _main
_main:
    mov bl, 0
    looping:
        add bl, 0x31 ;0x30 to 0x39 is 0 to 9 in ASCII
        mov [output], bl
        sub bl, 0x30
        push output
        call _printf
        add esp, 4
        xor eax, eax
        xor edx, edx
        mov al, bl
        mov ecx, 6
        div ecx ; remainder is saved in edx
        cmp edx, 0
        jne looping ; if n & 6 != 0 do looping again
    xor eax, eax
    ret

The code initializes a value to 0, then enters a do-while loop where it increments the value by 1 and prints it, continuing as long as the value modulo 6 is not 0. The loop is guaranteed to execute at least once.


generates a random 32-bit number using the system's hardware random number generator, specifically utilizing the RDRAND feature supported by the processor. The code includes a loop to handle potential retrieval failures from RDRAND, indicated by the carry flag.