Как мне эффективно делать подписанные сравнения на 8080? - PullRequest
0 голосов
/ 12 февраля 2019

Я хочу сравнить два 16-битных числа и ответвление по результату: эквивалент if (a<b) goto negative.Я использую Intel 8080.

Z80 имеет подписанный арифметический флаг переполнения, который можно использовать для этого с некоторой степенью усилия.Стандартный код:

ld de, _left
ld hl, _right
ld a, e
sub a, l
ld a, d
sbc a, h
jp po, $+5  ; branch on overflow flag not set
xor a, 0x80 ; flip sign bit
jm negative ; actually do the test

Но 8080 не является строгим подмножеством Z80, и приведенный выше код не будет работать там - на 8080 арифметические инструкции устанавливают флаг P на основепо соотношению результата с веселыми результатамибитовые операции с обоими операндами и результатом, и у меня заканчиваются регистры.Кроме того, это на самом деле не то, что я хочу здесь;Я на самом деле не забочусь о переполнении.Я просто хочу сделать сравнение.

(Я не могу просто вычесть и разветвить, если результат отрицательный, потому что это не работает во всех случаях. Рассмотрим INT_MIN

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Учитывая принятый ответ и его комментарии, я бы пересмотрел совет Джестера (который мне кажется только + 4B по сравнению с предложенным кодом Z80, но с несколько иной компоновкой кода, то есть там, где находятся ветви поменьше / большее_эквивалентные, что может еще более усложнить)или упростите ваш код ... плюс он должен работать лучше, чем делать xor 0x80 каждый раз для D и H):

    mov     a,d
    xra     h
    jp      sameSigns   ; as "JNS" in 8086 / "jp p," in Z80
    ; sign bits are different, signed overflow may happen
    ; but if H positive, then DE is less than HL
    xra     d           ; make A=H and set sign flag
    jm      DeIsGreaterEqualThanHl
:DeIsLessThanHl
    ; DE < HL
    ...

:sameSigns
    ; sign bits are equal, it is safe to do ordinary sub
    mov     a,e
    sub     l
    mov     a,d
    sbb     h
    jc      DeIsLessThanHl
:DeIsGreaterEqualThanHl
    ; DE >= HL
    ...

Вы также можете изменить его как процедуру, которая возвращает CF = 1, когда DE

0 голосов
/ 12 февраля 2019

На 8085 есть два недокументированных флага K и V для сравнения со знаком и переполнения со знаком, наряду с недокументированными инструкциями JK / JNK для перехода по знаку, меньшему / большему

Не уверен, доступны ли они на 8080 или нет.Но если они этого не делают, вы можете преобразовать сравнение со знаком в беззнаковое и наоборот , переключая верхний бит

bool signedCmp(int a, int b)
{
    return unsignedCmp(a ^ INT_MIN, b ^ INT_MIN);
}

Я не знаю, сборка 8080, но, возможно, что-то вродеэто можно использовать для сравнения DE и HL

mov a, e
sub a, l     ; e - l
mov a, h
xri a, 0x80
mov h, a     ; h ^= 0x80
mov a, d
xri a, 0x80  ; a = d ^ 0x80
sbb a, h     ; d - h
jc lessthan  ; branch on carry
    ; >= case
:lessthan
    ; < case
...