cassemblyarmarmv6

Clarity About TST Instruction - ARM Assembly


So here I have the following code (ARMv6 assembly):

wait$: 
    ldr r2,[r0,#24] //read 32 bits from addr + 24 in r0 and store in r2
    tst r2,#0x80000000 //????
    bne wait$

I understand all of the lines other than the tst instruction. I have done some research online and the best definition I could find was:

Test if a register is zero or minus. Perform a logical AND between a register and itself.

I had some trouble understanding what it meant so I then tried to make the C equivalent to an tst instruction and this is what I got:

if(valRead & 0x80000000 != 0){} 

The code above does not seems to be working. What is an easier to understand definition of tst and what is the equivalent to it in C?


Solution

  • What is an easier to understand definition of tst and what is the equivalent to it in C?

    Some background

    There is no equivalent in C because higher-level languages work differently than a CPU with "status registers" (such as ARM or x86):

    In high-level languages like C or C++, conditional code execution can be done directly:

    if(a < b) ...
    

    On a CPU with a "status register", conditional code execution is done in two steps:

    A simplified example:

    The operation if(a < b) ... could be performed the following way on a CPU with a "status register":

    /* Subtract b from a */
    c = a - b;
    /* (a < b) means that (a - b) is negative */
    if(status.last_result_was_negative) ...
    

    ... however, the result of the operation (c in the example) is not needed.

    The TST and CMP instructions

    To perform an if(...) operation, two operations are often needed:

    ... and in both cases, the result of the operation (the difference or the result of the AND operation) is not needed.

    For this reason, there are two instructions (CMP and TST) that perform an operation (CMP performs a subtraction and TST performs an AND operation) but discard the result:

    The TST operation performs an AND operation, sets the information in the "status register" according to the result but it discards the actual result.

    This makes sense in lines like if(a & 0xF000) ... where you are only interested in that the "status register" holds the information if the result of the operation a & 0xF000 was zero or not, but you are not interested in the actual result of a & 0xF000.

    if(valRead & 0x80000000 != 0){} 
    

    You need brackets:

    if((valRead & 0x80000000) != 0){} 
    

    Otherwise the compiler understands:

    if(valRead & (0x80000000 != 0)){} 
    

    ... which is the same as:

    if((valRead & 1) != 0){}