Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何有效地在8080上进行签名比较?_Assembly_Comparison_Signed_Intel 8080 - Fatal编程技术网

Assembly 如何有效地在8080上进行签名比较?

Assembly 如何有效地在8080上进行签名比较?,assembly,comparison,signed,intel-8080,Assembly,Comparison,Signed,Intel 8080,我想比较两个16位数字并在结果上进行分支:相当于8085上的if(a有两个用于有符号比较和有符号溢出,以及用于在有符号小于/大于时跳转的未记录指令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

我想比较两个16位数字并在结果上进行分支:相当于8085上的if(a有两个用于有符号比较和有符号溢出,以及用于在有符号小于/大于时跳转的未记录指令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
mova,e
子a,l;e-l
mov a,h
xri a,0x80
mov h,a;h^=0x80
莫夫a,d
xri a,0x80;a=d^0x80
sbb a,h;d-h
jc lessthan;分公司结转
例
:lessthan
例

考虑到公认的答案及其评论,我会重新考虑杰斯特的建议(在我看来,与建议的Z80代码相比,这似乎仅为+4B,但代码布局有所不同,即更少/更大的_相等分支所在的位置,这可能会进一步复杂化或简化您的代码……此外,它应该比每次对D和H执行xor 0x80更好):

针对任何16b#XY常量的reg对:

; signed 16b compare RP (HL/DE/BC) vs nonzero constant #XY
; subroutine, returns CF=1 if RP < #XY, modifies A
    mov     a,R
    xri     0x80    ; convert 8000..7FFF into 0000..FFFF
    cpi     #X^0x80 ; "X" is xor-ed with 0x80 too to have it in 0000..FFFF range
    rnz             ; if ZF=0, then CF=1 is (RP < XY) and CF=0 is (RP > XY)
    ; R == X, the low 8b P vs Y will decide
    mov     a,P
    cpi     #Y      ; CF=1 if (RP < XY)
    ret             ; 10B for particular #XY constant and RP

; inlined form
    mov     a,R
    xri     0x80    ; convert 8000..7FFF into 0000..FFFF
    cpi     #X^0x80 ; "X" is xor-ed with 0x80 too to have it in 0000..FFFF range
    jnz     HiByteWasDecisive   ; if ZF=0, then CF is set correctly, done
    mov     a,P     ; R == #X, the low 8b P vs #Y will decide final CF
    cpi     #Y      ; CF=1 if (RP < #XY)
:HiByteWasDecisive
    ; CF=1 is (RP < #XY) and CF=0 is (RP >= #XY)
    ...
;符号16b比较RP(HL/DE/BC)与非零常数#XY
;子例程,如果RP<#XY修改了
莫夫a,R
xri 0x80;将8000..7FFF转换为0000..FFFF
cpi#X^0x80;“X”也与0x80异或,以使其在0000..FFFF范围内
rnz;如果ZF=0,则CF=1为(RPXY)
;R==X,低8b P vs Y将决定
莫夫a,P
cpi#Y;CF=1如果(RP=#XY)
...

如果所有其他操作都失败,您可以检查操作数是否具有相同的符号。如果没有,您已经知道哪个符号更大。如果是,那么使用减法是安全的。我可以快速看一眼,这也是
sdcc
生成的内容。改用无符号值如何?没有机会将其他代码中的所有内容偏移+0x8000并在0..ffff范围内操作?我是一个编译器后端。我无法决定int是否已签名!@DavidGiven这在技术上是不正确的。您正在为某种抽象机器(如C抽象机器)创建实现,只要实现“好像”使用有符号整数是正确的,即使实际实现是使用无符号本机类型。现在将其付诸实践可能与现代clang/gcc编译器使用自动矢量化/etc所做的类似(比如用压缩整数并行化替换循环中的朴素“int”)。也就是说,显然不值得为晦涩难懂的8b平台付出多少努力……所以你几乎是正确的。:)挑剔:小于的倒数是大于或等于,而不仅仅是“更大”。遗憾的是,8080上没有这些标志。但切换顶部看起来很容易,我会尝试一下(虽然我的寄存器有点用完了)。事实上,这是可行的——但每次比较都需要额外的8个字节[悲伤的脸]:
mov a,d;xri 0x80;mov d,a;mov a,h;xro 0x80;mov h,a
。当与常数进行比较时,我可以将xor滚动到立即值中,但由于
xri
重置进位标志,我无法按照您上面建议的方式内联执行(它会导致
sbb
出错)8080上的@PeterCordes
jp
是8086上的
jns
如同“跳转正/正”,那么就有“jm”如同“跳转负”…奇偶校验跳跃是
jpo/jpe
:但如果有8080汇编程序具有这些助记符的特定变体,我不会感到震惊,我不是8080人,但在Z80的世界中,甚至有一些命名(非官方)指令的冲突方式,如
sll
被一些汇编程序用作
sla
的别名(左移算术=左移逻辑),一些汇编程序会将
sll
汇编为非官方的
sl1/sli/sls/…
=shift left+b0=1。我的意思是,也许我使用的TXT使用的是非官方的助记符,
jns
它甚至是官方的8080,这就是为什么我在这里放了注释,解释我想到的是哪一个,它应该在SF=0时跳转(当SF=1时,
rm
ret
)。啊,谢谢,我误解了他们的意思。这些是一些令人困惑的助记符,特别是当Z80将奇偶校验标志重新定义为带符号溢出时,人们将其与符号标志一起使用以进行比较。@PeterCordes Z80实际上也将该标志用作奇偶校验,并且还用于第三个目的,我已经忘记了,它是signed overflow仅适用于特定的指令…:D…非常有趣;)(现在就开始玩弄ZX Spectrum,所以我最近遇到了所有这些Z80细微差别:))所以我现在有15个字节用于与寄存器进行比较,13个字节用于与常量进行比较;与助手例程进行比较时,与寄存器进行比较的字节数将为6个(3个用于例程,3个用于测试)和9个字节用于与常量进行比较(另外3个用于加载值)。但是如果必须将值强制到我目前没有的特定寄存器中,也会受到惩罚。我的意思是,这样更好,我也会这样做,但我希望有更多更好的。。。
    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
    ...
:SignedCmpDeHl
    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 (CF=0)
    rm                  ; return CF=0 when DE >= HL (H is negative)
    stc
    ret                 ; return CF=1 when DE < HL (H is positive/zero)
:sameSigns
    ; sign bits are equal, it is safe to do ordinary sub
    mov     a,e
    sub     l
    mov     a,d
    sbb     h
    ret                 ; return with CF=1 when DE < HL (CF=0 DE >= HL)
; signed compare 8b or 16b register vs 0, into SF, destroys A
    xra     a       ; A=0
    ora     R       ; 16b R=[HDB], or any 8b R: SF = (RP < 0 or R < 0)
    ...i.e. "jm hlIsLessThanZero"

; signed compare 8b or 16b register vs 0, into CF, destroys A
    mov     a,R     ; 16b R=[HDB], or any 8b R
    ral             ; CF = (RP < 0) or (R < 0)
    ...i.e. "jc hlIsLessThanZero" or "sbb a" to get 0/255
; signed 16b compare RP (HL/DE/BC) vs nonzero constant #XY
; subroutine, returns CF=1 if RP < #XY, modifies A
    mov     a,R
    xri     0x80    ; convert 8000..7FFF into 0000..FFFF
    cpi     #X^0x80 ; "X" is xor-ed with 0x80 too to have it in 0000..FFFF range
    rnz             ; if ZF=0, then CF=1 is (RP < XY) and CF=0 is (RP > XY)
    ; R == X, the low 8b P vs Y will decide
    mov     a,P
    cpi     #Y      ; CF=1 if (RP < XY)
    ret             ; 10B for particular #XY constant and RP

; inlined form
    mov     a,R
    xri     0x80    ; convert 8000..7FFF into 0000..FFFF
    cpi     #X^0x80 ; "X" is xor-ed with 0x80 too to have it in 0000..FFFF range
    jnz     HiByteWasDecisive   ; if ZF=0, then CF is set correctly, done
    mov     a,P     ; R == #X, the low 8b P vs #Y will decide final CF
    cpi     #Y      ; CF=1 if (RP < #XY)
:HiByteWasDecisive
    ; CF=1 is (RP < #XY) and CF=0 is (RP >= #XY)
    ...