Assembly

Страница 5/5
1 | 2 | 3 | 4 |

By thegeps

Hero (579)

Аватар пользователя thegeps

17-05-2020, 11:18

This should work. You'll have your values from HL to HL+5. if AT address is hex aligned (low byte is $00) you can gain some speed and use less bytes using "inc l" instead of "inc hl". You can do this even if AT lowbyte+5 doesn't cross the $FF value (so H hasn't to be increased)

var
     tmpInt : integer;
     ss,ds,sm,dm,sh,dh : byte;
     num : array [0..5] of byte;
     hour,min,sec :string[2];
     pt : ^integer;
     at : integer absolute pt;
begin;
    inline(
		$21/at/	{ ld hl,at } 
		$E/$B4/	{ ld c,$B4 }
		$6/$0/	{ ld b,0   } 
		$ED/$41/	{ out (c),b}
		$0C/		{ inc c  faster then ld c,$B5 }
		$ED/$78/	{ in a,(c) }
		$CB/$27/	{ sla a     <- shift left 4 times}
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$3F/	{ srl a     <- shift right 4 times}
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$77/		{ ld (hl),a}
		$23/		{ inc hl   }

		$0D/		{ dec c  faster than ld c,$B4 }
		$04/		{ inc b  faster than ld b,1   }
		$ED/$41/	{ out (c),b}
		$0C/		{ inc c faster than ld c,$B5  }
		$ED/$78/	{ in a,(c) }
		$CB/$27/	{ sla a     <- shift left 4 times}
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$3F/	{ srl a     <- shift right 4 times}
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$77/		{ ld (hl),a}
		$23/		{ inc hl   }

		$0D/		{ dec c  faster than ld c,$B4 }
		$04/		{ inc b  faster than ld b,2   }
		$ED/$41/	{ out (c),b}
		$0C/		{ inc c }
		$ED/$78/	{ in a,(c) }
		$CB/$27/	{ sla a     <- shift left 4 times}
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$3F/	{ srl a     <- shift right 4 times}
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$77/		{ ld (hl),a}
		$23/		{ inc hl   }

		$0D/ 		{ dec c  faster than ld c,$B4 }
		$04/		{ inc b  faster than ld b,3   }
		$ED/$41/	{ out (c),b}
		$0C/		{ inc c }
		$ED/$78/	{ in a,(c) }
		$CB/$27/	{ sla a     <- shift left 4 times}
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$3F/	{ srl a     <- shift right 4 times}
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$77/		{ ld (hl),a}
		$23/		{ inc hl   }

		$0D/ 		{ dec c    }
		$04/		{ inc b    }
		$ED/$41/	{ out (c),b}
		$0C/		{ inc c    }
		$ED/$78/	{ in a,(c) }
		$CB/$27/	{ sla a     <- shift left 4 times}
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$3F/	{ srl a     <- shift right 4 times}
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$77/		{ ld (hl),a}
		$23/		{ inc hl   }

		$0D/ 		{ dec c    }
		$04/		{ inc b    }
		$ED/$41/	{ out (c),b}
		$0C/		{ inc c    }
		$ED/$78/	{ in a,(c) }
		$CB/$27/	{ sla a     <- shift left 4 times}
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$27/	{ sla a    }
		$CB/$3F/	{ srl a     <- shift right 4 times}
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }
		$77		{ ld (hl),a}
        );
end;

By pgimeno

Master (245)

Аватар пользователя pgimeno

17-05-2020, 13:07

I'm not convinced that using a pointer with no value is correct at all. It seems to me that you're writing to the pointer, not to where the pointer points at, and since it's 2 bytes and you're writing more than that, you're writing outside of the variable.

But speaking of efficiency... How about this? (assuming that TimeString is a string[8])

function clock : TimeString;
var
  TS: TimeString;
begin
  inline(
    221/229/         { push ix }
    221/33/TS/       { ld ix,TS }
    221/54/0/8/      { ld (ix+0),8 ; length of the string }
    221/54/3/$3A/    { ld (ix+3),':' }
    221/54/6/$3A/    { ld (ix+6),':' }
    62/5/            { ld a,5 }
    211/$B4/         { out ($B4),a }
    219/$B5/         { in a,($B5) }
    230/$0F/         { and $0F }
    198/$30/         { add a,'0' }
    221/119/1/       { ld (ix+1),a }
    62/4/            { ld a,4 }
    211/$B4/         { out ($B4),a }
    219/$B5/         { in a,($B5) }
    230/$0F/         { and $0F }
    198/$30/         { add a,'0' }
    221/119/2/       { ld (ix+2),a }
    62/3/            { ld a,3 }
    211/$B4/         { out ($B4),a }
    219/$B5/         { in a,($B5) }
    230/$0F/         { and $0F }
    198/$30/         { add a,'0' }
    221/119/4/       { ld (ix+4),a }
    62/2/            { ld a,2 }
    211/$B4/         { out ($B4),a }
    219/$B5/         { in a,($B5) }
    230/$0F/         { and $0F }
    198/$30/         { add a,'0' }
    221/119/5/       { ld (ix+5),a }
    62/1/            { ld a,1 }
    211/$B4/         { out ($B4),a }
    219/$B5/         { in a,($B5) }
    230/$0F/         { and $0F }
    198/$30/         { add a,'0' }
    221/119/7/       { ld (ix+7),a }
    175/             { xor a }
    211/$B4/         { out ($B4),a }
    219/$B5/         { in a,($B5) }
    230/$0F/         { and $0F }
    198/$30/         { add a,'0' }
    221/119/8/       { ld (ix+8),a }
    221/225          { pop ix }
  );
  clock := ts;
end;

Apologies for the mnemonics in decimal, it's how I learned them Smile

By thegeps

Hero (579)

Аватар пользователя thegeps

17-05-2020, 16:06

as I said I don't know TP. I thought that "at" was a pointer to an address. So I started writing within that address. In fact my code set hl to "at" value at the beginning and writing each data in the address pointed by HL, incrementing it after every byte is stored. so if "at" is an address (two bytes long, hi and low) then my code will work.
I didn's use loop becuse I don't know how to implemet adresses jump in the "inline" because I don't know if start address of the code inside "inline". I could have only use JR, I think because it needs only a byte displacement.

By rolandve

Master (220)

Аватар пользователя rolandve

17-05-2020, 17:34

wow, I think I'll need some time to study this. In the last example I posted, the pointer wasn't used anymore. Neither was AT because I dumped everything in A and then in tmpInt. In the situation where I used PT it was initialised like

getmem(pt,6). {allocated 6 bytes, pt point to the first byte}
mem[at]:=12 {writes 12 to the first allocated element because AT points too the location stored in PT. }

By thegeps

Hero (579)

Аватар пользователя thegeps

18-05-2020, 00:52

I don't know why you were doing all that "sla a" and "srl a" but watching at pgimeno code i think you used it to mask push out high nibble (values higher than $F). If it's true you can get rid of all those sla a and rla a and use instead a single AND $0F to mask the value agter each IN A,($B5) as pgimeno did. He also directly convert A value into corresponding ASC value (if you need it for a string is a good way) by doing add A,'0'

By Grauw

Ascended (9398)

Аватар пользователя Grauw

18-05-2020, 00:57

Also:

		$CB/$3F/	{ srl a     <- shift right 4 times}
		$CB/$3F/	{ srl a    }
		$CB/$3F/	{ srl a    }

You shift 3 times the second time around. But yeah using and seems better anyway.

By pgimeno

Master (245)

Аватар пользователя pgimeno

18-05-2020, 03:47

After sleeping on it, I think this should work, being shorter and probably faster as well due to not using IX:

function clock : TimeString;
var
  TS: TimeString;
begin
  inline(
    33/TS/           { ld hl,TS }
    1/5/3/           { ld bc,$0305 ; B = 3 iterations, C = starting value of port $B4 }
    62/8/            { ld a,8 ; length of the string }
{ LOOP: }
    119/             { ld (hl),a ; store 8 the first time, ':' the rest }
    35/              { inc hl ; advance }
    121/             { ld a,c ; grab the digit to ask the hardware }
    13/              { dec c ; prepare next digit }
    211/$B4/         { out ($B4),a ; set digit to read }
    219/$B5/         { in a,($B5) ; read the tens digit }
    230/$0F/         { and $0F ; mask out bits other than 0-3 }
    198/$30/         { add a,'0' ; convert to ASCII }
    119/             { ld (hl),a ; store }
    35/              { inc hl ; advance }
    121/             { ld a,c ; rinse, repeat }
    13/              { dec c }
    211/$B4/         { out ($B4),a }
    219/$B5/         { in a,($B5) ; read the units digit }
    230/$0F/         { and $0F }
    198/$30/         { add a,'0' }
    119/             { ld (hl),a }
    35/              { inc hl }
    62/$3A/          { ld a,':' ; value to write in the next iteration }
    16/-30           { djnz LOOP }
  );
  clock := TS;
end;

It does a trick by writing 8, DIGIT1, DIGIT2; then in the next loop it writes ':', DIGIT3, DIGIT4; and in the final loop it writes ':', DIGIT5, DIGIT6. The byte written first is changed after the first iteration, so that the first time it writes the 8 and the rest of times it writes the ':'.

Edit: Disclaimer: note this one is not tested! If it causes any problems, like emptying your bank account or causing your wife to divorce, don't blame me. I'm not sure if TP allows negative bytes; if not, use 226 instead of -30.

By thegeps

Hero (579)

Аватар пользователя thegeps

18-05-2020, 09:55

Yep, a mistake done by copy/paste (my fault obviously)

Страница 5/5
1 | 2 | 3 | 4 |