-1

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?

Packa
  • 173
  • 14
  • This clarify your question? https://stackoverflow.com/questions/54131662/whats-the-difference-between-the-cmp-and-tst-instructions-in-arm – Frankie_C Oct 02 '21 at 08:28
  • @Frankie_C pretty much the same definition as the one I have got – Packa Oct 02 '21 at 08:30
  • 1
    TST doesn't **perform a logical AND between a register and itself**, but with the second operand and sets the zero flag accordingly with result. The and with itself is used to check for zero result. The C definition is valid, even removing the `!=0` part. If it doesn't work for you check if `ValRead` is the same as `ldr r2,[r0,#24]`. – Frankie_C Oct 02 '21 at 08:38
  • `volatile int *ptr = /*whatever is in r0*/; while (ptr[6] < 0);` – EOF Oct 02 '21 at 08:42
  • 3
    The C code doesn't work because your parentheses are wrong. `!=` binds tighter than `&` in C. You need to write `if ((valRead & 0x80000000) != 0)` or just `if (valRead & 0x80000000)` for this to work. – fuz Oct 02 '21 at 09:53
  • while((*u32ptr)<0) continue; – old_timer Oct 03 '21 at 02:44
  • while(((*u32ptr)&0x80000000)!=0) continue; – old_timer Oct 03 '21 at 02:45
  • it is not an if it is a while – old_timer Oct 03 '21 at 02:45
  • arm has quite clearly documented this instruction. – old_timer Oct 03 '21 at 02:47

1 Answers1

3

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:

  • In the first step, you perform some calculation (such as a-b).
    In the so-called "status register" the CPU stores some "relevant" information (e.g. the sign) about the result.
  • In the second step, the actual conditional code execution is done.
    This can only be done depending on the information in the "status register".

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:

  • A subtraction:
    it is needed for ==, <, >, <=, >= and !=.
  • An AND operation:
    it is needed to check if some bit(s) in a value is (are) set:
    if(a & 0x8000) ...

... 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){} 
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38