<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://www.sizecoding.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Qkumba</id>
		<title>SizeCoding - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://www.sizecoding.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Qkumba"/>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/wiki/Special:Contributions/Qkumba"/>
		<updated>2026-05-03T02:20:11Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.0</generator>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Case_Studies&amp;diff=845</id>
		<title>Case Studies</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Case_Studies&amp;diff=845"/>
				<updated>2021-03-13T17:58:57Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: fix broken link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sometimes it can be helpful to examine a tinyprog in detail, seeing what choices were made and why:&lt;br /&gt;
&lt;br /&gt;
:[[MELT.COM]]: We take a cute program from the 1980s and see how far we can crunch it down&lt;br /&gt;
&lt;br /&gt;
:[[m8trix 8b]]: An &amp;quot;Enter The Matrix&amp;quot; screen display in only 8 bytes&lt;br /&gt;
&lt;br /&gt;
:[[4is256]]: &amp;amp;#344;r&amp;amp;#345;ola's Tetris is a full tetris clone with scoring&lt;br /&gt;
&lt;br /&gt;
:[[paint16b]]: Hellmood's paint program in 16 bytes (really)&lt;br /&gt;
&lt;br /&gt;
:[[Indian Spirit]]: An American Indian tapestry with music in 32 bytes&lt;br /&gt;
&lt;br /&gt;
:[[Essence]]: Fakery of path tracing and lighting, with audio, in 64 bytes&lt;br /&gt;
&lt;br /&gt;
:[[Memories]]: Detailed writeup on [https://www.pouet.net/prod.php?which=85227 &amp;quot;Memories&amp;quot; (256 bytes)]&lt;br /&gt;
&lt;br /&gt;
:[[Game of Life 32b]]; Writeup for game of life in 32 bytes&lt;br /&gt;
&lt;br /&gt;
== External Case Studies ==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Brainfuck Brainfuck] is a very tiny language, having only 8 commands and an instruction pointer.  Several compilers and interpreters have been made; Gynvael archived [http://gynvael.coldwind.pl/bf125/ many different versions along with their source code], the smallest of which was 125 bytes.  qkumba took that as inspiration and created his own [http://pferrie.epizy.com/misc/tiny/brainfck.htm brainfuck compiler in 100 bytes] (104 for one that is fully compliant).  (Note:  The term &amp;quot;compiler&amp;quot; is used mistakenly a lot in these descriptions; the majority of brainfuck programs are actually interpreters that load brainfuck programs and execute native code token by token.  This one is an exception in that it really does compile the code entirely into native instructions first.)&lt;br /&gt;
&lt;br /&gt;
[https://revival-studios.com/marquee/blog/blog_homogenic.html Small Beginnings: The development of Homogenic] Development Write up on [https://www.pouet.net/prod.php?which=84537 Homogenic, by: Marquee Design (256 bytes)]&lt;br /&gt;
&lt;br /&gt;
[https://revival-studios.com/marquee/blog/blog_nanorail.html Moving on: The development of Nanorail] Development Write up on [https://www.pouet.net/prod.php?which=84624 Nanorail, by: Marquee Design (256 bytes)]&lt;br /&gt;
&lt;br /&gt;
[https://revival-studios.com/marquee/blog/blog_enigma.html Full Circle: The development of Enigma] Development Write up on [https://www.pouet.net/prod.php?which=85232 Enigma, by: Marquee Design (256 bytes)]&lt;br /&gt;
&lt;br /&gt;
[https://revival-studios.com/marquee/blog/blog_microdose.html Crunching content: The development of Microdose] Development Write up on [https://www.pouet.net/prod.php?which=85677 Microdose, by: Marquee Design (128 bytes)]&lt;br /&gt;
&lt;br /&gt;
[https://abaddon.hu/crevenge/history.html The long journey to 1k real-time ray-tracing] Detailed technical writeup on [https://www.pouet.net/prod.php?which=87078 Chrome Revenge by Abaddon (1024 bytes)]&lt;br /&gt;
&lt;br /&gt;
[http://canonical.org/~kragen/demo/fr-016.html Disassembly of Farbrausch's &amp;quot;fr-016: bytes&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
[http://canonical.org/~kragen/demo/klappquadrat.html A disassembly of the 64-byte version of Klappquadrat]&lt;br /&gt;
&lt;br /&gt;
[https://trixter.oldskool.org/2012/12/17/maze-generation-in-thirteen-bytes/ Maze generation in 10 bytes]&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=MELT.COM&amp;diff=223</id>
		<title>MELT.COM</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=MELT.COM&amp;diff=223"/>
				<updated>2016-08-15T04:37:17Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
MELT.COM was written by an unknown author in the 1980s.  Originally 49 bytes in size, it performs the following cute effect:&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|https://www.youtube.com/watch?v=MoGKh5X3nS4}}&lt;br /&gt;
&lt;br /&gt;
(The video is simulated and shows how MELT performs on the old hardware it was written for.)  This effect is achieved by increasing or decreasing each onscreen character's value until it reaches #32, the space character.  The original source is lost to history, but here's a quick commented disassembly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
                org 100h&lt;br /&gt;
&lt;br /&gt;
                mov     ax, 0B800h&lt;br /&gt;
                mov     es, ax          ; es now points to screen segment&lt;br /&gt;
&lt;br /&gt;
doScreen:                               &lt;br /&gt;
                mov     cx, 2000        ; Going to loop over all (80*25=)2000 characters&lt;br /&gt;
                xor     bx, bx          ; bx = 0.  Also our &amp;quot;num of altered chars&amp;quot; counter&lt;br /&gt;
                mov     di, bx          ; es:di now points at the screen (b800:0000)&lt;br /&gt;
&lt;br /&gt;
alterChars:                             &lt;br /&gt;
                mov     ah, es:[di]     ; Retreive onscreen character&lt;br /&gt;
                cmp     ah, 32          ; comp to a space character (#32)&lt;br /&gt;
                jz      short nextChar  ; If already a space, do nothing&lt;br /&gt;
                jl      short upToSpace ; If lower than a space, increase upward&lt;br /&gt;
                dec     ah              ; If higher than a space, decrease downward&lt;br /&gt;
                mov     es:[di], ah     ; Store altered character back to screen&lt;br /&gt;
                inc     bx              ; increase &amp;quot;number of processed chars&amp;quot; counter&lt;br /&gt;
                jmp     short nextChar  ; Keep processing characters&lt;br /&gt;
&lt;br /&gt;
upToSpace:                              &lt;br /&gt;
                inc     ah              ; Increase character upwards towards a space&lt;br /&gt;
                mov     es:[di], ah     ; Store altered character back to screen&lt;br /&gt;
                inc     bx              ; increase &amp;quot;number of processed chars&amp;quot; counter&lt;br /&gt;
&lt;br /&gt;
nextChar:                               &lt;br /&gt;
                inc     di&lt;br /&gt;
                inc     di              ; es:di now points to next character&lt;br /&gt;
                loop    alterChars      ; Continue processing characters&lt;br /&gt;
                cmp     bx, 0           ; Were any characters processed?&lt;br /&gt;
                jnz     short doScreen  ; If so (bx != 0), keep processing&lt;br /&gt;
                mov     ah, 4Ch         ; Otherwise, get ready to terminate&lt;br /&gt;
                int     21h             ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are some very quick wins right off the bat:&lt;br /&gt;
&lt;br /&gt;
* AX is already 0, so set AX=B800 by setting AH=B8&lt;br /&gt;
* Replace DOS exit sequence with RET, since this is a .COM file&lt;br /&gt;
* The &amp;quot;CMP bx,0&amp;quot; can be replaced with a shorter test like &amp;quot;OR bx,bx&amp;quot;&lt;br /&gt;
* There is inefficient loading and saving of screen characters with manually advancing DI twice -- 80x86 has 1-byte string instructions to do that, so we'll use LODSW and STOSW.  This will load the character attribute byte redundantly, but we don't care about speed, we care about size.  Because we only use LODS once, we can shave a byte by getting rid of MOV DS,AX (3 bytes) and using ES: LODS (2 bytes) in the inner loop.&lt;br /&gt;
&lt;br /&gt;
This shaves 12 bytes down to 37 total.  At this point we can make some drastic changes that will shave bytes, but also make the program not behave ''exactly'' as it did before.  I chose to do the following:&lt;br /&gt;
&lt;br /&gt;
* 2000 is 7D0 in hex.  Change MOV CX,2000 (decimal) to MOV CH,08 (hex) to shave a byte.  This could result in CX being anywhere in the range 0800 to 08FF but the difference is minimal at execution time.  It's also larger than the original area, but that is fine since there is there is extra screen RAM after the visible portion of the screen.&lt;br /&gt;
* The code contains a check for characters below #32 (space) and moves them upward.  Most characters onscreen are going to be above #32, so this isn't really necessary and I removed the check.  Even if it were necessary, removing the check will just rotate them downward until they wrap around to 255, then go downward again until hitting #32 and stopping.&lt;br /&gt;
&lt;br /&gt;
This gets the code down to 29 bytes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
                org 100h&lt;br /&gt;
&lt;br /&gt;
                mov     ah, 0B8h&lt;br /&gt;
                mov     es, ax          ; es so we can use es: LODS and STOS to the same place&lt;br /&gt;
&lt;br /&gt;
doScreen:&lt;br /&gt;
                mov     ch, 08          ; (80 * 25 = 2000/07d0h)&lt;br /&gt;
                xor     bx, bx          ; bx is also our &amp;quot;num of altered chars&amp;quot; counter&lt;br /&gt;
                mov     di, bx          ; es:di now points at the screen (b800:0000)&lt;br /&gt;
                mov     si, di          ; ds:si = es:di, needed for lods/stos&lt;br /&gt;
&lt;br /&gt;
alterChars:&lt;br /&gt;
                es: lodsw               ; Retreive onscreen character&lt;br /&gt;
                cmp     al, 32          ; comp to a space character (#32)&lt;br /&gt;
                jz      short nextChar  ; If already a space, do nothing&lt;br /&gt;
                dec     al              ; If higher than a space, decrease downward&lt;br /&gt;
                inc     bx              ; increase &amp;quot;number of processed chars&amp;quot; counter&lt;br /&gt;
&lt;br /&gt;
nextChar:&lt;br /&gt;
                stosw&lt;br /&gt;
                loop    alterChars      ; Continue processing characters&lt;br /&gt;
                or      bx,bx           ; Were any characters processed?&lt;br /&gt;
                jnz     short doScreen  ; If so (bx != 0), keep processing&lt;br /&gt;
                ret                     ; exit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optimizing the above is left as an exercise to the reader.  It may be possible to shrink it further using instructions for the 80186 and later processors, but it runs way too quickly on those systems, so if doing so you may want to insert a HLT to pace the animation at 18.2 Hz.  It may also be possible to shrink it by taking advantage of the fact that ASCII character #0 is a null and shows nothing onscreen (just like the #32 space character), so instead of decrementing down to #32, you could decrement down to #0 in a more optimized form (like using the zero flag).&lt;br /&gt;
&lt;br /&gt;
== Or you could rethink it completely ==&lt;br /&gt;
&lt;br /&gt;
If you're willing to deviate from the original target environment (namely, that it was designed for a 4.77 MHz 8088), you can eliminate range checking for all sorts of optimizations.  &lt;br /&gt;
Instead of using two pointers/segments, it's possible to use only one, and directly operate on the chars on screen. Combined with optimized segment assignment and exclusion of the &amp;quot;processed chars&amp;quot;-count (fixed amount of iterations, set to the maximum possible 65536 * 255) this results in a 17 byte variation :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
			lds		bx,[si]			; load DS from our code &amp;quot;scasw&amp;quot; + &amp;quot;nop&amp;quot; = 0AF90h&lt;br /&gt;
			nop						; for alignment, maybe optimization potential here ;)&lt;br /&gt;
doChar:&lt;br /&gt;
			scasw					; used to advance DI by 2, and as DS high byte (0AFh)&lt;br /&gt;
			cmp 	byte [di],32	; is the current char on screen a &amp;quot;space&amp;quot;?&lt;br /&gt;
			jz		short skip 		; yes, don't decrement&lt;br /&gt;
			dec 	byte [di]		; nope, decrement&lt;br /&gt;
skip:&lt;br /&gt;
			dec 	dx				; first loop, besides the first time &lt;br /&gt;
			jnz 	doChar			; it's 65536 iterations&lt;br /&gt;
			loop 	doChar			; second loop, 255 times&lt;br /&gt;
			ret						; quit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above performs the same function as the previous optimization, but runs much more slowly as it traverses more RAM areas than necessary.&lt;br /&gt;
&lt;br /&gt;
There might be a way of altering the &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; to something useful.&lt;br /&gt;
&lt;br /&gt;
Returning to the non-printing null char, we can shave one more byte, to produce this 16 bytes version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
			lds		bx,[si]			; load DS from our code &amp;quot;scasw&amp;quot; + &amp;quot;nop&amp;quot; = 0AF90h&lt;br /&gt;
			nop						; for alignment, maybe optimization potential here ;)&lt;br /&gt;
doChar:&lt;br /&gt;
			scasw					; used to advance DI by 2, and as DS high byte (0AFh)&lt;br /&gt;
			cmp 	byte [di],al	; is the current char on screen a &amp;quot;null&amp;quot;?&lt;br /&gt;
			jz		short skip 		; yes, don't decrement&lt;br /&gt;
			dec 	byte [di]		; nope, decrement&lt;br /&gt;
skip:&lt;br /&gt;
			dec 	dx				; first loop, besides the first time &lt;br /&gt;
			jnz 	doChar			; it's 65536 iterations&lt;br /&gt;
			loop 	doChar			; second loop, 255 times&lt;br /&gt;
			ret						; quit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above performs a similar function as the previous optimization, but runs even more slowly as it requires regular characters to be decremented further than before.&lt;br /&gt;
&lt;br /&gt;
Note the &amp;lt;CODE&amp;gt;CMP/JZ/DEC&amp;lt;/CODE&amp;gt; sequence.  If we can control the carry flag as a result of the comparison, then we can perform a conditional decrement without the branch, via an &amp;lt;CODE&amp;gt;ADC&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Of course, if the AL register is zero, then there can never be a carry as a result of the comparison, but if we increase AL to 1, then every value other than zero will clear the carry.&lt;br /&gt;
&lt;br /&gt;
To increase the AX register would normally cost us one byte, but we happen to have one to spare in the &amp;lt;CODE&amp;gt;LDS&amp;lt;/CODE&amp;gt; alignment.&lt;br /&gt;
&lt;br /&gt;
That allows us to shave one more byte, to produce this 15 bytes version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
			lds		bx,[si]			; load DS from our code &amp;quot;scasw&amp;quot; + &amp;quot;inc&amp;quot; = 0AF40h&lt;br /&gt;
			inc		ax				; set AL to 1, also for alignment&lt;br /&gt;
doChar:&lt;br /&gt;
			scasw					; used to advance DI by 2, and as DS high byte (0AFh)&lt;br /&gt;
			cmp 	byte [di],al	; is the current char on screen a &amp;quot;null&amp;quot;?&lt;br /&gt;
			adc 	byte [di],ff		; if not, then decrement&lt;br /&gt;
			dec 	dx				; first loop, besides the first time &lt;br /&gt;
			jnz 	doChar			; it's 65536 iterations&lt;br /&gt;
			loop 	doChar			; second loop, 255 times&lt;br /&gt;
			ret						; quit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=MELT.COM&amp;diff=222</id>
		<title>MELT.COM</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=MELT.COM&amp;diff=222"/>
				<updated>2016-08-15T04:33:13Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: 15 bytes MELT&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
MELT.COM was written by an unknown author in the 1980s.  Originally 49 bytes in size, it performs the following cute effect:&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|https://www.youtube.com/watch?v=MoGKh5X3nS4}}&lt;br /&gt;
&lt;br /&gt;
(The video is simulated and shows how MELT performs on the old hardware it was written for.)  This effect is achieved by increasing or decreasing each onscreen character's value until it reaches #32, the space character.  The original source is lost to history, but here's a quick commented disassembly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
                org 100h&lt;br /&gt;
&lt;br /&gt;
                mov     ax, 0B800h&lt;br /&gt;
                mov     es, ax          ; es now points to screen segment&lt;br /&gt;
&lt;br /&gt;
doScreen:                               &lt;br /&gt;
                mov     cx, 2000        ; Going to loop over all (80*25=)2000 characters&lt;br /&gt;
                xor     bx, bx          ; bx = 0.  Also our &amp;quot;num of altered chars&amp;quot; counter&lt;br /&gt;
                mov     di, bx          ; es:di now points at the screen (b800:0000)&lt;br /&gt;
&lt;br /&gt;
alterChars:                             &lt;br /&gt;
                mov     ah, es:[di]     ; Retreive onscreen character&lt;br /&gt;
                cmp     ah, 32          ; comp to a space character (#32)&lt;br /&gt;
                jz      short nextChar  ; If already a space, do nothing&lt;br /&gt;
                jl      short upToSpace ; If lower than a space, increase upward&lt;br /&gt;
                dec     ah              ; If higher than a space, decrease downward&lt;br /&gt;
                mov     es:[di], ah     ; Store altered character back to screen&lt;br /&gt;
                inc     bx              ; increase &amp;quot;number of processed chars&amp;quot; counter&lt;br /&gt;
                jmp     short nextChar  ; Keep processing characters&lt;br /&gt;
&lt;br /&gt;
upToSpace:                              &lt;br /&gt;
                inc     ah              ; Increase character upwards towards a space&lt;br /&gt;
                mov     es:[di], ah     ; Store altered character back to screen&lt;br /&gt;
                inc     bx              ; increase &amp;quot;number of processed chars&amp;quot; counter&lt;br /&gt;
&lt;br /&gt;
nextChar:                               &lt;br /&gt;
                inc     di&lt;br /&gt;
                inc     di              ; es:di now points to next character&lt;br /&gt;
                loop    alterChars      ; Continue processing characters&lt;br /&gt;
                cmp     bx, 0           ; Were any characters processed?&lt;br /&gt;
                jnz     short doScreen  ; If so (bx != 0), keep processing&lt;br /&gt;
                mov     ah, 4Ch         ; Otherwise, get ready to terminate&lt;br /&gt;
                int     21h             ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are some very quick wins right off the bat:&lt;br /&gt;
&lt;br /&gt;
* AX is already 0, so set AX=B800 by setting AH=B8&lt;br /&gt;
* Replace DOS exit sequence with RET, since this is a .COM file&lt;br /&gt;
* The &amp;quot;CMP bx,0&amp;quot; can be replaced with a shorter test like &amp;quot;OR bx,bx&amp;quot;&lt;br /&gt;
* There is inefficient loading and saving of screen characters with manually advancing DI twice -- 80x86 has 1-byte string instructions to do that, so we'll use LODSW and STOSW.  This will load the character attribute byte redundantly, but we don't care about speed, we care about size.  Because we only use LODS once, we can shave a byte by getting rid of MOV DS,AX (3 bytes) and using ES: LODS (2 bytes) in the inner loop.&lt;br /&gt;
&lt;br /&gt;
This shaves 12 bytes down to 37 total.  At this point we can make some drastic changes that will shave bytes, but also make the program not behave ''exactly'' as it did before.  I chose to do the following:&lt;br /&gt;
&lt;br /&gt;
* 2000 is 7D0 in hex.  Change MOV CX,2000 (decimal) to MOV CH,08 (hex) to shave a byte.  This could result in CX being anywhere in the range 0800 to 08FF but the difference is minimal at execution time.  It's also larger than the original area, but that is fine since there is there is extra screen RAM after the visible portion of the screen.&lt;br /&gt;
* The code contains a check for characters below #32 (space) and moves them upward.  Most characters onscreen are going to be above #32, so this isn't really necessary and I removed the check.  Even if it were necessary, removing the check will just rotate them downward until they wrap around to 255, then go downward again until hitting #32 and stopping.&lt;br /&gt;
&lt;br /&gt;
This gets the code down to 29 bytes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
                org 100h&lt;br /&gt;
&lt;br /&gt;
                mov     ah, 0B8h&lt;br /&gt;
                mov     es, ax          ; es so we can use es: LODS and STOS to the same place&lt;br /&gt;
&lt;br /&gt;
doScreen:&lt;br /&gt;
                mov     ch, 08          ; (80 * 25 = 2000/07d0h)&lt;br /&gt;
                xor     bx, bx          ; bx is also our &amp;quot;num of altered chars&amp;quot; counter&lt;br /&gt;
                mov     di, bx          ; es:di now points at the screen (b800:0000)&lt;br /&gt;
                mov     si, di          ; ds:si = es:di, needed for lods/stos&lt;br /&gt;
&lt;br /&gt;
alterChars:&lt;br /&gt;
                es: lodsw               ; Retreive onscreen character&lt;br /&gt;
                cmp     al, 32          ; comp to a space character (#32)&lt;br /&gt;
                jz      short nextChar  ; If already a space, do nothing&lt;br /&gt;
                dec     al              ; If higher than a space, decrease downward&lt;br /&gt;
                inc     bx              ; increase &amp;quot;number of processed chars&amp;quot; counter&lt;br /&gt;
&lt;br /&gt;
nextChar:&lt;br /&gt;
                stosw&lt;br /&gt;
                loop    alterChars      ; Continue processing characters&lt;br /&gt;
                or      bx,bx           ; Were any characters processed?&lt;br /&gt;
                jnz     short doScreen  ; If so (bx != 0), keep processing&lt;br /&gt;
                ret                     ; exit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optimizing the above is left as an exercise to the reader.  It may be possible to shrink it further using instructions for the 80186 and later processors, but it runs way too quickly on those systems, so if doing so you may want to insert a HLT to pace the animation at 18.2 Hz.  It may also be possible to shrink it by taking advantage of the fact that ASCII character #0 is a null and shows nothing onscreen (just like the #32 space character), so instead of decrementing down to #32, you could decrement down to #0 in a more optimized form (like using the zero flag).&lt;br /&gt;
&lt;br /&gt;
== Or you could rethink it completely ==&lt;br /&gt;
&lt;br /&gt;
If you're willing to deviate from the original target environment (namely, that it was designed for a 4.77 MHz 8088), you can eliminate range checking for all sorts of optimizations.  &lt;br /&gt;
Instead of using two pointers/segments, it's possible to use only one, and directly operate on the chars on screen. Combined with optimized segment assignment and exclusion of the &amp;quot;processed chars&amp;quot;-count (fixed amount of iterations, set to the maximum possible 65536 * 255) this results in a 17 byte variation :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
			lds		bx,[si]			; load DS from our code &amp;quot;scasw&amp;quot; + &amp;quot;nop&amp;quot; = 0AF90h&lt;br /&gt;
			nop						; for alignment, maybe optimization potential here ;)&lt;br /&gt;
doChar:&lt;br /&gt;
			scasw					; used to advance DI by 2, and as DS high byte (0AFh)&lt;br /&gt;
			cmp 	byte [di],32	; is the current char on screen a &amp;quot;space&amp;quot;?&lt;br /&gt;
			jz		short skip 		; yes, don't decrement&lt;br /&gt;
			dec 	byte [di]		; nope, decrement&lt;br /&gt;
skip:&lt;br /&gt;
			dec 	dx				; first loop, besides the first time &lt;br /&gt;
			jnz 	doChar			; it's 65536 iterations&lt;br /&gt;
			loop 	doChar			; second loop, 255 times&lt;br /&gt;
			ret						; quit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above performs the same function as the previous optimization, but runs much more slowly as it traverses more RAM areas than necessary.&lt;br /&gt;
&lt;br /&gt;
There might be a way of altering the &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; to something useful.&lt;br /&gt;
&lt;br /&gt;
Returning to the non-printing null char, we can shave one more byte, to produce this 16 bytes version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
			lds		bx,[si]			; load DS from our code &amp;quot;scasw&amp;quot; + &amp;quot;nop&amp;quot; = 0AF90h&lt;br /&gt;
			nop						; for alignment, maybe optimization potential here ;)&lt;br /&gt;
doChar:&lt;br /&gt;
			scasw					; used to advance DI by 2, and as DS high byte (0AFh)&lt;br /&gt;
			cmp 	byte [di],al	; is the current char on screen a &amp;quot;null&amp;quot;?&lt;br /&gt;
			jz		short skip 		; yes, don't decrement&lt;br /&gt;
			dec 	byte [di]		; nope, decrement&lt;br /&gt;
skip:&lt;br /&gt;
			dec 	dx				; first loop, besides the first time &lt;br /&gt;
			jnz 	doChar			; it's 65536 iterations&lt;br /&gt;
			loop 	doChar			; second loop, 255 times&lt;br /&gt;
			ret						; quit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above performs a similar function as the previous optimization, but runs even more slowly as it requires regular characters to be decremented further than before.&lt;br /&gt;
&lt;br /&gt;
Note the &amp;lt;CODE&amp;gt;CMP/JZ/DEC&amp;lt;/CODE&amp;gt; sequence.  If we can set the carry flag as a result of the comparison, then we can perform a conditional decrement without the branch, via an &amp;lt;CODE&amp;gt;ADC&amp;lt;/CODE&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Of course, if the AL register is zero, then there can never be a carry as a result of the comparison, but if we increase AL to 1, then every value other than zero will set the carry.&lt;br /&gt;
&lt;br /&gt;
To increase the AX register would normally cost us one byte, but we happen to have one to spare in the &amp;lt;CODE&amp;gt;LDS&amp;lt;/CODE&amp;gt; alignment.&lt;br /&gt;
&lt;br /&gt;
That allows us to shave one more byte, to produce this 15 bytes version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
			lds		bx,[si]			; load DS from our code &amp;quot;scasw&amp;quot; + &amp;quot;inc&amp;quot; = 0AFh&lt;br /&gt;
			inc		ax				; for alignment&lt;br /&gt;
doChar:&lt;br /&gt;
			scasw					; used to advance DI by 2, and as DS high byte (0AFh)&lt;br /&gt;
			cmp 	byte [di],al	; is the current char on screen a &amp;quot;null&amp;quot;?&lt;br /&gt;
			adc 	byte [di],ff		; if not, then decrement&lt;br /&gt;
			dec 	dx				; first loop, besides the first time &lt;br /&gt;
			jnz 	doChar			; it's 65536 iterations&lt;br /&gt;
			loop 	doChar			; second loop, 255 times&lt;br /&gt;
			ret						; quit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Resources&amp;diff=214</id>
		<title>Resources</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Resources&amp;diff=214"/>
				<updated>2016-08-14T22:54:48Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Discussions ==&lt;br /&gt;
&lt;br /&gt;
Pouet's [http://www.pouet.net/topic.php?which=8791&amp;amp;page=1 Tiny Intro Toolbox Thread] was one of sizecoding.org's main inspirations.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
The Hugi demoscene diskmag has been kind to the sizecoding movement.  They included [http://www.hugi.scene.org/online/coding/hugi%20se%204%20-%20index%20sorted%20by%20topic.htm many programming articles] since it started in 1996.  Additionally, the [http://www.hugi.scene.org/compo/compoold.htm Hugi Size Coding Competition Series] is the gold standard for learning how to sizecode:  Each competition was given a specific task, then participants submitted their results.  ([http://retrolandia.net/hugi/showthread.php?tid=7&amp;amp;pid=13#pid13 All of the entries with their source code] are available, as are [http://retrolandia.net/hugi/showthread.php?tid=7&amp;amp;pid=396#pid396 the rules for each challenge].)  Hugi #35 also provided a [http://hugi.scene.org/online/hugi35/hugi%2035%20-%20demoscene%20forum%20adok%20256b%20intros%20round-table.htm 256b intros round-table] between Baze, Digimind, &amp;amp;#344;r&amp;amp;#345;ola, Pirx, Optimus, and Seven.&lt;br /&gt;
&lt;br /&gt;
fysnet.net has an extensive [http://www.fysnet.net/yourhelp.htm list of DOS .COM register starting values].  If your environment isn't listed, [http://www.fysnet.net/yourhelp.com a program] is also available that can print out all of the register starting values.  See also [http://pferrie.host22.com/misc/lowlevel12.htm DOS Register Starting Values] to understand why the register starting values for .COM files are set the way that they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The [http://sparksandflames.com/files/x86InstructionChart.html Sparks And Flames x86 Instruction Chart] is awesome, once you can &amp;quot;read&amp;quot; it. Find out what the bright green (1-byte) commands do, and use them. For the extreme sizecoding (&amp;lt;=32 bytes) it's also very useful to have the HEX value in sight.&lt;br /&gt;
&lt;br /&gt;
The [http://ref.x86asm.net/geek.html Geek Edition x86asm-ref] is comprehensive and dense.  It might be the only reference you'll need.  The last part covers modr/m bytes, which is useful.&lt;br /&gt;
&lt;br /&gt;
[http://x86.renejeschke.de/ Rene Jeschke's preservation of siyobik.com's x86 Documentation] is one of the most compact and understandable references to the x86 instruction set you'll ever see.&lt;br /&gt;
&lt;br /&gt;
[http://www.rcollins.org/secrets/OpCodes.html Robert Collins' Undocumented Opcodes] page has some gems you can exploit depending on your target environment.&lt;br /&gt;
&lt;br /&gt;
[http://wiki.osdev.org/PC_Speaker PC Speaker Basics] For everything from simple bleeps to sophisticated synthesizers.&lt;br /&gt;
&lt;br /&gt;
[https://de.wikipedia.org/wiki/Program_Segment_Prefix Program Segment Prefix] : whats in front of our code, and why.&lt;br /&gt;
&lt;br /&gt;
Never underestimate [http://www.hugi.scene.org/online/coding/hugi%2017%20-%20coaax.htm The Hidden Power of BCD Instructions].&lt;br /&gt;
&lt;br /&gt;
[http://wiki.osdev.org/Programmable_Interval_Timer Programmable Interval Timer] : timing is everything.&lt;br /&gt;
&lt;br /&gt;
[http://stanislavs.org/helppc/bios_data_area.html BIOS data area] : direct system communication overview&lt;br /&gt;
&lt;br /&gt;
[https://www.midi.org/specifications/item/table-1-summary-of-midi-message Summary of MIDI messages] : Summary of MIDI messages&lt;br /&gt;
&lt;br /&gt;
== Repositories ==&lt;br /&gt;
&lt;br /&gt;
Tinyprogs are so small that you sometimes don't need the source code to understand them:  Just pop them into a disassembler (like IDA) or a debugger and look at them.  If you want to grab specimens for study, here are some places to start.&lt;br /&gt;
&lt;br /&gt;
Pouet can be searched for the latest tinyprogs:  [http://www.pouet.net/prodlist.php?type%5B%5D=256b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 256b], [http://www.pouet.net/prodlist.php?type%5B%5D=128b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 128b], [http://www.pouet.net/prodlist.php?type%5B%5D=64b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 64b], and even [http://www.pouet.net/prodlist.php?type%5B%5D=32b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 32b and smaller].&lt;br /&gt;
&lt;br /&gt;
[http://hardcode.untergrund.net/ HardCode] is a repository of 7800 64KB and smaller intros.&lt;br /&gt;
&lt;br /&gt;
[http://256bytes.untergrund.net 256b.com] is a website dedicated primarily to 256b and smaller releases.&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=General_Coding_Tricks&amp;diff=213</id>
		<title>General Coding Tricks</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=General_Coding_Tricks&amp;diff=213"/>
				<updated>2016-08-14T22:47:09Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Data is code, code is data ==&lt;br /&gt;
&lt;br /&gt;
Code is nothing more than data that the CPU interprets.  For example, consider this multi-byte instruction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
        mov ah,37h&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This assembles to &amp;lt;code&amp;gt;B4 37&amp;lt;/code&amp;gt;.  &amp;lt;code&amp;gt;B4&amp;lt;/code&amp;gt; by itself isn't interesting, but &amp;lt;code&amp;gt;37&amp;lt;/code&amp;gt; happens to be the opcode for &amp;lt;code&amp;gt;AAS&amp;lt;/code&amp;gt;.  Let's say you had this code before a loop, and you needed to perform &amp;lt;code&amp;gt;AAS&amp;lt;/code&amp;gt; at the top of a loop.  Rather than put AAS at the top of the loop, you can reuse the opcode that will already be there as part of the &amp;lt;code&amp;gt;mov ah,37&amp;lt;/code&amp;gt; that comes before it.  Just jump directly into the middle of the &amp;lt;code&amp;gt;mov ah,37h&amp;lt;/code&amp;gt;, which will get interpreted and executed as &amp;lt;code&amp;gt;AAS&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
label:&lt;br /&gt;
        mov ah,37h&lt;br /&gt;
        ;misc. stuff&lt;br /&gt;
        loop label+1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;+1&amp;lt;/code&amp;gt; specifies the jump should go to 1 byte past the actual location.&lt;br /&gt;
&lt;br /&gt;
=== Reuse ===&lt;br /&gt;
&lt;br /&gt;
You can use opcodes hidden in your existing data.  For example, .COM files can end with &amp;lt;code&amp;gt;RET&amp;lt;/code&amp;gt;, which is opcode &amp;lt;code&amp;gt;C3&amp;lt;/code&amp;gt;.  If you already have a &amp;lt;code&amp;gt;C3&amp;lt;/code&amp;gt; somewhere else in your code, even as part of data, just &amp;lt;code&amp;gt;JMP&amp;lt;/code&amp;gt; to that pre-existing &amp;lt;code&amp;gt;C3&amp;lt;/code&amp;gt; instead of adding a &amp;lt;code&amp;gt;RET&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== If your environment holds you back, change it ==&lt;br /&gt;
&lt;br /&gt;
The [https://en.wikipedia.org/wiki/Video_Graphics_Array#/media/File:VGA_palette_with_black_borders.svg default MCGA palette] is fairly horrible, but can be size advantages to changing it:  While setting a new palette costs bytes, the new palette arrangement could save you headaches down the road.  For example, if your code is calculating pixel colors that fall into goofy ranges, rather than constantly adjust the colors to sane ranges (ie. aligned to powers of 2), just set the palette so that values falling into those ranges look the way you want.  (This assumes you have very small ways of redefining the palette, of course.)&lt;br /&gt;
&lt;br /&gt;
The above is maybe not the best example.  Rewrites to this section are welcome.&lt;br /&gt;
&lt;br /&gt;
== Need a constant? ==&lt;br /&gt;
&lt;br /&gt;
If you need a constant value but you're out of space, search your assembled code for a byte value you can use.&lt;br /&gt;
&lt;br /&gt;
== A smaller way to point to Mode 13's screen segment ==&lt;br /&gt;
&lt;br /&gt;
Rather than &amp;lt;code&amp;gt;mov ah,0a0h; mov es,ax&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;push word 0a000h; pop es&amp;lt;/code&amp;gt;, try this 2-byte wonder:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
les bp,[bx]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets ES=9FFF, only one away from A000.  You can write to the screen with ES: this way as long as you are aware the segment is one paragraph (16 bytes) behind, so just increase your offset by 16 if you need exact placement.&lt;br /&gt;
&lt;br /&gt;
How does this work?   At start of execution of a .COM file, BX=0, and DS=CS. The contents of the COM file get loaded to offset 0x100 in that segment, but loaded before that is the PSP (program segment prefix), which DOS populates with information about the loaded program and other info. The PSP starts with &amp;lt;code&amp;gt;CD 20&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;INT 20&amp;lt;/code&amp;gt;, which exits the program), so that's what gets loaded into BP.  The next word is the number of the last free conventional memory segment, typically 0x9fff (but can be something different if parts of the upper memory range are either not installed or allocated).&lt;br /&gt;
&lt;br /&gt;
'''Warning:''' This trick doesn't always work.  On FreeDos, this can set ES=9FE0 and there is something resident at that location that can screw up the system after normal program exit if you overwrite it.&lt;br /&gt;
&lt;br /&gt;
== Accessing the timer tick for free ==&lt;br /&gt;
&lt;br /&gt;
If using a 386+, FS=0 at .COM start.  So, &amp;lt;code&amp;gt;FS:[046C]&amp;lt;/code&amp;gt; gets you the DOS timer tick variable, which you could use for timing/pacing, or a random seed. Some environments, especially EMS/XMS programs, can modify the FS register, so it can't always assumed to be 0000h. &amp;lt;code&amp;gt;POP DS&amp;lt;/code&amp;gt; right after the start and accessing &amp;lt;code&amp;gt;[046C]&amp;lt;/code&amp;gt; does the trick then with equal size.&lt;br /&gt;
&lt;br /&gt;
== Looping twice ==&lt;br /&gt;
&lt;br /&gt;
If you need to repeat a section of code that doesn't modify the carry flag, and you know the carry flag is clear, you can loop once in only 3 bytes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
looping:&lt;br /&gt;
        ;do stuff here&lt;br /&gt;
        cmc&lt;br /&gt;
        jc      looping&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Looping three times ==&lt;br /&gt;
&lt;br /&gt;
If you need to repeat a section of code and you have a register whose value is zero and can be incremented freely, or whose value is -1 and can be decremented freely, you can loop twice in only 3 bytes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
looping:&lt;br /&gt;
        ;do stuff here&lt;br /&gt;
        inc     bx ;if decrementing instead, parity check must be reversed&lt;br /&gt;
        jpo     looping ;1 (01b) and 2 (10b) have odd parity, 3 (11b) has even parity&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=General_Coding_Tricks&amp;diff=212</id>
		<title>General Coding Tricks</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=General_Coding_Tricks&amp;diff=212"/>
				<updated>2016-08-14T22:46:17Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: looping three times&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Data is code, code is data ==&lt;br /&gt;
&lt;br /&gt;
Code is nothing more than data that the CPU interprets.  For example, consider this multi-byte instruction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
        mov ah,37h&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This assembles to &amp;lt;code&amp;gt;B4 37&amp;lt;/code&amp;gt;.  &amp;lt;code&amp;gt;B4&amp;lt;/code&amp;gt; by itself isn't interesting, but &amp;lt;code&amp;gt;37&amp;lt;/code&amp;gt; happens to be the opcode for &amp;lt;code&amp;gt;AAS&amp;lt;/code&amp;gt;.  Let's say you had this code before a loop, and you needed to perform &amp;lt;code&amp;gt;AAS&amp;lt;/code&amp;gt; at the top of a loop.  Rather than put AAS at the top of the loop, you can reuse the opcode that will already be there as part of the &amp;lt;code&amp;gt;mov ah,37&amp;lt;/code&amp;gt; that comes before it.  Just jump directly into the middle of the &amp;lt;code&amp;gt;mov ah,37h&amp;lt;/code&amp;gt;, which will get interpreted and executed as &amp;lt;code&amp;gt;AAS&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
label:&lt;br /&gt;
        mov ah,37h&lt;br /&gt;
        ;misc. stuff&lt;br /&gt;
        loop label+1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;+1&amp;lt;/code&amp;gt; specifies the jump should go to 1 byte past the actual location.&lt;br /&gt;
&lt;br /&gt;
=== Reuse ===&lt;br /&gt;
&lt;br /&gt;
You can use opcodes hidden in your existing data.  For example, .COM files can end with &amp;lt;code&amp;gt;RET&amp;lt;/code&amp;gt;, which is opcode &amp;lt;code&amp;gt;C3&amp;lt;/code&amp;gt;.  If you already have a &amp;lt;code&amp;gt;C3&amp;lt;/code&amp;gt; somewhere else in your code, even as part of data, just &amp;lt;code&amp;gt;JMP&amp;lt;/code&amp;gt; to that pre-existing &amp;lt;code&amp;gt;C3&amp;lt;/code&amp;gt; instead of adding a &amp;lt;code&amp;gt;RET&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== If your environment holds you back, change it ==&lt;br /&gt;
&lt;br /&gt;
The [https://en.wikipedia.org/wiki/Video_Graphics_Array#/media/File:VGA_palette_with_black_borders.svg default MCGA palette] is fairly horrible, but can be size advantages to changing it:  While setting a new palette costs bytes, the new palette arrangement could save you headaches down the road.  For example, if your code is calculating pixel colors that fall into goofy ranges, rather than constantly adjust the colors to sane ranges (ie. aligned to powers of 2), just set the palette so that values falling into those ranges look the way you want.  (This assumes you have very small ways of redefining the palette, of course.)&lt;br /&gt;
&lt;br /&gt;
The above is maybe not the best example.  Rewrites to this section are welcome.&lt;br /&gt;
&lt;br /&gt;
== Need a constant? ==&lt;br /&gt;
&lt;br /&gt;
If you need a constant value but you're out of space, search your assembled code for a byte value you can use.&lt;br /&gt;
&lt;br /&gt;
== A smaller way to point to Mode 13's screen segment ==&lt;br /&gt;
&lt;br /&gt;
Rather than &amp;lt;code&amp;gt;mov ah,0a0h; mov es,ax&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;push word 0a000h; pop es&amp;lt;/code&amp;gt;, try this 2-byte wonder:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
les bp,[bx]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets ES=9FFF, only one away from A000.  You can write to the screen with ES: this way as long as you are aware the segment is one paragraph (16 bytes) behind, so just increase your offset by 16 if you need exact placement.&lt;br /&gt;
&lt;br /&gt;
How does this work?   At start of execution of a .COM file, BX=0, and DS=CS. The contents of the COM file get loaded to offset 0x100 in that segment, but loaded before that is the PSP (program segment prefix), which DOS populates with information about the loaded program and other info. The PSP starts with &amp;lt;code&amp;gt;CD 20&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;INT 20&amp;lt;/code&amp;gt;, which exits the program), so that's what gets loaded into BP.  The next word is the number of the last free conventional memory segment, typically 0x9fff (but can be something different if parts of the upper memory range are either not installed or allocated).&lt;br /&gt;
&lt;br /&gt;
'''Warning:''' This trick doesn't always work.  On FreeDos, this can set ES=9FE0 and there is something resident at that location that can screw up the system after normal program exit if you overwrite it.&lt;br /&gt;
&lt;br /&gt;
== Accessing the timer tick for free ==&lt;br /&gt;
&lt;br /&gt;
If using a 386+, FS=0 at .COM start.  So, &amp;lt;code&amp;gt;FS:[046C]&amp;lt;/code&amp;gt; gets you the DOS timer tick variable, which you could use for timing/pacing, or a random seed. Some environments, especially EMS/XMS programs, can modify the FS register, so it can't always assumed to be 0000h. &amp;lt;code&amp;gt;POP DS&amp;lt;/code&amp;gt; right after the start and accessing &amp;lt;code&amp;gt;[046C]&amp;lt;/code&amp;gt; does the trick then with equal size.&lt;br /&gt;
&lt;br /&gt;
== Looping twice ==&lt;br /&gt;
&lt;br /&gt;
If you need to repeat a section of code that doesn't modify the carry flag, and you know the carry flag is clear, you can loop once in only 3 bytes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
looping:&lt;br /&gt;
        ;do stuff here&lt;br /&gt;
        cmc&lt;br /&gt;
        jc      looping&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Looping three times ==&lt;br /&gt;
&lt;br /&gt;
If you need to repeat a section of code and you have a register whose value is zero and can be incremented freeyl, or whose value is -1 and can be decremented freely, you can loop twice in only 3 bytes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
looping:&lt;br /&gt;
        ;do stuff here&lt;br /&gt;
        inc     bx ;if decrementing instead, parity check must be reversed&lt;br /&gt;
        jpo     looping ;1 (01b) and 2 (10b) have odd parity, 3 (11b) has even parity&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Case_Studies&amp;diff=211</id>
		<title>Case Studies</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Case_Studies&amp;diff=211"/>
				<updated>2016-08-14T22:31:34Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: display Řrřola's name properly&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sometimes it can be helpful to examine a tinyprog in detail, seeing what choices were made and why:&lt;br /&gt;
&lt;br /&gt;
:[[MELT.COM]]: We take a cute program from the 1980s and see how far we can crunch it down&lt;br /&gt;
&lt;br /&gt;
:[[m8trix 8b]]: An &amp;quot;Enter The Matrix&amp;quot; screen display in only 8 bytes&lt;br /&gt;
&lt;br /&gt;
:[[4is256]]: &amp;amp;#344;r&amp;amp;#345;ola's Tetris is a full tetris clone with scoring&lt;br /&gt;
&lt;br /&gt;
:[[paint16b]]: Hellmood's paint program in 16 bytes (really)&lt;br /&gt;
&lt;br /&gt;
== External Case Studies ==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Brainfuck Brainfuck] is a very tiny language, having only 8 commands and an instruction pointer.  Several interpreters have been made; Gynvael archived [http://gynvael.coldwind.pl/bf125/ many different versions along with their source code], the smallest of which was 125 bytes.  qkumba took that as inspiration and created his own [http://pferrie.host22.com/misc/tiny/brainfck.htm brainfuck compiler in 100 bytes] (104 for one that is fully compliant).  (Note:  The term &amp;quot;compiler&amp;quot; is used mistakenly a lot in these descriptions; the majority of brainfuck programs are actually interpreters that load brainfuck programs and execute native code token by token.  This one is an exception in that it really does compile the code entirely into native instructions first).&lt;br /&gt;
&lt;br /&gt;
[http://canonical.org/~kragen/demo/fr-016.html Disassembly of Farbrausch's &amp;quot;fr-016: bytes&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
[http://canonical.org/~kragen/demo/klappquadrat.html A disassembly of the 64-byte version of Klappquadrat]&lt;br /&gt;
&lt;br /&gt;
[https://trixter.oldskool.org/2012/12/17/maze-generation-in-thirteen-bytes/ Maze generation in 10 bytes]&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Case_Studies&amp;diff=210</id>
		<title>Case Studies</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Case_Studies&amp;diff=210"/>
				<updated>2016-08-14T22:29:39Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: tiny compiler is really a compiler&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sometimes it can be helpful to examine a tinyprog in detail, seeing what choices were made and why:&lt;br /&gt;
&lt;br /&gt;
:[[MELT.COM]]: We take a cute program from the 1980s and see how far we can crunch it down&lt;br /&gt;
&lt;br /&gt;
:[[m8trix 8b]]: An &amp;quot;Enter The Matrix&amp;quot; screen display in only 8 bytes&lt;br /&gt;
&lt;br /&gt;
:[[4is256]]: rrrola's Tetris is a full tetris clone with scoring&lt;br /&gt;
&lt;br /&gt;
:[[paint16b]]: Hellmood's paint program in 16 bytes (really)&lt;br /&gt;
&lt;br /&gt;
== External Case Studies ==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Brainfuck Brainfuck] is a very tiny language, having only 8 commands and an instruction pointer.  Several interpreters have been made; Gynvael archived [http://gynvael.coldwind.pl/bf125/ many different versions along with their source code], the smallest of which was 125 bytes.  qkumba took that as inspiration and created his own [http://pferrie.host22.com/misc/tiny/brainfck.htm brainfuck compiler in 100 bytes] (104 for one that is fully compliant).  (Note:  The term &amp;quot;compiler&amp;quot; is used mistakenly a lot in these descriptions; the majority of brainfuck programs are actually interpreters that load brainfuck programs and execute native code token by token.  This one is an exception in that it really does compile the code entirely into native instructions first).&lt;br /&gt;
&lt;br /&gt;
[http://canonical.org/~kragen/demo/fr-016.html Disassembly of Farbrausch's &amp;quot;fr-016: bytes&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
[http://canonical.org/~kragen/demo/klappquadrat.html A disassembly of the 64-byte version of Klappquadrat]&lt;br /&gt;
&lt;br /&gt;
[https://trixter.oldskool.org/2012/12/17/maze-generation-in-thirteen-bytes/ Maze generation in 10 bytes]&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=MELT.COM&amp;diff=209</id>
		<title>MELT.COM</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=MELT.COM&amp;diff=209"/>
				<updated>2016-08-14T22:19:16Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Case Study]]&lt;br /&gt;
MELT.COM was written by an unknown author in the 1980s.  Originally 49 bytes in size, it performs the following cute effect:&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|https://www.youtube.com/watch?v=MoGKh5X3nS4}}&lt;br /&gt;
&lt;br /&gt;
(The video is simulated and shows how MELT performs on the old hardware it was written for.)  This effect is achieved by increasing or decreasing each onscreen character's value until it reaches #32, the space character.  The original source is lost to history, but here's a quick commented disassembly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
                org 100h&lt;br /&gt;
&lt;br /&gt;
                mov     ax, 0B800h&lt;br /&gt;
                mov     es, ax          ; es now points to screen segment&lt;br /&gt;
&lt;br /&gt;
doScreen:                               &lt;br /&gt;
                mov     cx, 2000        ; Going to loop over all 2000 characters&lt;br /&gt;
                                        ; (80 * 25 = 2000)&lt;br /&gt;
                xor     bx, bx          ; bx = 0&lt;br /&gt;
                                        ; bx is also our &amp;quot;num of altered chars&amp;quot; counter&lt;br /&gt;
                mov     di, bx          ; es:di now points at the screen (b800:0000)&lt;br /&gt;
&lt;br /&gt;
alterChars:                             &lt;br /&gt;
                mov     ah, es:[di]     ; Retreive onscreen character&lt;br /&gt;
                cmp     ah, 32          ; comp to a space character (#32)&lt;br /&gt;
                jz      short nextChar  ; If already a space, do nothing&lt;br /&gt;
                jl      short upToSpace ; If lower than a space, increase upward&lt;br /&gt;
                dec     ah              ; If higher than a space, decrease downward&lt;br /&gt;
                mov     es:[di], ah     ; Store altered character back to screen&lt;br /&gt;
                inc     bx              ; increase &amp;quot;number of processed chars&amp;quot; counter&lt;br /&gt;
                jmp     short nextChar  ; Keep processing characters&lt;br /&gt;
; ---------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
upToSpace:                              &lt;br /&gt;
                inc     ah              ; Increase character upwards towards a space&lt;br /&gt;
                mov     es:[di], ah     ; Store altered character back to screen&lt;br /&gt;
                inc     bx              ; increase &amp;quot;number of processed chars&amp;quot; counter&lt;br /&gt;
&lt;br /&gt;
nextChar:                               &lt;br /&gt;
                inc     di&lt;br /&gt;
                inc     di              ; es:di now points to next character&lt;br /&gt;
                loop    alterChars      ; Continue processing characters&lt;br /&gt;
                cmp     bx, 0           ; Were any characters processed?&lt;br /&gt;
                jnz     short doScreen  ; If so (bx != 0), keep processing&lt;br /&gt;
                mov     ah, 4Ch         ; Otherwise, get ready to terminate&lt;br /&gt;
                int     21h             ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are some very quick wins right off the bat:&lt;br /&gt;
&lt;br /&gt;
* AX is already 0, so set AX=B800 by setting AH=B8&lt;br /&gt;
* Replace DOS exit sequence with RET, since this is a .COM file&lt;br /&gt;
* The &amp;quot;CMP bx,0&amp;quot; can be replaced with a shorter test like &amp;quot;OR bx,bx&amp;quot;&lt;br /&gt;
* There is inefficient loading and saving of screen characters with manually advancing DI twice -- 80x86 has 1-byte string instructions to do that, so we'll use LODSW and STOSW.  This will load the character attribute byte redundantly, but we don't care about speed, we care about size.  Because we only use LODS once, we can shave a byte by getting rid of MOV DS,AX (3 bytes) and using ES: LODS (2 bytes) in the inner loop.&lt;br /&gt;
&lt;br /&gt;
This shaves 12 bytes down to 37 total.  At this point we can make some drastic changes that will shave bytes, but also make the program not behave ''exactly'' as it did before.  I chose to do the following:&lt;br /&gt;
&lt;br /&gt;
* 2000 is 7D0 in hex.  Change MOV CX,2000 (decimal) to MOV CH,08 (hex) to shave a byte.  This could result in CX being anywhere in the range 0800 to 08FF but the difference is minimal at execution time.  It's also larger than the original area, but that is fine since there is there is extra screen RAM after the visible portion of the screen.&lt;br /&gt;
* The code contains a check for characters below #32 (space) and moves them upward.  Most characters onscreen are going to be above #32, so this isn't really necessary and I removed the check.  Even if it were necessary, removing the check will just rotate them downward until they wrap around to 255, then go downward again until hitting #32 and stopping.&lt;br /&gt;
&lt;br /&gt;
This gets the code down to 29 bytes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
                org 100h&lt;br /&gt;
&lt;br /&gt;
                mov     ah, 0B8h&lt;br /&gt;
                mov     es, ax          ; es so we can use es: LODS and STOS to the same place&lt;br /&gt;
&lt;br /&gt;
doScreen:&lt;br /&gt;
                mov     ch, 08          ; (80 * 25 = 2000/07d0h)&lt;br /&gt;
                xor     bx, bx          ; bx is also our &amp;quot;num of altered chars&amp;quot; counter&lt;br /&gt;
                mov     di, bx          ; es:di now points at the screen (b800:0000)&lt;br /&gt;
                mov     si, di          ; ds:si = es:di, needed for lods/stos&lt;br /&gt;
&lt;br /&gt;
alterChars:&lt;br /&gt;
                es: lodsw               ; Retreive onscreen character&lt;br /&gt;
                cmp     al, 32          ; comp to a space character (#32)&lt;br /&gt;
                jz      short nextChar  ; If already a space, do nothing&lt;br /&gt;
                dec     al              ; If higher than a space, decrease downward&lt;br /&gt;
                inc     bx              ; increase &amp;quot;number of processed chars&amp;quot; counter&lt;br /&gt;
&lt;br /&gt;
nextChar:&lt;br /&gt;
                stosw&lt;br /&gt;
                loop    alterChars      ; Continue processing characters&lt;br /&gt;
                or      bx,bx           ; Were any characters processed?&lt;br /&gt;
                jnz     short doScreen  ; If so (bx != 0), keep processing&lt;br /&gt;
                ret                     ; exit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optimizing the above is left as an exercise to the reader.  It may be possible to shrink it further using instructions for the 80186 and later processors, but it runs way too quickly on those systems, so if doing so you may want to insert a HLT to pace the animation at 18.2 Hz.  It may also be possible to shrink it by taking advantage of the fact that ASCII character #0 is a null and shows nothing onscreen (just like the #32 space character), so instead of decrementing down to #32, you could decrement down to #0 in a more optimized form (like using the zero flag).&lt;br /&gt;
&lt;br /&gt;
== Or you could rethink it completely ==&lt;br /&gt;
&lt;br /&gt;
If you're willing to deviate from the original target environment (namely, that it was designed for a 4.77 MHz 8088), you can eliminate range checking for all sorts of optimizations.  &lt;br /&gt;
Instead of using two pointers/segments, it's possible to use only one, and directly operate on the chars on screen. Combined with optimized segment assignment and exclusion of the &amp;quot;processed chars&amp;quot;-count (fixed amount of iterations, set to the maximum possible 65536 * 255) this results in a 17 byte variation :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
			lds		bx,[si]			; load DS from our code &amp;quot;scasw&amp;quot; + &amp;quot;nop&amp;quot; = 0AF90h&lt;br /&gt;
			nop						; for alignment, maybe optimization potential here ;)&lt;br /&gt;
doChar:&lt;br /&gt;
			scasw					; used to advance DI by 2, and as DS high byte (0AFh)&lt;br /&gt;
			cmp 	byte [di],32	; is the current char on screen a &amp;quot;space&amp;quot;?&lt;br /&gt;
			jz		short skip 		; yes, don't decrement&lt;br /&gt;
			dec 	byte [di]		; nope, decrement&lt;br /&gt;
skip:&lt;br /&gt;
			dec 	dx				; first loop, besides the first time &lt;br /&gt;
			jnz 	doChar			; it's 65536 iterations&lt;br /&gt;
			loop 	doChar			; second loop, 255 times&lt;br /&gt;
			ret						; quit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above performs the same function as the previous optimization, but runs much more slowly as it traverses more RAM areas than necessary.&lt;br /&gt;
&lt;br /&gt;
There might be a way of altering the &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; to something useful.&lt;br /&gt;
&lt;br /&gt;
Returning to the non-printing null char, we can shave one more byte, to produce this 16 bytes version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
			lds		bx,[si]			; load DS from our code &amp;quot;scasw&amp;quot; + &amp;quot;nop&amp;quot; = 0AF90h&lt;br /&gt;
			nop						; for alignment, maybe optimization potential here ;)&lt;br /&gt;
doChar:&lt;br /&gt;
			scasw					; used to advance DI by 2, and as DS high byte (0AFh)&lt;br /&gt;
			cmp 	byte [di],al	; is the current char on screen a &amp;quot;null&amp;quot;?&lt;br /&gt;
			jz		short skip 		; yes, don't decrement&lt;br /&gt;
			dec 	byte [di]		; nope, decrement&lt;br /&gt;
skip:&lt;br /&gt;
			dec 	dx				; first loop, besides the first time &lt;br /&gt;
			jnz 	doChar			; it's 65536 iterations&lt;br /&gt;
			loop 	doChar			; second loop, 255 times&lt;br /&gt;
			ret						; quit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above performs a similar function as the previous optimization, but runs even more slowly as it requires regular characters to be decremented further than before.&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Getting_Started&amp;diff=183</id>
		<title>Getting Started</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Getting_Started&amp;diff=183"/>
				<updated>2016-08-14T18:29:42Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: clarify initial SP&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Words of warning ==&lt;br /&gt;
&lt;br /&gt;
Sizecoding assumes a basic level of assembler knowledge.  You should have at least a few regular (non-optimized) assembler programs under your belt before you attempt sizecoding.  Also, don't assume sizecoding is ''normal'' -- shaving bytes is a black art that should be kept far, far away from normal programming targets.  People sizecode for fun, not profit!&lt;br /&gt;
&lt;br /&gt;
== Tools and Workflows ==&lt;br /&gt;
&lt;br /&gt;
Most people use NASM (it's free) and DOSBox for testing.  A simple workflow:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
nasm main.asm -fbin -o main.com&lt;br /&gt;
ndisasm -o100h main.com&lt;br /&gt;
dir main.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some crazy sizecoders like writing tinyprogs on very old hardware.  For that, a86 is a good choice for an assembler, as it assembles source directly to a .COM file in one pass.  Even on the first 8086 systems, you can use debug.com to check the assembly and size:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
a86 main.asm&lt;br /&gt;
debug main.com&lt;br /&gt;
dir main.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Know your environment ==&lt;br /&gt;
&lt;br /&gt;
Most sizecoders choose to write to mode 13h, a chunky 320x200 graphics mode located at segment A000:0000.  Each byte is a pixel, and the graphics buffer is linear, so it is extremely easy to program for.  Because it is contained to a single segment, you can be sloppy, as overwriting or underwriting the offset value won't damage anything.  The [https://en.wikipedia.org/wiki/Video_Graphics_Array#/media/File:VGA_palette_with_black_borders.svg default palette] leaves a little to be desired, so if you have room, you may want to change it.&lt;br /&gt;
&lt;br /&gt;
=== .COM file defaults ===&lt;br /&gt;
&lt;br /&gt;
Knowing what register values are initialized at program start can save you the trouble of having to set them in your code.  On most (but not all) DOS environments, the following registers have these default values:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
AX=0000&lt;br /&gt;
BX=0000&lt;br /&gt;
CX=00FF&lt;br /&gt;
DX=Same as CS register&lt;br /&gt;
SI=0100&lt;br /&gt;
DI=FFFE&lt;br /&gt;
SP=FFFC (DOS child process) or FFFE (the default)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Because .COM files only support 64K executables, &amp;lt;code&amp;gt;DS&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ES&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;SS&amp;lt;/code&amp;gt; are all set to the same value as &amp;lt;code&amp;gt;CS&amp;lt;/code&amp;gt;.  The rest can't be counted on for any specific value, except that &amp;lt;code&amp;gt;BP&amp;lt;/code&amp;gt; is mostly 09??h so you can usually count on the high byte being &amp;lt;code&amp;gt;09h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Usually, the top stack contains &amp;lt;code&amp;gt;0000h&amp;lt;/code&amp;gt;. That allows for using the one byte instruction &amp;lt;code&amp;gt;RET&amp;lt;/code&amp;gt; to exit your program, since at location &amp;lt;code&amp;gt;CS:0000h&amp;lt;/code&amp;gt; there is the value &amp;lt;code&amp;gt;20CDh&amp;lt;/code&amp;gt; (= &amp;lt;code&amp;gt;int 20h&amp;lt;/code&amp;gt;). See [https://en.wikipedia.org/wiki/Program_Segment_Prefix Program Segment Prefix].&lt;br /&gt;
&lt;br /&gt;
=== Boot sector defaults ===&lt;br /&gt;
&lt;br /&gt;
Boot sector tinyprogs are occasionally explored, but The BIOS changes every register value as it executes before the boot sequence, so there's not much to count on other than what occurs directly before execution of the boot sector:&lt;br /&gt;
* The boot sector is loaded at 0000:7C00&lt;br /&gt;
* DL holds the drive number that was booted from, so if booted from a floppy disk in drive A:, it will be 00&lt;br /&gt;
* The stack pointer is 512 bytes beyond the end of the boot sector, so SP is likely 7E00h&lt;br /&gt;
&lt;br /&gt;
This is why most sizecoders target .COM files, and is also why [https://github.com/nanochess/Toledo-Atomchess Toledo Atomchess] is 9 bytes larger if loaded from boot sector than from a .COM file.&lt;br /&gt;
&lt;br /&gt;
=== 1-byte opcodes ===&lt;br /&gt;
The 80x86 family was originally a [https://en.wikipedia.org/wiki/Complex_instruction_set_computing CISC] design, which is a design philosophy that intentionally attempts to create many instructions that perform multiple steps.  In sizecoding, you are trying to perform as much work in as little space as possible, so it is helpful to know (or memorize!) every 1-byte instruction in the 80x86 family.  Here's a handy chart (segments and prefixes omitted):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Opcode !! Mnemonic !! Arch !! Description !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 37      || AAA     ||         || ASCII adjust AL (carry into AH) after addition&lt;br /&gt;
|-&lt;br /&gt;
|3F||AAS         || ||ASCII adjust AL (borrow from AH) after subtraction    &lt;br /&gt;
|-&lt;br /&gt;
|98||CBW         || ||Convert byte into word (AH = top bit of AL)           &lt;br /&gt;
|-&lt;br /&gt;
|99||CDQ         ||80386+||Convert dword to qword (EDX = top bit of EAX)         &lt;br /&gt;
|-&lt;br /&gt;
|F8||CLC         || ||Clear carry flag                                      &lt;br /&gt;
|-&lt;br /&gt;
|FC||CLD         || ||Clear direction flag so SI and DI will increment      &lt;br /&gt;
|-&lt;br /&gt;
|FA||CLI         || ||Clear interrupt enable flag; interrupts disabled      &lt;br /&gt;
|-&lt;br /&gt;
|F5||CMC         || ||Complement carry flag                                 &lt;br /&gt;
|-&lt;br /&gt;
|A6||CMPS mb,mb  || ||Compare bytes [SI] - ES:[DI], advance SI,DI           &lt;br /&gt;
|-&lt;br /&gt;
|A7||CMPS mv,mv  || ||Compare words [SI] - ES:[DI], advance SI,DI          &lt;br /&gt;
|-&lt;br /&gt;
|A6||CMPSB       || ||Compare bytes DS:[SI] - ES:[DI], advance SI,DI        &lt;br /&gt;
|-&lt;br /&gt;
|A7||CMPSD       ||80386+||Compare dwords DS:[SI] - ES:[DI], advance SI,DI       &lt;br /&gt;
|-&lt;br /&gt;
|A7||CMPSW       || ||Compare words DS:[SI] - ES:[DI], advance SI,DI        &lt;br /&gt;
|-&lt;br /&gt;
|99||CWD         || ||Convert word to doubleword (DX = top bit of AX)       &lt;br /&gt;
|-&lt;br /&gt;
|98||CWDE        ||80386+||Sign-extend word AX to doubleword EAX                 &lt;br /&gt;
|-&lt;br /&gt;
|27||DAA         || ||Decimal adjust AL after addition                      &lt;br /&gt;
|-&lt;br /&gt;
|2F||DAS         || ||Decimal adjust AL after subtraction                   &lt;br /&gt;
|-&lt;br /&gt;
|F4||HLT         || ||Halt||Resumes operation if an interrupt occurs; could use this for pacing effects that run too fast&lt;br /&gt;
|-&lt;br /&gt;
|EC||IN AL,DX    || ||Input byte from port DX into AL                       &lt;br /&gt;
|-&lt;br /&gt;
|ED||IN eAX,DX   || ||Input word from port DX into eAX                     &lt;br /&gt;
|-&lt;br /&gt;
|6C||INS rmb,DX  ||80186+||Input byte from port DX into [DI], advance DI         &lt;br /&gt;
|-&lt;br /&gt;
|6D||INS rmv,DX  ||80186+||Input word from port DX into [DI], advance DI        &lt;br /&gt;
|-&lt;br /&gt;
|6C||INSB        ||80186+||Input byte from port DX into ES:[DI], advance DI      &lt;br /&gt;
|-&lt;br /&gt;
|6D||INSD        ||80386+||Input dword from port DX into ES:[DI], advance DI     &lt;br /&gt;
|-&lt;br /&gt;
|6D||INSW        ||80186+||Input word from port DX into ES:[DI], advance DI     &lt;br /&gt;
|-&lt;br /&gt;
|CC||INT 3       || ||Interrupt 3 (trap to debugger)||If performing very many CALLs to a single procedure, could make it INT 3&lt;br /&gt;
|-&lt;br /&gt;
|CE||INTO        || ||Interrupt 4 if overflow flag is 1                     &lt;br /&gt;
|-&lt;br /&gt;
|CF||IRET        || ||Interrupt return (far return and pop flags)           &lt;br /&gt;
|-&lt;br /&gt;
|CF||IRETD       ||80386+||Interrupt return (pop EIP, ECS, Eflags)               &lt;br /&gt;
|-&lt;br /&gt;
|9F||LAHF        || ||Load: AH = flags  SF ZF xx AF xx PF xx CF             &lt;br /&gt;
|-&lt;br /&gt;
|C9||LEAVE       ||80186+||Set SP to BP, then POP BP (reverses previous ENTER)   &lt;br /&gt;
|-&lt;br /&gt;
|AC||LODS mb     || ||Load byte [SI] into AL, advance SI                    &lt;br /&gt;
|-&lt;br /&gt;
|AD||LODS mv     || ||Load word [SI] into eAX, advance SI                  &lt;br /&gt;
|-&lt;br /&gt;
|AC||LODSB       || ||Load byte [SI] into AL, advance SI                    &lt;br /&gt;
|-&lt;br /&gt;
|AD||LODSD       ||80386+||Load dword [SI] into EAX, advance SI                  &lt;br /&gt;
|-&lt;br /&gt;
|AD||LODSW       || ||Load word [SI] into AX, advance SI                    &lt;br /&gt;
|-&lt;br /&gt;
|A4||MOVS mb,mb  || ||Move byte [SI] to ES:[DI], advance SI,DI              &lt;br /&gt;
|-&lt;br /&gt;
|A5||MOVS mv,mv  || ||Move word [SI] to ES:[DI], advance SI,DI             &lt;br /&gt;
|-&lt;br /&gt;
|A4||MOVSB       || ||Move byte DS:[SI] to ES:[DI], advance SI,DI           &lt;br /&gt;
|-&lt;br /&gt;
|A5||MOVSD       ||80386+||Move dword DS:[SI] to ES:[DI], advance SI,DI          &lt;br /&gt;
|-&lt;br /&gt;
|A5||MOVSW       || ||Move word DS:[SI] to ES:[DI], advance SI,DI           &lt;br /&gt;
|-&lt;br /&gt;
|90||NOP         || ||No Operation                                          &lt;br /&gt;
|-&lt;br /&gt;
|EE||OUT DX,AL   || ||Output byte AL to port number DX                      &lt;br /&gt;
|-&lt;br /&gt;
|EF||OUT DX,eAX  || ||Output word eAX to port number DX                     &lt;br /&gt;
|-&lt;br /&gt;
|6E||OUTS DX,rmb ||80186+||Output byte [SI] to port number DX, advance SI        &lt;br /&gt;
|-&lt;br /&gt;
|6F||OUTS DX,rmv ||80186+||Output word [SI] to port number DX, advance SI        &lt;br /&gt;
|-&lt;br /&gt;
|6E||OUTSB       ||80186+||Output byte DS:[SI] to port number DX, advance SI     &lt;br /&gt;
|-&lt;br /&gt;
|6F||OUTSD       ||80386+||Output dword DS:[SI] to port number DX, advance SI    &lt;br /&gt;
|-&lt;br /&gt;
|6F||OUTSW       ||80186+||Output word DS:[SI] to port number DX, advance SI     &lt;br /&gt;
|-&lt;br /&gt;
|1F||POP DS      || ||Set DS to top of stack, increment SP by 2             &lt;br /&gt;
|-&lt;br /&gt;
|07||POP ES      || ||Set ES to top of stack, increment SP by 2             &lt;br /&gt;
|-&lt;br /&gt;
|17||POP SS      || ||Set SS to top of stack, increment SP by 2             &lt;br /&gt;
|-&lt;br /&gt;
|61||POPA        ||80186+||Pop DI,SI,BP,x ,BX,DX,CX,AX (SP value is ignored)     &lt;br /&gt;
|-&lt;br /&gt;
|61||POPAD       ||80386+||Pop EDI,ESI,EBP,x,EBX,EDX,ECX,EAX (ESP ign.)          &lt;br /&gt;
|-&lt;br /&gt;
|9D||POPF        || ||Set flags register to top of stack, increment SP by 2 &lt;br /&gt;
|-&lt;br /&gt;
|9D||POPFD       ||80386+||Set eflags reg to top of stack, incr SP by 2          &lt;br /&gt;
|-&lt;br /&gt;
|0E||PUSH CS     || ||Set [SP-2] to CS, then decrement SP by 2              &lt;br /&gt;
|-&lt;br /&gt;
|1E||PUSH DS     || ||Set [SP-2] to DS, then decrement SP by 2              &lt;br /&gt;
|-&lt;br /&gt;
|06||PUSH ES     || ||Set [SP-2] to ES, then decrement SP by 2              &lt;br /&gt;
|-&lt;br /&gt;
|16||PUSH SS     || ||Set [SP-2] to SS, then decrement SP by 2              &lt;br /&gt;
|-&lt;br /&gt;
|60||PUSHA       ||80186+||Push AX,CX,DX,BX,original SP,BP,SI,DI                 &lt;br /&gt;
|-&lt;br /&gt;
|60||PUSHAD      ||80386+||Push EAX,ECX,EDX,EBX,original ESP,EBP,ESI,EDI         &lt;br /&gt;
|-&lt;br /&gt;
|9C||PUSHF       || ||Set [SP-2] to flags register, then decrement SP by 2  &lt;br /&gt;
|-&lt;br /&gt;
|9C||PUSHFD      ||80386+||Set [SP-4] to eflags reg, then decr SP by 4           &lt;br /&gt;
|-&lt;br /&gt;
|C3||RET         || ||Return to caller (near or far, depending on PROC)     &lt;br /&gt;
|-&lt;br /&gt;
|CB||RETF        || ||Return to far caller (pop offset, then seg)           &lt;br /&gt;
|-&lt;br /&gt;
|C3||RETN        || ||Return to near caller (pop offset only)               &lt;br /&gt;
|-&lt;br /&gt;
|9E||SAHF        || ||Store AH into flags  SF ZF xx AF xx PF xx CF          &lt;br /&gt;
|-&lt;br /&gt;
|AE||SCAS mb     || ||Compare bytes AL - ES:[DI], advance DI                &lt;br /&gt;
|-&lt;br /&gt;
|AF||SCAS mv     || ||Compare words eAX - ES:[DI], advance DI              &lt;br /&gt;
|-&lt;br /&gt;
|AE||SCASB       || ||Compare bytes AL - ES:[DI], advance DI                &lt;br /&gt;
|-&lt;br /&gt;
|AF||SCASD       ||80386+||Compare dwords EAX - ES:[DI], advance DI              &lt;br /&gt;
|-&lt;br /&gt;
|AF||SCASW       || ||Compare words AX - ES:[DI], advance DI                &lt;br /&gt;
|-&lt;br /&gt;
|36||SS          || ||Use SS segment for the following memory reference     &lt;br /&gt;
|-&lt;br /&gt;
|F9||STC         || ||Set carry flag                                        &lt;br /&gt;
|-&lt;br /&gt;
|FD||STD         || ||Set direction flag so SI and DI will decrement        &lt;br /&gt;
|-&lt;br /&gt;
|FB||STI         || ||Set interrupt enable flag, interrupts enabled         &lt;br /&gt;
|-&lt;br /&gt;
|AA||STOS mb     || ||Store AL to byte [DI], advance DI                     &lt;br /&gt;
|-&lt;br /&gt;
|AB||STOS mv     || ||Store eAX to word [DI], advance DI                    &lt;br /&gt;
|-&lt;br /&gt;
|AA||STOSB       || ||Store AL to byte ES:[DI], advance DI                  &lt;br /&gt;
|-&lt;br /&gt;
|AB||STOSD       ||80386+||Store EAX to dword ES:[DI], advance DI                &lt;br /&gt;
|-&lt;br /&gt;
|AB||STOSW       || ||Store AX to word ES:[DI], advance DI                  &lt;br /&gt;
|-&lt;br /&gt;
|9B||WAIT        || ||Wait until floating-point operation is completed      &lt;br /&gt;
|-&lt;br /&gt;
|D7||XLAT        || ||Set AL to memory byte DS:[BX + unsigned AL]           &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, there are accumulator-optimized (AX) forms of opcodes that are one byte, such as &amp;lt;code&amp;gt;DEC AX&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INC AX&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XCHG reg,AX&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== A sample framework ==&lt;br /&gt;
&lt;br /&gt;
Want to just dive in and see what happens?  Here's a skeleton that sets up Mode 13h, loops until a keypress is detected, then exits.  Although it assembles to only 19 bytes, do not consider this fully and finally optimized; your program's structure may allow some of this to be reduced further.  But it's a good place to start:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=nasm&amp;gt;&lt;br /&gt;
org 100h                        ;specify .COM file&lt;br /&gt;
&lt;br /&gt;
start:&lt;br /&gt;
        mov     al,13h          ;AX=0000 at program start&lt;br /&gt;
        int     10h             ;init mode 13h&lt;br /&gt;
        push    word A000h      ;Requires 80186 or higher to PUSH IMMED&lt;br /&gt;
        pop     es              ;ES now points to mode 13h screen segment&lt;br /&gt;
        &lt;br /&gt;
mainloop:&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
;this is where you do your mega-amazing tiny program;&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
&lt;br /&gt;
        ;Check for user wanting to leave by pressing ESC&lt;br /&gt;
        in      al,60h          ;read whatever is at keyboard port; looking for ESC which is #1&lt;br /&gt;
        dec     ax              ;if ESC, AX now 0&lt;br /&gt;
        jnz     mainloop        ;fall through if 0, jump otherwise&lt;br /&gt;
        mov     al,03           ;AX=0000 due to mainloop exit condition&lt;br /&gt;
        int     10h             ;Switch back to text mode as a convenience&lt;br /&gt;
        ret                     ;.COM files can exit with RET&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Where to go from here? ==&lt;br /&gt;
&lt;br /&gt;
[[Techniques|Tips, Tricks, and Techniques]] can help you with ideas on optimizing your next production, or help you design while you're writing it.&lt;br /&gt;
&lt;br /&gt;
Some [[Case Studies]] are provided that illustrate and explain some of the choices made when sizecoding.&lt;br /&gt;
&lt;br /&gt;
Can't find what you need?  Check our list of [[Resources|external resources]].&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=User:Qkumba&amp;diff=181</id>
		<title>User:Qkumba</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=User:Qkumba&amp;diff=181"/>
				<updated>2016-08-14T18:20:23Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: create page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I started coding for 6502 CPUs in 1982 ([http://pferrie.host22.com/misc/appleii.htm and still do]), x86 since 1990 or so.  Some of my recent efforts are on [http://pferrie.host22.com/misc/intel.htm this page] of [http://pferrie.host22.com/misc/intel.htm my website], and on my [https://github.com/peterferrie GitHub site].&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Resources&amp;diff=156</id>
		<title>Resources</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Resources&amp;diff=156"/>
				<updated>2016-08-12T23:06:55Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: link to register value derivation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Discussions ==&lt;br /&gt;
&lt;br /&gt;
Pouet's [http://www.pouet.net/topic.php?which=8791&amp;amp;page=1 Tiny Intro Toolbox Thread] was one of sizecoding.org's main inspirations.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
The Hugi demoscene diskmag has been kind to the sizecoding movement.  They included [http://www.hugi.scene.org/online/coding/hugi%20se%204%20-%20index%20sorted%20by%20topic.htm many programming articles] since it started in 1996.  Additionally, the [http://www.hugi.scene.org/compo/compoold.htm Hugi Size Coding Competition Series] is the gold standard for learning how to sizecode:  Each competition was given a specific task, then participants submitted their results.  ([http://retrolandia.net/hugi/showthread.php?tid=7&amp;amp;pid=13#pid13 All of the entries with their source code] are available, as are [http://retrolandia.net/hugi/showthread.php?tid=7&amp;amp;pid=396#pid396 the rules for each challenge].)  Hugi #35 also provided a [http://hugi.scene.org/online/hugi35/hugi%2035%20-%20demoscene%20forum%20adok%20256b%20intros%20round-table.htm 256b intros round-table] between Baze, Digimind, Rrrola, Pirx, Optimus, and Seven.&lt;br /&gt;
&lt;br /&gt;
fysnet.net has an extensive [http://www.fysnet.net/yourhelp.htm list of DOS .COM register starting values].  If your environment isn't listed, [http://www.fysnet.net/yourhelp.com a program] is also available that can print out all of the register starting values.  See also [http://pferrie.host22.com/misc/lowlevel12.htm DOS Register Starting Values] to understand why the register starting values for .COM files are set the way that they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The [http://sparksandflames.com/files/x86InstructionChart.html Sparks And Flames x86 Instruction Chart] is awesome, once you can &amp;quot;read&amp;quot; it. Find out what the bright green (1-byte) commands do, and use them. For the extreme sizecoding (&amp;lt;=32 bytes) it's also very useful to have the HEX value in sight.&lt;br /&gt;
&lt;br /&gt;
The [http://ref.x86asm.net/geek.html Geek Edition x86asm-ref] is comprehensive and dense.  It might be the only reference you'll need.  The last part covers modr/m bytes, which is useful.&lt;br /&gt;
&lt;br /&gt;
[http://x86.renejeschke.de/ Rene Jeschke's preservation of siyobik.com's x86 Documentation] is one of the most compact and understandable references to the x86 instruction set you'll ever see.&lt;br /&gt;
&lt;br /&gt;
[http://www.rcollins.org/secrets/OpCodes.html Robert Collins' Undocumented Opcodes] page has some gems you can exploit depending on your target environment.&lt;br /&gt;
&lt;br /&gt;
[http://wiki.osdev.org/PC_Speaker PC Speaker Basics] For everything from simple bleeps to sophisticated synthesizers.&lt;br /&gt;
&lt;br /&gt;
[https://de.wikipedia.org/wiki/Program_Segment_Prefix Program Segment Prefix] : whats in front of our code, and why.&lt;br /&gt;
&lt;br /&gt;
Never underestimate [http://www.hugi.scene.org/online/coding/hugi%2017%20-%20coaax.htm The Hidden Power of BCD Instructions].&lt;br /&gt;
&lt;br /&gt;
[http://wiki.osdev.org/Programmable_Interval_Timer Programmable Interval Timer] : timing is everything.&lt;br /&gt;
&lt;br /&gt;
== Repositories ==&lt;br /&gt;
&lt;br /&gt;
Tinyprogs are so small that you sometimes don't need the source code to understand them:  Just pop them into a disassembler (like IDA) or a debugger and look at them.  If you want to grab specimens for study, here are some places to start.&lt;br /&gt;
&lt;br /&gt;
Pouet can be searched for the latest tinyprogs:  [http://www.pouet.net/prodlist.php?type%5B%5D=256b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 256b], [http://www.pouet.net/prodlist.php?type%5B%5D=128b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 128b], [http://www.pouet.net/prodlist.php?type%5B%5D=64b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 64b], and even [http://www.pouet.net/prodlist.php?type%5B%5D=32b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 32b and smaller].&lt;br /&gt;
&lt;br /&gt;
[http://hardcode.untergrund.net/ HardCode] is a repository of 7800 64KB and smaller intros.&lt;br /&gt;
&lt;br /&gt;
[http://256bytes.untergrund.net 256b.com] is a website dedicated primarily to 256b and smaller releases.&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	<entry>
		<id>http://www.sizecoding.org/index.php?title=Resources&amp;diff=155</id>
		<title>Resources</title>
		<link rel="alternate" type="text/html" href="http://www.sizecoding.org/index.php?title=Resources&amp;diff=155"/>
				<updated>2016-08-12T22:59:58Z</updated>
		
		<summary type="html">&lt;p&gt;Qkumba: corrected 256.com link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Discussions ==&lt;br /&gt;
&lt;br /&gt;
Pouet's [http://www.pouet.net/topic.php?which=8791&amp;amp;page=1 Tiny Intro Toolbox Thread] was one of sizecoding.org's main inspirations.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
The Hugi demoscene diskmag has been kind to the sizecoding movement.  They included [http://www.hugi.scene.org/online/coding/hugi%20se%204%20-%20index%20sorted%20by%20topic.htm many programming articles] since it started in 1996.  Additionally, the [http://www.hugi.scene.org/compo/compoold.htm Hugi Size Coding Competition Series] is the gold standard for learning how to sizecode:  Each competition was given a specific task, then participants submitted their results.  ([http://retrolandia.net/hugi/showthread.php?tid=7&amp;amp;pid=13#pid13 All of the entries with their source code] are available, as are [http://retrolandia.net/hugi/showthread.php?tid=7&amp;amp;pid=396#pid396 the rules for each challenge].)  Hugi #35 also provided a [http://hugi.scene.org/online/hugi35/hugi%2035%20-%20demoscene%20forum%20adok%20256b%20intros%20round-table.htm 256b intros round-table] between Baze, Digimind, Rrrola, Pirx, Optimus, and Seven.&lt;br /&gt;
&lt;br /&gt;
fysnet.net has an extensive [http://www.fysnet.net/yourhelp.htm list of DOS .COM register starting values].  If your environment isn't listed, [http://www.fysnet.net/yourhelp.com a program] is also available that can print out all of the starting register values.&lt;br /&gt;
&lt;br /&gt;
The [http://sparksandflames.com/files/x86InstructionChart.html Sparks And Flames x86 Instruction Chart] is awesome, once you can &amp;quot;read&amp;quot; it. Find out what the bright green (1-byte) commands do, and use them. For the extreme sizecoding (&amp;lt;=32 bytes) it's also very useful to have the HEX value in sight.&lt;br /&gt;
&lt;br /&gt;
The [http://ref.x86asm.net/geek.html Geek Edition x86asm-ref] is comprehensive and dense.  It might be the only reference you'll need.  The last part covers modr/m bytes, which is useful.&lt;br /&gt;
&lt;br /&gt;
[http://x86.renejeschke.de/ Rene Jeschke's preservation of siyobik.com's x86 Documentation] is one of the most compact and understandable references to the x86 instruction set you'll ever see.&lt;br /&gt;
&lt;br /&gt;
[http://www.rcollins.org/secrets/OpCodes.html Robert Collins' Undocumented Opcodes] page has some gems you can exploit depending on your target environment.&lt;br /&gt;
&lt;br /&gt;
[http://wiki.osdev.org/PC_Speaker PC Speaker Basics] For everything from simple bleeps to sophisticated synthesizers.&lt;br /&gt;
&lt;br /&gt;
[https://de.wikipedia.org/wiki/Program_Segment_Prefix Program Segment Prefix] : whats in front of our code, and why.&lt;br /&gt;
&lt;br /&gt;
Never underestimate [http://www.hugi.scene.org/online/coding/hugi%2017%20-%20coaax.htm The Hidden Power of BCD Instructions].&lt;br /&gt;
&lt;br /&gt;
[http://wiki.osdev.org/Programmable_Interval_Timer Programmable Interval Timer] : timing is everything.&lt;br /&gt;
&lt;br /&gt;
== Repositories ==&lt;br /&gt;
&lt;br /&gt;
Tinyprogs are so small that you sometimes don't need the source code to understand them:  Just pop them into a disassembler (like IDA) or a debugger and look at them.  If you want to grab specimens for study, here are some places to start.&lt;br /&gt;
&lt;br /&gt;
Pouet can be searched for the latest tinyprogs:  [http://www.pouet.net/prodlist.php?type%5B%5D=256b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 256b], [http://www.pouet.net/prodlist.php?type%5B%5D=128b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 128b], [http://www.pouet.net/prodlist.php?type%5B%5D=64b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 64b], and even [http://www.pouet.net/prodlist.php?type%5B%5D=32b&amp;amp;platform%5B%5D=MS-Dos&amp;amp;page=1 32b and smaller].&lt;br /&gt;
&lt;br /&gt;
[http://hardcode.untergrund.net/ HardCode] is a repository of 7800 64KB and smaller intros.&lt;br /&gt;
&lt;br /&gt;
[http://256bytes.untergrund.net 256b.com] is a website dedicated primarily to 256b and smaller releases.&lt;/div&gt;</summary>
		<author><name>Qkumba</name></author>	</entry>

	</feed>