Этот вопрос был задан на гф, на который предложено решение:
;A=A mod 7
ld c,a
xor a
ld b,#08
label2 rl c
adc a,a
sbc a,7
jr nc,label1
add a,7
label1 djnz label2
ld c,a
xor a
ld b,#08
label2 rl c
adc a,a
sbc a,7
jr nc,label1
add a,7
label1 djnz label2
Я решил написать по-другому, потому что видел похожий способ:
ORG #6000
start
ld b,0
; jr $
tt:
ld a,b
call pr10
ld a,":"
rst 16
;*36
ld l,b
ld h,0
ld d,h
ld e,l
add hl,hl ; *2
add hl,hl ; *4
add hl,hl ; *8
add hl,de ; *9
add hl,hl ; *18
add hl,hl ; 36
ld a,h
add a,a
add a,h
add a,a
add a,h
sub b
neg
cp 7
jr nz,skp
xor a
skp:
call pr10
ld a,6
rst 16
inc b
bit 4,b
jr z,tt
jr $
pr10
push bc
ld c,a
ld b,0
call $1A1B; print num in BC(0-9999),1a28-out-num-2
pop bc
ret
;end
end start
start
ld b,0
; jr $
tt:
ld a,b
call pr10
ld a,":"
rst 16
;*36
ld l,b
ld h,0
ld d,h
ld e,l
add hl,hl ; *2
add hl,hl ; *4
add hl,hl ; *8
add hl,de ; *9
add hl,hl ; *18
add hl,hl ; 36
ld a,h
add a,a
add a,h
add a,a
add a,h
sub b
neg
cp 7
jr nz,skp
xor a
skp:
call pr10
ld a,6
rst 16
inc b
bit 4,b
jr z,tt
jr $
pr10
push bc
ld c,a
ld b,0
call $1A1B; print num in BC(0-9999),1a28-out-num-2
pop bc
ret
;end
end start
И вроде все правильно, и четко, но с делением 255 этот код не проходит. Переписал код под 16-бит, та же фигня.Вспомнил про трэд, в котором есть примеры деления на 6502, и попробовал перевести на Z80 - ошибка. Сегодня посмотрел на код, исправил, и деление работает:
org $6000
start
ld b,0
tt
ld a,b
call pr10
ld a,":"
rst 16
ld a,b
;https://forums.nesdev.org/viewtopic.php?f=2&t=11336
;Divide by 7 (From December '84 Apple Assembly Line)
;15 bytes, 27 cycles
; sta temp
ld c,a
; lsr
srl a ;0->A->C
; lsr
srl a
; lsr
srl a
; adc temp
adc a,c
; ror ->C->A->C
rr a
; lsr
srl a
; lsr
srl a
; adc temp
adc a,c
; ror
rr a
; lsr
srl a
; lsr
srl a
;
ld c,a
add a,a
add a,a
add a,a
sub c
sub b
neg
call pr10
ld a,6
rst 16
inc b
bit 4,b
jr z,tt
jr $
pr10
push bc
ld c,a
ld b,0
call $1A1B; num in bc,1a28-out-num-2
pop bc
ret
end start
start
ld b,0
tt
ld a,b
call pr10
ld a,":"
rst 16
ld a,b
;https://forums.nesdev.org/viewtopic.php?f=2&t=11336
;Divide by 7 (From December '84 Apple Assembly Line)
;15 bytes, 27 cycles
; sta temp
ld c,a
; lsr
srl a ;0->A->C
; lsr
srl a
; lsr
srl a
; adc temp
adc a,c
; ror ->C->A->C
rr a
; lsr
srl a
; lsr
srl a
; adc temp
adc a,c
; ror
rr a
; lsr
srl a
; lsr
srl a
;
ld c,a
add a,a
add a,a
add a,a
sub c
sub b
neg
call pr10
ld a,6
rst 16
inc b
bit 4,b
jr z,tt
jr $
pr10
push bc
ld c,a
ld b,0
call $1A1B; num in bc,1a28-out-num-2
pop bc
ret
end start
И это работает. Гугл подсказал еще один способ:
; Z80 assembly to compute 'x mod 7' from 'x' and 'x div 7'
; 'x' in HL
; 'x div 7' in DE
LD A, E ; 4T 1B -- A := x div 7 [low bits]
ADD A, A ; 4T 1B -- A := (x div 7) * 2 [low bits]
ADD A, A ; 4T 1B -- A := (x div 7) * 4 [low bits]
ADD A, A ; 4T 1B -- A := (x div 7) * 8 [low bits]
SUB E ; 4T 1B -- A := (x div 7) * 7 [low bits]
NEG ; 8T 2B -- A := (x div 7) * -7 [low bits]
ADD A, L ; 4T 1B -- A := x mod 7
; 'x mod 7' in A
; 'x' in HL
; 'x div 7' in DE
LD A, E ; 4T 1B -- A := x div 7 [low bits]
ADD A, A ; 4T 1B -- A := (x div 7) * 2 [low bits]
ADD A, A ; 4T 1B -- A := (x div 7) * 4 [low bits]
ADD A, A ; 4T 1B -- A := (x div 7) * 8 [low bits]
SUB E ; 4T 1B -- A := (x div 7) * 7 [low bits]
NEG ; 8T 2B -- A := (x div 7) * -7 [low bits]
ADD A, L ; 4T 1B -- A := x mod 7
; 'x mod 7' in A
Но и на этом я не остановился, нашел еще один метод, но для 10, а не 7:
A_mod_10:
This is not a typical method used, but it is small and fast at 196 to 201 t-states, 12 bytes
ld bc,05A0h
Loop:
sub c
jr nc,$+3
add a,c
srl c
djnz Loop
ret
Комментарии
Отправить комментарий