-1

I'm writing a program in assembly that is suppose to take the value of a key press, store it in a register and see what the value is.

I have managed to save 0x00000002 after pressing the key 2, into the register I wanted to save it in which is called "r1".

Now this is where I get lost. I'm now trying to compare this to some hexadecimals, so that I then can get know what the value is and use it in an other function. This is how my code looks like:

cmp r1, #0x30
beq savekey
cmp r1, #0x31
beq savekey
cmp r1, #0x32
beq savekey
cmp r1, #0x33
beq savekey
cmp r1, #0x34
beq savekey
cmp r1, #0x35
beq savekey
cmp r1, #0x36
beq savekey
cmp r1, #0x37
beq savekey
cmp r1, #0x38
beq savekey
cmp r1, #0x39
beq savekey

The expected result of this I thought would be that it would go in to the function "savekey" whenever it recognize that it was a number. However this never happens and it just skips all of them.

How could I do the comparison between the register and the hexadecimal different so it will work correctly? And is there any simpler way I can write this so I don't have to write a case for every single digit?

artless noise
  • 21,212
  • 6
  • 68
  • 105
  • instead of a series of `cmp`s like that, you should use a jump table. But if you just want to get 2 from 0x32 then just subtract 0x30 from it. And to check if a value is withing the range [0x30, 0x39] then [there's a nice trick that needs only a single comparison](https://stackoverflow.com/q/17095324/995714) – phuclv Feb 09 '19 at 15:18
  • ARM has bgt / blt for range checks: you don't need a chain of BEQ for contiguous values that all jump to the same place. – Peter Cordes Feb 09 '19 at 19:01

2 Answers2

1

I solved it through replacing for example #0x38 with #8. However I'm still wondering how to simplify the code.

  • Did you already `sub r1, #'0'`` to convert a digit from ASCII to integer? `#0x38` is the right syntax for decimal `56` = hex `0x38` as an immediate. – Peter Cordes Feb 09 '19 at 19:03
1

You can do a range check in assembler. In 'C' this would be something like, if(x >= '0' && x < ((int)'9')+1) savekey();. The equivalent ARM assembler would be like,

  cmp r1, 0x30
  blo bad_value
  cmp r1, 0x3A
  bhs bad_value
  b   save_key

You need to have a branch to the bad case unless you use a temporary register. The you can subtract the base (0x30), treat the temporary as unsigned and test for the higher case. Here is something like that,

 sub r2, r1, 0x30         @ low values will wrap to a high unsigned value
 cmp r2, 10               @ in range (0-9)?
 blo save_key
 ; bad/error handling here.

As others have noted, your ASCII value might already need this subtraction to convert to a binary or machine value.

artless noise
  • 21,212
  • 6
  • 68
  • 105
  • Note, the above is for converting ASCII decimal to binary. Note sure if the user input is decimal or hexidecimal. Also, you need to multiply/shift the converted single ASCII value to get a full binary value. – artless noise Feb 14 '19 at 15:07