Просмотр полной версии : ABS и SGN в машкоде
Oleg N. Cher
01.01.2017, 15:06
Всем привет.
Покритикуйте мою реализацию функций ABS и SGN для байта и слова, может можно как-то оптимизировать.
Байтовый аргумент поступает в регистре L, результат возвращается в нём же. Слова - в паре HL. Таковы соглашения модели вызова __z88dk_fastcall.
/*--------------------------------- Cut here ---------------------------------*/
signed char Basic_ABS (signed char x) __z88dk_fastcall {
__asm
BIT 7,L
RET Z
XOR A
SUB L
LD L,A
__endasm;
} //Basic_ABS
/*--------------------------------- Cut here ---------------------------------*/
signed int Basic_ABSI (signed int x) __z88dk_fastcall {
__asm
BIT 7,H
RET Z
EX DE,HL
XOR A
LD L,A
LD H,A
SBC HL,DE
__endasm;
} //Basic_ABSI
/*--------------------------------- Cut here ---------------------------------*/
signed char Basic_SGN (signed char x) __z88dk_fastcall {
__asm
LD A,L
OR L
RET Z
BIT 7,L
LD L,#0xFF
RET NZ
LD L,#1
__endasm;
} //Basic_SGN
/*--------------------------------- Cut here ---------------------------------*/
signed char Basic_SGNI (signed int x) __z88dk_fastcall {
__asm
LD A,H
OR L
RET Z
BIT 7,H
LD L,#0xFF
RET NZ
LD L,#1
__endasm;
} //Basic_SGNI
Идеально, оптимизировать нечего ;)
Alex Rider
01.01.2017, 15:46
XOR A
LD L,A
LD H,A
LD L,0
LD H,L
На такт быстрее.
Alex Rider
01.01.2017, 16:05
Точно :-(
NEO SPECTRUMAN
01.01.2017, 17:51
bit 7,h ;8
ret z ;5 11
ex de,hl ;4
xor a ;4
ld l,a ;4
ld h,a ;4
sbc hl,de ;15
ret ;10
;19 54 оригинальная процедура
bit 7,h ;8
ret z ;5 11
ld a,h ;4
cpl ;4
ld h,a ;4
ld a,l ;4
cpl ;4
ld l,a ;4
inc hl ;6
ret ;10
;19 53
ld a,h ;4
cp $80 ;7 возможно +-$01
ret c ;5 11
cpl ;4
ld h,a ;4
ld a,l ;4
cpl ;4
ld l,a ;4
inc hl ;6
ret ;10
;22 52
- - - Добавлено - - -
XOR A
LD L,A
LD H,A
LD L,0
LD H,L
На такт быстрее.
LD HL,$0000 в таком случае на 2 такта быстрее;)
Не проверял. На вскидку так:
LD A,H ; 4
OR A ; 4
RET P ; 5 / 11
CPL ; 4
LD H,A ; 4
LD A,L ; 4
CPL ; 4
LD L,A ; 4
INC HL ; 6
RET ; 10
; 19 / 49
LD A,$FF ; 7
XOR H ; 4
RET M ; 5 / 11
LD H,A ; 4
LD A,L ; 4
CPL ; 4
LD L,A ; 4
INC HL ; 6
RET ; 10
; 22 / 48
NEO SPECTRUMAN
01.01.2017, 20:58
SGN можно запилить 100500-ю способами
;оригинальная процедура
LD A,L ;4
OR L ;4
RET Z ;5 11
BIT 7,L ;8
LD L,#0xFF ;7
RET NZ ;5 11
LD L,#1 ;7
RET ;10
;+=50 0=19 -=39
;36 в среднем ; 44,5 в среднем без 0
с ходу придумалось так
ld a,l ;4
rlca ;4 возможно rla (нужно чтоб флаг С не попадал в А)
jp c,l1 ;10 (7 12 JR)
or a ;4
ret z ;5 11
ld l,$01 ;7
ret ;10
l1
ld l,$FF ;7
ret ;10
;с использованием JP
;+=44 0=33 -=35
;37,3 в среднем ;39,5 в среднем без 0
;с использованием JR
;+=41 0=30 -=37
;36 в среднем ; 39 в среднем без 0
думаю можно и в 600 раз быстрее как минимум
кажется мне оптимизировать процедуру чтоб проверка на 0(1 против 255 других входящих значений) выполнялась быстрей всего нет смысла
правда я хз в какой ситуации применять sgn
- - - Добавлено - - -
вы и правда так кодите
мну *****кодер 80 уровня
Я только сегодня узнал что такое sgn:rolleyes:
глядя на код в самом верху:D
кто мне не дает так кодить?
- - - Добавлено - - -
MOAR SPEED!!!
rlc l ;8
ret z ;5 11
jp c,l1 ;10 (7 12 JR)
ld l,$01 ;7
ret ;10
l1
ld l,$FF ;7
ret ;10
;с использованием JP
;+=40 0=19 -=40
;33 в среднем ;40 в среднем без 0
;с использованием JR
;+=37 0=19 -=42
;32,6 в среднем ;39,5 в среднем без 0
АND MOAR!!!!
rlc l ;8
ret z ;5 11
ld l,$01 ;7 ;ld l,$FF
ret nc ;5 11 ;ret c
ld l,$FF ;7 ;ld l,$01
ret ;10
;-=31 0=19 +=42
;30,6 в среднем ;36,5 в среднем без 0
;легко реверсится в
;-=42 0=19 +=31 (если положительные числа встречаются чаще(а они наверное встречаются чаще))
- - - Добавлено - - -
;оригинальная процедура
BIT 7,L 8
RET Z 5 11
XOR A 4
SUB L 4
LD L,A 4
RET 10
;19 35
xor a ;4
sub l ;4
ret m ;5 11
ld l,a ;4
ret ;10
;19 27
;по ходу дает ложный результат при $00 и $80 перепроверьте кто нить!!!
Oleg N. Cher
02.01.2017, 01:33
А какой результат должно дать ABS($80)? Разве не $80? Просто у него нет симметричного положительного :-)
- - - Добавлено - - -
/*--------------------------------- Cut here ---------------------------------*/
signed char Basic_SGN (signed char x) __z88dk_fastcall { // Code by NEO SPECTRUMAN
__asm
RLC L ; 8
RET Z ; 5 11
LD L,#1 ; 7
RET NC ; 5 11
LD L,#0xFF ; 7
__endasm;
} //Basic_SGN
NEO SPECTRUMAN, зачётный код, респект! Я бы так не додумался. :-) Вот что значит опыт низкоуровневого кодинга. У меня он небольшой. Интересно, как бы Вы оптимизировали Laser2 :-)
;sgn
rlc l
ret z
sbc a,a
ld l,a
set 0,l
+
jr nc, -> 0..127
jr c, -> -128..-1
;sgn
+
jr nc, -> 0..127
jr c, -> -128..-1
Если переходы не нужны, то можно еще такт сэкономить:
rlc l
ret z
sbc a,a
or 1
ld l,a
Oleg N. Cher
02.01.2017, 06:37
Что значит "если переходы не нужны"? :-)
char предложил общий вариант, но если использовать только для функции, можно один такт выиграть, поменяв "set 0,l" на "or 1".
signed char Basic_SGN (signed char x) __z88dk_fastcall {
__asm
RLC L
RET Z
SBC A,A
OR 1
LD L,A
__endasm;
} //Basic_SGN
хотите линейную, и самую жесть? их есть у нас ->
ld a,l
rla
sbc a,a
sub l
adc a,l
ld l,a
Гениально! :v2_dizzy_roll:
хотите линейную, и самую жесть? их есть у нас ->
ld a,l
rla
sbc a,a3
sub l
adc a,l
ld l,a
Пиши демы)
Пиши демы)
как только, так... уже )
для себя вынес из темы "две новейших двадцатитактных команды", еще бы знать куда их теперь... )
;sgn c
ld a,c
rla
sbc a,a
sub c
adc a,c
;sgn c,a
ld c,a
rla
sbc a,a
sub c
adc a,c
как только, так... уже )
Как называются?
Oleg N. Cher
04.01.2017, 03:55
Titus, только доглядел. Это мега-код! :-) По сравнению с оригинальной процедурой:
signed int Basic_ABSI (signed int x) __z88dk_fastcall {
__asm
BIT 7,H ; 8
RET Z ; 11/5
EX DE,HL ; 4
XOR A ; 4
LD L,A ; 4
LD H,A ; 4
SBC HL,DE ; 15 => 44/19
__endasm;
} //Basic_ABSI
Получилось:
signed int Basic_ABSI (signed int x) __z88dk_fastcall {
__asm // Code by Titus
LD A,H ; 4
OR A ; 4
RET P ; 11/5
CPL ; 4
LD H,A ; 4
LD A,L ; 4
CPL ; 4
LD L,A ; 4
INC HL ; 6 => 39/19
__endasm;
} //Basic_ABSIТактов кушает меньше и не портит пару DE! А байтиков столько же!
В Basic.h добавляю ключик:
extern signed int Basic_ABSI (signed int x) __z88dk_fastcall __preserves_regs(b,c,d,e,iyl,iyh);- и оптимизатор точно знает, какие регистры сохраняет функция. И использует эту информацию, чтобы сделать код лучше.
- - - Добавлено - - -
Эх, всё-таки не зря открыл тему =) Благодарю!
Oleg N. Cher
10.01.2017, 04:14
На идеях char'а и SaNchez'а. SGN для байтов:
signed char Basic_SGN (signed char x) __z88dk_fastcall {
__asm // Code by char & SaNchez
RLC L
RET Z
SBC A
OR #1
LD L,A
__endasm;
} //Basic_SGNДля слов:
signed char Basic_SGNI (signed int x) __z88dk_fastcall {
__asm // Code by char & SaNchez
LD A,L
OR H
RET Z
RLC H
SBC A
OR #1
LD L,A
__endasm;
} //Basic_SGNI
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot