Converting integer to hex string in ARM Assembly





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I am trying to figure out how to convert a 32 bit integer into its hex representation. I know that I need to separate the last 4 bits, use a switch case to find which hex character it corresponds to. And then I need to repeat this for each of the 4 bits. I am struggling to find out how to get each of the 4 bits from LSB to MSB. Can anyone help? Thanks!










share|improve this question























  • Can you call printf?

    – Fiddling Bits
    Nov 20 '18 at 20:19











  • No, I want to implement it on my own, I would only like to use putchar()

    – user9615667
    Nov 20 '18 at 20:20













  • Just mask out all but 4 bits (use an AND instruction). Then shift by 4 bits and repeat...

    – Paul R
    Nov 20 '18 at 20:23











  • don't know why i didn't think of shifting. thanks.

    – user9615667
    Nov 20 '18 at 20:27


















0















I am trying to figure out how to convert a 32 bit integer into its hex representation. I know that I need to separate the last 4 bits, use a switch case to find which hex character it corresponds to. And then I need to repeat this for each of the 4 bits. I am struggling to find out how to get each of the 4 bits from LSB to MSB. Can anyone help? Thanks!










share|improve this question























  • Can you call printf?

    – Fiddling Bits
    Nov 20 '18 at 20:19











  • No, I want to implement it on my own, I would only like to use putchar()

    – user9615667
    Nov 20 '18 at 20:20













  • Just mask out all but 4 bits (use an AND instruction). Then shift by 4 bits and repeat...

    – Paul R
    Nov 20 '18 at 20:23











  • don't know why i didn't think of shifting. thanks.

    – user9615667
    Nov 20 '18 at 20:27














0












0








0








I am trying to figure out how to convert a 32 bit integer into its hex representation. I know that I need to separate the last 4 bits, use a switch case to find which hex character it corresponds to. And then I need to repeat this for each of the 4 bits. I am struggling to find out how to get each of the 4 bits from LSB to MSB. Can anyone help? Thanks!










share|improve this question














I am trying to figure out how to convert a 32 bit integer into its hex representation. I know that I need to separate the last 4 bits, use a switch case to find which hex character it corresponds to. And then I need to repeat this for each of the 4 bits. I am struggling to find out how to get each of the 4 bits from LSB to MSB. Can anyone help? Thanks!







assembly arm






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 20 '18 at 20:16







user9615667




















  • Can you call printf?

    – Fiddling Bits
    Nov 20 '18 at 20:19











  • No, I want to implement it on my own, I would only like to use putchar()

    – user9615667
    Nov 20 '18 at 20:20













  • Just mask out all but 4 bits (use an AND instruction). Then shift by 4 bits and repeat...

    – Paul R
    Nov 20 '18 at 20:23











  • don't know why i didn't think of shifting. thanks.

    – user9615667
    Nov 20 '18 at 20:27



















  • Can you call printf?

    – Fiddling Bits
    Nov 20 '18 at 20:19











  • No, I want to implement it on my own, I would only like to use putchar()

    – user9615667
    Nov 20 '18 at 20:20













  • Just mask out all but 4 bits (use an AND instruction). Then shift by 4 bits and repeat...

    – Paul R
    Nov 20 '18 at 20:23











  • don't know why i didn't think of shifting. thanks.

    – user9615667
    Nov 20 '18 at 20:27

















Can you call printf?

– Fiddling Bits
Nov 20 '18 at 20:19





Can you call printf?

– Fiddling Bits
Nov 20 '18 at 20:19













No, I want to implement it on my own, I would only like to use putchar()

– user9615667
Nov 20 '18 at 20:20







No, I want to implement it on my own, I would only like to use putchar()

– user9615667
Nov 20 '18 at 20:20















Just mask out all but 4 bits (use an AND instruction). Then shift by 4 bits and repeat...

– Paul R
Nov 20 '18 at 20:23





Just mask out all but 4 bits (use an AND instruction). Then shift by 4 bits and repeat...

– Paul R
Nov 20 '18 at 20:23













don't know why i didn't think of shifting. thanks.

– user9615667
Nov 20 '18 at 20:27





don't know why i didn't think of shifting. thanks.

– user9615667
Nov 20 '18 at 20:27












1 Answer
1






active

oldest

votes


















1














Masking and shifting, as suggested in the comments and in your answer, will get you the individual nibbles (half-bytes) that make up the word. But to print the number using putchar or equivalent, you'll need to convert these nibbles to ASCII characters. You don't need a 'switch-case' for this (or rather its equivalent in assembly language, a 'jump table'). You could use a lookup table, given that there will only be 16 entries, or you could conditionally add to the nibble to form a character.



The ASCII digits 0-9 have character codes 48-57. The uppercase letters have character codes starting at 65 for A (the lowercase letters start from 97) and of course 0xA represents the decimal value 10. So you can turn a nibble into a hex string by adding 55 to it if its value is 10 or more, and 48 otherwise. (Equivalently, add 48 unconditionally and add a further 7 to it if the resulting value is 58 or more.)



Note also that shifting right, as you suggest in your answer, will extract digits starting with the least-significant nibble, which is not what you want.



The following is untested and written off the top of my head, so no warranty, but it might set you on the right track:



    ; Assume number to be converted is in r4.  Note r4 is clobbered

; Initialise loop counter
MOV r5, #8
.loop
; Take most significant nibble from r4 into r0
MOV r0, r4, LSR #28

; Shift r4 for next time
MOV r4, r4, LSL #4

; For each nibble (now in r0) convert to ASCII and print
ADD r0, r0, #48
CMP r0, #58 ; did that exceed ASCII '9'?
ADDHS r0, r0, #7 ; add 'A' - ('0'+10) if needed
BL putchar

; Decrement loop counter, loop if not zero
SUBS r5, r5, #1
BNZ .loop





share|improve this answer


























  • For bases that aren't powers of 2, you don't really get a choice about starting from the LSD with repeated division. The usual way to deal with this is to start at the end of a buffer and decrement a pointer. When you're done, print from the current position. (example in C and x86 asm here: How do I print an integer in Assembly Level Programming without printf from the c library?). But yeah, given the choice, starting with the high nibble is easiest.

    – Peter Cordes
    Nov 20 '18 at 23:49













  • You don't need to AND before right shifting. Your 0xFF000000 mask keeps the high byte (2 nibbles = 2 hex digits = 2 Fs). But then right-shifting by 28 keeps only the high one. The AND was useless. :/ I think you can optimize down to add r0, r6, r4 LSR #28, if you have '0' in r6. I don't think ARM can barrel-shift a register in an instruction with an immediate. Or if you rotate r4 with mov r4, r4, ROL #4, you can and r0, r4, #0xF to use only 1 shift. And BTW, it would be clearer to use character literals like add r0,r0, #'0', if that's the right syntax.

    – Peter Cordes
    Nov 20 '18 at 23:52













  • Thanks - corrected. The 0xFF000000 was a typo, and the unnecessary AND was an oversight. :-) Not sure about the syntax for character literals so I didn't include them - didn't have the time to test! Agreed that there may be optimisations, but I wanted my code to be clear and to demonstrate the principles rather than to be optimal in any sense.

    – cooperised
    Nov 21 '18 at 12:50














Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53400875%2fconverting-integer-to-hex-string-in-arm-assembly%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown
























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














Masking and shifting, as suggested in the comments and in your answer, will get you the individual nibbles (half-bytes) that make up the word. But to print the number using putchar or equivalent, you'll need to convert these nibbles to ASCII characters. You don't need a 'switch-case' for this (or rather its equivalent in assembly language, a 'jump table'). You could use a lookup table, given that there will only be 16 entries, or you could conditionally add to the nibble to form a character.



The ASCII digits 0-9 have character codes 48-57. The uppercase letters have character codes starting at 65 for A (the lowercase letters start from 97) and of course 0xA represents the decimal value 10. So you can turn a nibble into a hex string by adding 55 to it if its value is 10 or more, and 48 otherwise. (Equivalently, add 48 unconditionally and add a further 7 to it if the resulting value is 58 or more.)



Note also that shifting right, as you suggest in your answer, will extract digits starting with the least-significant nibble, which is not what you want.



The following is untested and written off the top of my head, so no warranty, but it might set you on the right track:



    ; Assume number to be converted is in r4.  Note r4 is clobbered

; Initialise loop counter
MOV r5, #8
.loop
; Take most significant nibble from r4 into r0
MOV r0, r4, LSR #28

; Shift r4 for next time
MOV r4, r4, LSL #4

; For each nibble (now in r0) convert to ASCII and print
ADD r0, r0, #48
CMP r0, #58 ; did that exceed ASCII '9'?
ADDHS r0, r0, #7 ; add 'A' - ('0'+10) if needed
BL putchar

; Decrement loop counter, loop if not zero
SUBS r5, r5, #1
BNZ .loop





share|improve this answer


























  • For bases that aren't powers of 2, you don't really get a choice about starting from the LSD with repeated division. The usual way to deal with this is to start at the end of a buffer and decrement a pointer. When you're done, print from the current position. (example in C and x86 asm here: How do I print an integer in Assembly Level Programming without printf from the c library?). But yeah, given the choice, starting with the high nibble is easiest.

    – Peter Cordes
    Nov 20 '18 at 23:49













  • You don't need to AND before right shifting. Your 0xFF000000 mask keeps the high byte (2 nibbles = 2 hex digits = 2 Fs). But then right-shifting by 28 keeps only the high one. The AND was useless. :/ I think you can optimize down to add r0, r6, r4 LSR #28, if you have '0' in r6. I don't think ARM can barrel-shift a register in an instruction with an immediate. Or if you rotate r4 with mov r4, r4, ROL #4, you can and r0, r4, #0xF to use only 1 shift. And BTW, it would be clearer to use character literals like add r0,r0, #'0', if that's the right syntax.

    – Peter Cordes
    Nov 20 '18 at 23:52













  • Thanks - corrected. The 0xFF000000 was a typo, and the unnecessary AND was an oversight. :-) Not sure about the syntax for character literals so I didn't include them - didn't have the time to test! Agreed that there may be optimisations, but I wanted my code to be clear and to demonstrate the principles rather than to be optimal in any sense.

    – cooperised
    Nov 21 '18 at 12:50


















1














Masking and shifting, as suggested in the comments and in your answer, will get you the individual nibbles (half-bytes) that make up the word. But to print the number using putchar or equivalent, you'll need to convert these nibbles to ASCII characters. You don't need a 'switch-case' for this (or rather its equivalent in assembly language, a 'jump table'). You could use a lookup table, given that there will only be 16 entries, or you could conditionally add to the nibble to form a character.



The ASCII digits 0-9 have character codes 48-57. The uppercase letters have character codes starting at 65 for A (the lowercase letters start from 97) and of course 0xA represents the decimal value 10. So you can turn a nibble into a hex string by adding 55 to it if its value is 10 or more, and 48 otherwise. (Equivalently, add 48 unconditionally and add a further 7 to it if the resulting value is 58 or more.)



Note also that shifting right, as you suggest in your answer, will extract digits starting with the least-significant nibble, which is not what you want.



The following is untested and written off the top of my head, so no warranty, but it might set you on the right track:



    ; Assume number to be converted is in r4.  Note r4 is clobbered

; Initialise loop counter
MOV r5, #8
.loop
; Take most significant nibble from r4 into r0
MOV r0, r4, LSR #28

; Shift r4 for next time
MOV r4, r4, LSL #4

; For each nibble (now in r0) convert to ASCII and print
ADD r0, r0, #48
CMP r0, #58 ; did that exceed ASCII '9'?
ADDHS r0, r0, #7 ; add 'A' - ('0'+10) if needed
BL putchar

; Decrement loop counter, loop if not zero
SUBS r5, r5, #1
BNZ .loop





share|improve this answer


























  • For bases that aren't powers of 2, you don't really get a choice about starting from the LSD with repeated division. The usual way to deal with this is to start at the end of a buffer and decrement a pointer. When you're done, print from the current position. (example in C and x86 asm here: How do I print an integer in Assembly Level Programming without printf from the c library?). But yeah, given the choice, starting with the high nibble is easiest.

    – Peter Cordes
    Nov 20 '18 at 23:49













  • You don't need to AND before right shifting. Your 0xFF000000 mask keeps the high byte (2 nibbles = 2 hex digits = 2 Fs). But then right-shifting by 28 keeps only the high one. The AND was useless. :/ I think you can optimize down to add r0, r6, r4 LSR #28, if you have '0' in r6. I don't think ARM can barrel-shift a register in an instruction with an immediate. Or if you rotate r4 with mov r4, r4, ROL #4, you can and r0, r4, #0xF to use only 1 shift. And BTW, it would be clearer to use character literals like add r0,r0, #'0', if that's the right syntax.

    – Peter Cordes
    Nov 20 '18 at 23:52













  • Thanks - corrected. The 0xFF000000 was a typo, and the unnecessary AND was an oversight. :-) Not sure about the syntax for character literals so I didn't include them - didn't have the time to test! Agreed that there may be optimisations, but I wanted my code to be clear and to demonstrate the principles rather than to be optimal in any sense.

    – cooperised
    Nov 21 '18 at 12:50
















1












1








1







Masking and shifting, as suggested in the comments and in your answer, will get you the individual nibbles (half-bytes) that make up the word. But to print the number using putchar or equivalent, you'll need to convert these nibbles to ASCII characters. You don't need a 'switch-case' for this (or rather its equivalent in assembly language, a 'jump table'). You could use a lookup table, given that there will only be 16 entries, or you could conditionally add to the nibble to form a character.



The ASCII digits 0-9 have character codes 48-57. The uppercase letters have character codes starting at 65 for A (the lowercase letters start from 97) and of course 0xA represents the decimal value 10. So you can turn a nibble into a hex string by adding 55 to it if its value is 10 or more, and 48 otherwise. (Equivalently, add 48 unconditionally and add a further 7 to it if the resulting value is 58 or more.)



Note also that shifting right, as you suggest in your answer, will extract digits starting with the least-significant nibble, which is not what you want.



The following is untested and written off the top of my head, so no warranty, but it might set you on the right track:



    ; Assume number to be converted is in r4.  Note r4 is clobbered

; Initialise loop counter
MOV r5, #8
.loop
; Take most significant nibble from r4 into r0
MOV r0, r4, LSR #28

; Shift r4 for next time
MOV r4, r4, LSL #4

; For each nibble (now in r0) convert to ASCII and print
ADD r0, r0, #48
CMP r0, #58 ; did that exceed ASCII '9'?
ADDHS r0, r0, #7 ; add 'A' - ('0'+10) if needed
BL putchar

; Decrement loop counter, loop if not zero
SUBS r5, r5, #1
BNZ .loop





share|improve this answer















Masking and shifting, as suggested in the comments and in your answer, will get you the individual nibbles (half-bytes) that make up the word. But to print the number using putchar or equivalent, you'll need to convert these nibbles to ASCII characters. You don't need a 'switch-case' for this (or rather its equivalent in assembly language, a 'jump table'). You could use a lookup table, given that there will only be 16 entries, or you could conditionally add to the nibble to form a character.



The ASCII digits 0-9 have character codes 48-57. The uppercase letters have character codes starting at 65 for A (the lowercase letters start from 97) and of course 0xA represents the decimal value 10. So you can turn a nibble into a hex string by adding 55 to it if its value is 10 or more, and 48 otherwise. (Equivalently, add 48 unconditionally and add a further 7 to it if the resulting value is 58 or more.)



Note also that shifting right, as you suggest in your answer, will extract digits starting with the least-significant nibble, which is not what you want.



The following is untested and written off the top of my head, so no warranty, but it might set you on the right track:



    ; Assume number to be converted is in r4.  Note r4 is clobbered

; Initialise loop counter
MOV r5, #8
.loop
; Take most significant nibble from r4 into r0
MOV r0, r4, LSR #28

; Shift r4 for next time
MOV r4, r4, LSL #4

; For each nibble (now in r0) convert to ASCII and print
ADD r0, r0, #48
CMP r0, #58 ; did that exceed ASCII '9'?
ADDHS r0, r0, #7 ; add 'A' - ('0'+10) if needed
BL putchar

; Decrement loop counter, loop if not zero
SUBS r5, r5, #1
BNZ .loop






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 23 '18 at 10:09

























answered Nov 20 '18 at 21:27









cooperisedcooperised

1,444914




1,444914













  • For bases that aren't powers of 2, you don't really get a choice about starting from the LSD with repeated division. The usual way to deal with this is to start at the end of a buffer and decrement a pointer. When you're done, print from the current position. (example in C and x86 asm here: How do I print an integer in Assembly Level Programming without printf from the c library?). But yeah, given the choice, starting with the high nibble is easiest.

    – Peter Cordes
    Nov 20 '18 at 23:49













  • You don't need to AND before right shifting. Your 0xFF000000 mask keeps the high byte (2 nibbles = 2 hex digits = 2 Fs). But then right-shifting by 28 keeps only the high one. The AND was useless. :/ I think you can optimize down to add r0, r6, r4 LSR #28, if you have '0' in r6. I don't think ARM can barrel-shift a register in an instruction with an immediate. Or if you rotate r4 with mov r4, r4, ROL #4, you can and r0, r4, #0xF to use only 1 shift. And BTW, it would be clearer to use character literals like add r0,r0, #'0', if that's the right syntax.

    – Peter Cordes
    Nov 20 '18 at 23:52













  • Thanks - corrected. The 0xFF000000 was a typo, and the unnecessary AND was an oversight. :-) Not sure about the syntax for character literals so I didn't include them - didn't have the time to test! Agreed that there may be optimisations, but I wanted my code to be clear and to demonstrate the principles rather than to be optimal in any sense.

    – cooperised
    Nov 21 '18 at 12:50





















  • For bases that aren't powers of 2, you don't really get a choice about starting from the LSD with repeated division. The usual way to deal with this is to start at the end of a buffer and decrement a pointer. When you're done, print from the current position. (example in C and x86 asm here: How do I print an integer in Assembly Level Programming without printf from the c library?). But yeah, given the choice, starting with the high nibble is easiest.

    – Peter Cordes
    Nov 20 '18 at 23:49













  • You don't need to AND before right shifting. Your 0xFF000000 mask keeps the high byte (2 nibbles = 2 hex digits = 2 Fs). But then right-shifting by 28 keeps only the high one. The AND was useless. :/ I think you can optimize down to add r0, r6, r4 LSR #28, if you have '0' in r6. I don't think ARM can barrel-shift a register in an instruction with an immediate. Or if you rotate r4 with mov r4, r4, ROL #4, you can and r0, r4, #0xF to use only 1 shift. And BTW, it would be clearer to use character literals like add r0,r0, #'0', if that's the right syntax.

    – Peter Cordes
    Nov 20 '18 at 23:52













  • Thanks - corrected. The 0xFF000000 was a typo, and the unnecessary AND was an oversight. :-) Not sure about the syntax for character literals so I didn't include them - didn't have the time to test! Agreed that there may be optimisations, but I wanted my code to be clear and to demonstrate the principles rather than to be optimal in any sense.

    – cooperised
    Nov 21 '18 at 12:50



















For bases that aren't powers of 2, you don't really get a choice about starting from the LSD with repeated division. The usual way to deal with this is to start at the end of a buffer and decrement a pointer. When you're done, print from the current position. (example in C and x86 asm here: How do I print an integer in Assembly Level Programming without printf from the c library?). But yeah, given the choice, starting with the high nibble is easiest.

– Peter Cordes
Nov 20 '18 at 23:49







For bases that aren't powers of 2, you don't really get a choice about starting from the LSD with repeated division. The usual way to deal with this is to start at the end of a buffer and decrement a pointer. When you're done, print from the current position. (example in C and x86 asm here: How do I print an integer in Assembly Level Programming without printf from the c library?). But yeah, given the choice, starting with the high nibble is easiest.

– Peter Cordes
Nov 20 '18 at 23:49















You don't need to AND before right shifting. Your 0xFF000000 mask keeps the high byte (2 nibbles = 2 hex digits = 2 Fs). But then right-shifting by 28 keeps only the high one. The AND was useless. :/ I think you can optimize down to add r0, r6, r4 LSR #28, if you have '0' in r6. I don't think ARM can barrel-shift a register in an instruction with an immediate. Or if you rotate r4 with mov r4, r4, ROL #4, you can and r0, r4, #0xF to use only 1 shift. And BTW, it would be clearer to use character literals like add r0,r0, #'0', if that's the right syntax.

– Peter Cordes
Nov 20 '18 at 23:52







You don't need to AND before right shifting. Your 0xFF000000 mask keeps the high byte (2 nibbles = 2 hex digits = 2 Fs). But then right-shifting by 28 keeps only the high one. The AND was useless. :/ I think you can optimize down to add r0, r6, r4 LSR #28, if you have '0' in r6. I don't think ARM can barrel-shift a register in an instruction with an immediate. Or if you rotate r4 with mov r4, r4, ROL #4, you can and r0, r4, #0xF to use only 1 shift. And BTW, it would be clearer to use character literals like add r0,r0, #'0', if that's the right syntax.

– Peter Cordes
Nov 20 '18 at 23:52















Thanks - corrected. The 0xFF000000 was a typo, and the unnecessary AND was an oversight. :-) Not sure about the syntax for character literals so I didn't include them - didn't have the time to test! Agreed that there may be optimisations, but I wanted my code to be clear and to demonstrate the principles rather than to be optimal in any sense.

– cooperised
Nov 21 '18 at 12:50







Thanks - corrected. The 0xFF000000 was a typo, and the unnecessary AND was an oversight. :-) Not sure about the syntax for character literals so I didn't include them - didn't have the time to test! Agreed that there may be optimisations, but I wanted my code to be clear and to demonstrate the principles rather than to be optimal in any sense.

– cooperised
Nov 21 '18 at 12:50






















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53400875%2fconverting-integer-to-hex-string-in-arm-assembly%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

ComboBox Display Member on multiple fields

Is it possible to collect Nectar points via Trainline?