Electronics > Microcontrollers

Why do people not like Microchip?

<< < (41/47) > >>

woofy:

--- Quote from: Jan Audio on October 06, 2021, 02:31:26 pm ---They start asking for your email already if you want to download the latest compiler.

--- End quote ---

Microchip compilers are free to download, you do not have to give them an email address.
https://www.microchip.com/en-us/development-tools-tools-and-software/mplab-xc-compilers#Downloads

Jan Audio:
Ah better, they removed it.
I was getting suspicious.

Gotto be hard about these things, people dont care normally.

AaronD:

--- Quote from: MIS42N on October 06, 2021, 11:33:41 am ---...converting two characters into one byte. I came up with a bizarre way of doing it, I haven't seen it anywhere else. It doesn't check the data and alpha hex (A-F) has to be in upper case. It reads the hex output of MPLAB just fine:

--- Code: --- SWAPF CHAR1,W
ADDLW 0x55
BTFSS CHAR1,6 ; test if letter
ADDLW 0x71
; 2nd hex char
ADDWF CHAR2,W
BTFSS CHAR2,6 ; test if letter
ADDLW 0x07
--- End code ---

--- End quote ---

I'll...just take your word that that works.  I tried to prove it to myself before I left yesterday morning; I could see a little bit of a pattern emerging, but not the whole thing.

You assembler guys are something else.  You might be the best bit-twiddlers on the planet, and you produce the most compact and obfuscated code that I've seen, even compared to an optimizing compiler.  That's great, as long as the rest of us just take it as a black box that "just works" and don't try to wrap our minds around how.

T3sl4co1l:
I mean it doesn't look too bad to me, even though I'm not familiar with PIC ASM; but that is the catch, you have to know what things mean, and step through it and reason it out -- I know a few instruction sets, so it's not too alien to me.  If you don't know ASM at all, it's just a bunch of cryptic incantation; you sure as hell aren't going to know where to plop it into a project!

The constants 0x55, 0x71 and 0x07 look like offsets related to ASCII code, namely the ranges of letters, or the lack thereof.  Although I'm not sure how exactly they relate ('A' == 0x41 is a long way from 0x55?), I'd have to read the instruction set to see what exactly is being done.

So, that is to say: even for experts in related fields like myself, it may not exactly be useful, or even intelligible; your sarcasm is understandable!


A relevant example in C (if not an equivalent; but given the above is only 7 instructions, I don't think it does nearly the full thing either, just a snippet from the middle of such) might look like the two functions here,
https://github.com/T3sl4co1l/Reverb/blob/master/console.c#L275

Whereas in my linked C example, the constants are explicitly readable -- single-quoted letters are parsed as numeric constants, so you get precisely the range of letters converted as is written.  (Does use the assumption that ASCII is well-ordered, which, fortunately it is; this might not always be the case, like in the bad old days of EBCDIC!)  Note it also checks range more carefully, which might not be needed, and will take more instructions (to be exact, the whole function is 40 instructions on avr-gcc 8.1.0 -Os; that includes the helper function, which gets inlined; for a complete function that operates on a string, and even with GCC 8's very poor AVR optimizing, that's quite reasonable).

Tim

NorthGuy:

--- Quote from: T3sl4co1l on October 07, 2021, 03:58:00 pm ---Although I'm not sure how exactly they relate ('A' == 0x41 is a long way from 0x55?), I'd have to read the instruction set to see what exactly is being done.

--- End quote ---

That's quite straightforward actually. Letters 'A' to 'F' are encoded with codes 0x41 - 0x46, while numbers are encoded 0x30 to 0x31. Like symbol = number + 0x30. It would be nice if 'A' was encoded as 0x3a, 'B' as 0x3b etc, but the creators of ASCII were dumb and didn't do it this way. But we can fix it:


--- Code: ---uint8_t get_byte(char ch, char cl) {
  if (ch & 0x40) ch -= 7; // 'A' is changed from 0x41 to 0x3a, 'B' from 0x42 to 0x3b etc
  ch -= 0x30; // convert to a number

  if (cl & 0x40) cl -= 7; // same for the next character
  cl -= 0x30;
 
  return (ch << 4) + cl;
}
--- End code ---

Now, we can re-write this in assembler. It'll be a little bit dumb at first, as a non-optimized compiler:


--- Code: ---  movf ch,w   ; load ch
  btfsc ch,6  ; the next command is executed only if ch is a letter
  addlw 0xf9  ; subtract 7
  addlw 0xd0  ; subtract 0x30
  movwf ch    ; store the result
 
  movf cl,w   ; load cl
  btfsc cl,6  ; the next command is executed only if cl is a letter
  addlw 0xf9  ; subtract 7
  addlw 0xd0  ; subtract 0x30
  movwf cl    ; store the result
 
  swapf ch,w  ; shift (no barrel shifter, so swap instead)
  addwf cl,w  ; and add to get the result
--- End code ---

Now we can optimize it a bit. First, the cl calculation only used additions. Therefore, instead of storing the ch value and adding it at the end, we can simply keep it and add everything to it. This saves 3 instructions:


--- Code: ---  movf ch,w   ; load ch
  btfsc ch,6  ; the next command is executed only if ch is a letter
  addlw 0xf9  ; subtract 7
  addlw 0xd0  ; subtract 0x30
  swapf WREG,w   ; shift the result
   
  addwf cl,w  ; add cl to the result
  btfsc cl,6  ; the next command is executed only if cl is a letter
  addlw 0xf9  ; subtract 7
  addlw 0xd0  ; subtract 0x30
--- End code ---

Then, we can join the loading of ch with the swap. This will requite some intelligence in tweaking the constants to make sure the effect is the same, but will save one more instruction:


--- Code: ---  swapf ch,w  ; load and shift ch
  btfsc ch,6  ; the next command is executed only if ch is a letter
  addlw 0x8f  ; subtract 1 from lower nibble, add 9 to upper nibble
  addlw 0xfd  ; subtract 0x30, which is 0x03 after the shift
   
  addwf cl,w  ; add cl to the result
  btfsc cl,6  ; the next command is executed only if cl is a letter
  addlw 0xf9  ; subtract 7
  addlw 0xd0  ; subtract 0x30
--- End code ---

Finally, there are two unconditional additions, which can be united into one


--- Code: ---  swapf ch,w  ; load and shift ch
  btfsc ch,6  ; the next command is executed only if ch is a letter
  addlw 0x8f  ; subtract 1 from lower nibble, add 9 to upper nibble
  addwf cl,w  ; add cl to the result
  btfsc cl,6  ; the next command is executed only if cl is a letter
  addlw 0xf9  ; subtract 7
  addlw 0xcd  ; united addition
--- End code ---

Now, the only thing left is to remove comments. Lo and behold:


--- Code: ---  swapf ch,w
  btfsc ch,6
  addlw 0x8f   
  addwf cl,w
  btfsc cl,6
  addlw 0xf9
  addlw 0xcd
--- End code ---

You can re-write it in C as well, only C won't have a swap:


--- Code: ---uint8_t swap(uint8_t r) {
  return (r << 4) | (r >> 4);
}

uint8_t get_byte(char ch, char cl) {
  uint8_t x = swap(ch) + cl;
 
  if (ch & 0x40) x += 0x8f;
  if (cl & 0x40) x += 0xf9;
   
  return (x + 0xcd);
}
--- End code ---

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version