这段汇编代码中的进位标志是如何设置的?

And*_*ong 1 c random assembly carryflag 65816

给定以下 16 位 PRNG 函数的汇编代码,

$80/8111 E2 20       SEP #$20   ; set 8-bit mode accumulator
$80/8113 AD E5 05    LDA $05E5  ; load low byte of last random number
$80/8116 8D 02 42    STA $4202
$80/8119 A9 05       LDA #$05   ; multiply it by 5
$80/811B 8D 03 42    STA $4203
$80/811E EA          NOP
$80/811F C2 20       REP #$20   ; set 16-bit mode accumulator
$80/8121 AD 16 42    LDA $4216  ; load the resultant product
$80/8124 48          PHA        ; push it onto the stack
$80/8125 E2 20       SEP #$20   ; 8-bit
$80/8127 AD E6 05    LDA $05E6  ; load high byte of last random number
$80/812A 8D 02 42    STA $4202
$80/812D A9 05       LDA #$05   ; multiply by 5
$80/812F 8D 03 42    STA $4203
$80/8132 EB          XBA        ; exchange high and low bytes of accumulator
$80/8133 EA          NOP
$80/8134 AD 16 42    LDA $4216  ; load low byte of product
$80/8137 38          SEC
$80/8138 63 02       ADC $02,s  ; add to it the high byte of the original product
$80/813A 83 02       STA $02,s  ; save it to the high byte of the original product
$80/813C C2 20       REP #$20   ; 16-bit
$80/813E 68          PLA        ; pull it from the stack
$80/813F 69 11 00    ADC #$0011 ; add 11
$80/8142 8D E5 05    STA $05E5  ; save as new random number
$80/8145 6B          RTL
Run Code Online (Sandbox Code Playgroud)

一位名为 @sagara 的用户将代码翻译为 C:

$80/8111 E2 20       SEP #$20   ; set 8-bit mode accumulator
$80/8113 AD E5 05    LDA $05E5  ; load low byte of last random number
$80/8116 8D 02 42    STA $4202
$80/8119 A9 05       LDA #$05   ; multiply it by 5
$80/811B 8D 03 42    STA $4203
$80/811E EA          NOP
$80/811F C2 20       REP #$20   ; set 16-bit mode accumulator
$80/8121 AD 16 42    LDA $4216  ; load the resultant product
$80/8124 48          PHA        ; push it onto the stack
$80/8125 E2 20       SEP #$20   ; 8-bit
$80/8127 AD E6 05    LDA $05E6  ; load high byte of last random number
$80/812A 8D 02 42    STA $4202
$80/812D A9 05       LDA #$05   ; multiply by 5
$80/812F 8D 03 42    STA $4203
$80/8132 EB          XBA        ; exchange high and low bytes of accumulator
$80/8133 EA          NOP
$80/8134 AD 16 42    LDA $4216  ; load low byte of product
$80/8137 38          SEC
$80/8138 63 02       ADC $02,s  ; add to it the high byte of the original product
$80/813A 83 02       STA $02,s  ; save it to the high byte of the original product
$80/813C C2 20       REP #$20   ; 16-bit
$80/813E 68          PLA        ; pull it from the stack
$80/813F 69 11 00    ADC #$0011 ; add 11
$80/8142 8D E5 05    STA $05E5  ; save as new random number
$80/8145 6B          RTL
Run Code Online (Sandbox Code Playgroud)

我对两件事感到困惑。

  1. 在这一行...

    uint16_t v1    = LOW(mul_high) + HIGH(mul_low) + 1;
    
    Run Code Online (Sandbox Code Playgroud)

    为什么会有一个+ 1?我认为是因为ADC操作的原因,但是我们如何确定进位标志设置为1呢?之前的什么操作可以保证这一点?这XBC?我读了一些帖子,例如Assembly ADC (Add with Carry) to C++和Overflow and Carry flags on Z80,但我不清楚,因为指令集似乎不同,我不熟悉65C816 汇编。(这是一款 1994 年流行的 SNES 游戏,其 NA 发行周年纪念日刚刚过去;对正确的猜测免费投票:-)

  2. 在下一行...

    uint8_t  carry = HIGH(v1) ? 1 : 0;
    
    Run Code Online (Sandbox Code Playgroud)

    为什么会这样呢?我将其读为“当且仅当高字节非零时设置进位标志”。但是,难道只有高字节为零时才表明溢出吗?(我可能误解了这条线的作用。)

预先感谢您的任何见解。

Mic*_*ael 5

  1. 但是我们如何确定进位标志设置为1呢?之前的什么操作可以保证这一点?
$80/8137 38          SEC   ; SEt Carry flag
Run Code Online (Sandbox Code Playgroud)
  1. uint8_t carry = HIGH(v1) ? 1 : 0;
    为什么会这样呢?我将其读为“当且仅当高字节非零时设置进位标志”。但是,难道只有高字节为零时才表明溢出吗?

加法ADC #$0011是使用来自 的进位ADC $02,s。当ADC $02,s执行时,累加器被设置为 8 位(因为SEP #$20),因此如果 的结果ADC $02,s超过 8 位(即,如果您在 16 位中得到了 >= $100 的东西,则进位标志将被设置模式)。
在 C 版本中,您有一个 16 位变量 ( v1) 来保存结果,因此您的进位将位于 的第 8 位中v1,您可以使用 进行测试HIGH(v1) == 1,或者只是HIGH(v1)因为它将是 1 或 0。