我想比较两个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标志,并产生有趣的结果。
那么在8080上进行签名比较的惯用方式是什么?
实际上可以计算溢出标志,但确实很麻烦,因为它需要对操作数和结果都进行位运算,而我用光了寄存器。另外,这实际上并不是我想要的;我实际上并不关心溢出。我只想进行比较。
(如果结果为负,我不能简单地减去并分支,因为这在所有情况下都不起作用。考虑INT_MIN
答案 0 :(得分:3)
在8085上有两个undocumented flags K and V用于带符号的比较和带符号的溢出,以及用于跳过小于/大于的带符号的未记录的JK / JNK指令
不确定它们是否可用于8080。但是,如果他们不这样做,您可以通过切换最高位来convert a signed comparison to an unsigned one and vice versa
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
答案 1 :(得分:2)
考虑到已接受的答案及其评论,我将重新考虑Jester的建议(与拟议的Z80代码相比,在我看来,该建议仅+ 4B,但代码布局略有不同,即,较少/ greater_equal分支所在的位置,可能会使情况更加复杂)或简化您的代码...而且它的性能应该比每次对D和H都执行xor 0x80更好):
for (i in 1:length(cell_ranges)) {
a <- c()
for(sheet in sheet_names) {
a <- c(a, read_excel("file.xlsx", sheet = sheet,range=cell_ranges[i]))
assign(var_names[i], a)
}
}
您还可以通过以下方式将其修改为在DE 顺便说一句,您可以通过 但是正如我所质疑的那样,很多时候值得在体系结构级别上进行重新研究,以查看是否无法将整个代码逻辑转换为无符号0..FFFF操作模式,也许会导致调整( (由-32768表示)仅在一个/两个特定位置(例如向用户的最终输出)的“ _left”值,而其他许多内部比较/用法将以无符号方式工作。 编辑: 一些与常量进行比较的变体(对于一次性常量,最好将其加载到其他RP中并使用通用RP1与RP2比较(在大小上更好),尤其是当您有备用RP并且通用比较为已经为其他代码实例化了...但是对于相同常量的多次使用,这可能会同时赢得大小和速度方面的好处...内联赢得速度方面的好处?可以与子例程相提并论,取决于结果的使用方式)。 reg对(实际上也是8b reg)对零: 针对任何16b #XY常数的reg对: 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)
将CF = 0/1转换为A = 0 /〜0-有时sbb a
很方便进行进一步的计算... 0/255
; 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