0

I have this piece of code in C and I want in nasm, decompose the 16bit to two 8bits, How Can I do it? C

uint16_t data = 0xCAFE; // global
uint8_t result[2];
...

decompose();
printf(
  "result %d %d \n", 
  result[0], result[1]
);

ASM

 global decompose
decompose:
  enter 0,0
  movzx ax, word[data],
  movzx al, [ax]
  leave
  ret

kopkaa
  • 61
  • 1
  • 9
  • Your assembly code never writes to `result`. Also, there's no `movzx r16, r/m16`. Just use a regular `mov`. – Michael Feb 16 '21 at 11:11
  • Depends on which byte that should be MS and LS, or if it should just be the same as CPU endianess. Anyway, simply study the bitwise operators, or find any of the numerous duplicates of this question here on the site. – Lundin Feb 16 '21 at 11:11
  • 3
    AX already is 2 separate registers, AH and AL. You're done after `movzx eax, word [data]` to efficiently load 16 bits into EAX (with the low 16 in AX). Or store AX to `[result]` if you want it there, just like `memcpy(result, &data, 2);`. Bytes are just bytes, copying more than one at once isn't special. – Peter Cordes Feb 16 '21 at 11:17
  • 1
    Or even better, make `result` an alias for `data`, or part of a union with it so you don't have to copy, it's just another C way of accessing the same underlying bytes. – Peter Cordes Feb 16 '21 at 11:20
  • Not quite a duplicate of [How to load a single byte from address in assembly](https://stackoverflow.com/q/20727379) / [Nasm - move value from a 4 byte register into an 1 byte address space](https://stackoverflow.com/q/59232265) / [How do AX, AH, AL map onto EAX?](https://stackoverflow.com/q/15191178) – Peter Cordes Feb 16 '21 at 11:44

1 Answers1

0

first: it is very bad design to create functions that have global side effects e.g. get their arguments or pass their results via globals.
second: there is absolutely no reason to use assembly on this. especially not if you pass the result to comparable slow printing routines.

If you really want to have functions for that I would suggest to introduce small inline functions

static inline uint8_t u16High(uint16_t v){ return (uint8_t)(v >> 8); }
static inline uint8_t u16Low (uint16_t v){ return (uint8_t)(v);      }

Another (in my eyes ugly) option would be:

static inline uint8_t* u16decompose(uint16_t* v){ return (uint8_t*)v; }

But beware: this only is allowed for uint8_t* you may not use this for 'decompose' uint32_t into uint16_t because this violates the strict aliasing rule.

vlad_tepesch
  • 6,681
  • 1
  • 38
  • 80