0

I have this RLE exercise in assembly to count elements of an array and I am encountering a strange problem I cannot understand. In label RegisterOccurrence, I increment BL for the second time and compare it to 255 cause this is the max value of an unsigned char in case there are more elements in the array. Now the problem is that in this case when CMP BL,255 is done BL will be 2 and 2 is lower than 255 still the program jumps to AdjustValue


    __asm
    {
        XOR EAX, EAX
        XOR EBX, EBX
        XOR ECX, ECX
        XOR EDX, EDX
        XOR EDI, EDI
        XOR ESI, ESI

        MOV EAX, Len                     

//---------------------------------------------------------------------------------------------------------------------


Loop:
           CMP ESI,EAX
           JE EndProgram
           MOV DL,[Buffer+ESI]
           MOV CL,[Buffer+ESI+1]
           CMP DL,CL
           JE Occurrence
           JNE SingleNumber
           INC ESI
           JMP Loop
//----------------------------------------------------------------------------------------------------------------------



SingleNumber:
           MOV BufComp[EDI],1
           MOV BufComp[EDI+1],DL
           INC ESI
           ADD EDI,2
           JMP Loop

//----------------------------------------------------------------------------------------------------------------

Occurrence:
           INC BL
           INC ESI
           MOV DL, [Buffer + ESI]
           MOV CL, [Buffer + ESI + 1]
           CMP DL,CL
           JNE RegisterOccurrence
           JMP Loop

//---------------------------------------------------------------------------------------------------------------

RegisterOccurrence:
           INC BL
           CMP BL,255
           JG AdjustValue 
           MOV BufComp[EDI],BL
           MOV BufComp[EDI+1],DL
           INC ESI
           ADD EDI,2
           XOR EBX,EBX
           JMP Loop

//-------------------------------------------------------------------------------------------------------------------


AdjustValue:
           SUB BL,255
           MOV BufComp[EDI],255
           MOV BufComp[EDI+1],DL
           ADD EDI,2
           MOV BufComp[EDI],BL
           MOV BufComp[EDI+1],DL
           INC ESI
           ADD EDI,2
           XOR EBX,EBX
           JMP Loop

//----------------------------------------------------------------------------------------------------------------------


EndProgram:
           
           MOV BufComp[EDI],0d
    }

//PRINT VALUES PART
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • There's a bunch of stuff here that doesn't make sense. Like `INC ESI` after `je`/`jne` can never be reached, because one or the other of those branches will have been taken. Looks like you could just simplify to `je Occurrence` otherwise fall through to `SingleNumber`. And the thing you asked about, `bl > 255`, can never be true for `uint8_t bl`. Instead you probably want to just detect carry-out from `add bl, 1`. – Peter Cordes May 21 '21 at 20:15
  • Or you could test for zero after the fact, since that's what you get from wraparound. – Peter Cordes May 21 '21 at 20:24
  • BTW, I wondered how much more efficiently run-length encoding could be written in asm. https://godbolt.org/z/W76ocTcaz is untested NASM. That's unlikely to be optimal, especially for inputs where long runs are frequent, but it's *much* more compact, and keeps the current-run byte in a register instead of doing 2 loads for every inc esi. – Peter Cordes May 21 '21 at 21:17

1 Answers1

2

The instruction JG is for comparision of signed integers. A 8-bit value 255 means -1 in two's complement and the jump is taken because 2 is larger than -1.

You should use JA to compare unsigned integers and jump in greater case.

Reference: Intel x86 JUMP quick reference

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • @EverythingPro: You might want `add bl, 1` and use `jc` to branch if it wrapped around. (`cmp bl, 255` / `ja` can never be take because no uint8_t can be above 255). (inc leaves CF unmodified.) – Peter Cordes May 21 '21 at 20:12