Difference between revisions of "Output"

From SizeCoding
Jump to: navigation, search
(three textmode output possibilities with external links)
(added the "LES inception" trick)
Line 40: Line 40:
 
pop ss
 
pop ss
 
int 0x20
 
int 0x20
</syntaxhighlight>  
+
</syntaxhighlight>
 +
 
 +
You might notice that the ''push <word>'' + ''pop seg_reg'' combination is always the same and occupies four bytes alltogether. If correct alignment is not important to you and you really just want ''any'' pointer to the screen, there is another way to get a valid one:
 +
 
 +
<syntaxhighlight lang="nasm">
 +
les bx,[si]
 +
nop
 +
stosb
 +
</syntaxhighlight>
 +
 
 +
That's also four bytes, but it already has the ''stosb'' opcode (for putting something onto the screen) integrated and even one slot free for another one-byte-instruction. It works because SI initially points to the start of our code, and ''stosb'' has the hexadecimal representation of 0xAA. After the first command, the segment register ES contains the value 0xAB90. If you repeatedly write something to the screen with ''stosb'' you will eventually reach the 0xB800 segment and chars will appear on the screen. With a careful selection of the free one-byte-opcode you can also reintroduce some alignment. This works also with the ''stosw'' opcode (0xAB).
  
 
=== Outputting in mode 13h (320x200) ===
 
=== Outputting in mode 13h (320x200) ===

Revision as of 13:37, 12 August 2016

Outputting to the screen

First, be aware of the MSDOS memory layout

Outputting in Textmode (80x25)

Right after the start of your program you are in mode 3, that is 80x25 in 16 colors.

See the Video Modes List

So, to show something on the screen, you would need to set a segment register to 0xB800, then write values into this segment.

The following three snippets showcase how to draw a red smiley in three different ways. The target coordinate (40,12) is about the middle of the screen. We need a multiplier 2 since one char needs two bytes in memory (char and color is a byte each). The high byte 0x04 means red (4) on black (0) while the 0x01 is the first ASCII char - a smiley.

 
push 0xb800
pop ds
mov bx,(80*12+40)*2
mov ax, 0x0401
mov [bx],ax
ret
 
push 0xb800
pop es
mov di,(80*12+40)*2
mov ax, 0x0401
stosw
ret
 
push ss
push 0xb800
pop ss
mov sp,(80*12+40)*2
mov ax, 0x0401
push ax
pop ss
int 0x20

You might notice that the push <word> + pop seg_reg combination is always the same and occupies four bytes alltogether. If correct alignment is not important to you and you really just want any pointer to the screen, there is another way to get a valid one:

 
les bx,[si]
nop
stosb

That's also four bytes, but it already has the stosb opcode (for putting something onto the screen) integrated and even one slot free for another one-byte-instruction. It works because SI initially points to the start of our code, and stosb has the hexadecimal representation of 0xAA. After the first command, the segment register ES contains the value 0xAB90. If you repeatedly write something to the screen with stosb you will eventually reach the 0xB800 segment and chars will appear on the screen. With a careful selection of the free one-byte-opcode you can also reintroduce some alignment. This works also with the stosw opcode (0xAB).

Outputting in mode 13h (320x200)

Producing sound

MIDI notes

PC Speaker