Search (using Google):  Web Karig

 

13 December 2003

Adding a record block

Now I want to verify that I can store some arbitrary data to the record segment.

I'll store a sixteen-byte string into block #1 and use dump_16 to verify that (1) the directory entry for block #1 was written correctly, and (2) the data to be contained in block #1 was written at the correct location.

Code

The new code does the following:

Prepare for a REP MOVSB operation. First, load DI with the address where data is going — in this case, the offset to the first byte beyond the end of the data in the record segment, which is always equal to the data size stored at 0x1000:0000. (In this case, ES is assumed to be pointing to the record segment already. Also note that I need to use the data size in a calculation, so I load it into AX — and the code produced by loading AX and moving to DI is one byte shorter than the equivalent code that loads DI and moves to AX.)

		mov	ax, [es:0]
		mov	di, ax

For REP MOVSB, CX must be loaded with the number of bytes to move.

		mov	cx, 16 ; size of block

REP MOVSB alters CX, which contains a value I need to calculate the new record-segment data size, so I calculate that now.

		add	ax, cx

Normally at this point I'd include jc .error — that is, if the carry flag is set, then there's not enough room in the record segment for the new block, so we can't add it. But that won't happen here, so I simply store the result in the data-size field.

		mov	[es:0], ax

Now I write the directory entry for block #1. Note that if the block number is between 1 and 15, the block's entry is stored in the start block. That block's offset field is at offset (block-number x 4), and the block's size field is at offset ((block-number x 4) + 2). So I store the block offset (in DI) to offset 4, and I store the block size (in CX) to offset 6.

		mov	[es:4], di
		mov	[es:6], cx

For REP MOVSB, store the segment:offset of the bytes to be copied in DS:SI. DS is assumed to be 0x0000 already, so I load only SI here.

		mov	si, recdata

Now move the bytes into the block. (Note that I could have sped things up by halving CX and using REP MOVSW instead, but I'm concentrating on keeping the code small, not making it faster.)

		rep	movsb

Now I can dump the contents of the start block (the first 64 bytes of the record segment).

		call	clear_screen
		mov	ax, 0x1000
		mov	fs, ax
		xor	bx, bx
		call	dump_16
		call	dump_16
		call	dump_16
		call	dump_16

I dump another 16 bytes so that I can show the contents of block #1. The ASCII portion of the dump should say Here's some text.

		call	dump_16

I dump another 16 bytes to show that the space beyond the end of block #1 is all zeroes.

		call	dump_16

		jmp	$

recdata:
		db	"Here's some text" ; 16 chars long

Results

Record #0 in the start block should now list a data size of 0x50 (80 -- 64 + 16). The start-block size at offset 2 should still be 0x40 (64).

Record #1 in the start block (at offset 4) should show an offset of 0x40 (64) and a size of 0x10 (16).

Block #1 (at offset 0x0040 or 64) should contain the characters "Here's some text".

Here is the display that appears on my laptop when I run this code:

1000:0000: 50 00 40 00 40 00 10 00 00 00 00 00 00 00 00 00 | P @ @ >
1000:0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
1000:0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
1000:0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
1000:0040: 48 65 72 65 27 73 20 73 6F 6D 65 20 74 65 78 74 | Here's some text
1000:0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |

Check the index for other entries.