LINUX.ORG.RU

сдвиг влево

 , ,


0

0

Вопрос банальный, но спрошу.

ID микроконтроллера задается тремя ногами от 000 до 111

как правильно вдвинуть эти биты в инт?

bool h; // high bit
bool m; // middle bit
bool l; // low bit

 uint8_t id;

1. id = h*4 + m*2 + l;

2. id = h;
   id = id<<1 | m;
   id = id<<1 | l;

3. id = h<<2 | m<<1 | l;

★★★★★

Последнее исправление: futurama (всего исправлений: 2)

Ответ на: комментарий от EXL
1.

       src/main.c:97: ID = gpio_pin_val_read(P0_1) + (gpio_pin_val_read(P0_2) * 2) + (gpio_pin_val_read(P0_3) * 4);
        mov     dpl,#0x01
        lcall   _gpio_pin_val_read
        mov     r7,dpl
        mov     dpl,#0x02
        push    ar7
        lcall   _gpio_pin_val_read
        mov     r6,dpl
        pop     ar7
        mov     a,r6
        add     a,r6
        add     a,r7
        mov     r6,a
        mov     dpl,#0x03
        push    ar6
        lcall   _gpio_pin_val_read
        mov     r7,dpl
        pop     ar6
        mov     a,r7
        add     a,r7
        add     a,acc
        mov     dptr,#_ID
        add     a,r6
        movx    @dptr,a
;       src/main.c:101: } //main()
        ret

2.

;       src/main.c:98: ID = gpio_pin_val_read(P0_3);
        mov     dpl,#0x03
        lcall   _gpio_pin_val_read
        mov     r7,dpl
        mov     dptr,#_ID
        mov     a,r7
        movx    @dptr,a
;       src/main.c:99: ID = (ID<<1) | gpio_pin_val_read(P0_2);
        mov     a,r7
        add     a,r7
        mov     r7,a
        mov     dpl,#0x02
        push    ar7
        lcall   _gpio_pin_val_read
        mov     r6,dpl
        pop     ar7
        mov     a,r7
        orl     ar6,a
        mov     dptr,#_ID
        mov     a,r6
        movx    @dptr,a
;       src/main.c:100: ID = (ID<<1) | gpio_pin_val_read(P0_1);
        mov     a,r6
        add     a,r6
        mov     r6,a
        mov     dpl,#0x01
        push    ar6
        lcall   _gpio_pin_val_read
        mov     r7,dpl
        pop     ar6
        mov     dptr,#_ID
        mov     a,r7
        orl     a,r6
        movx    @dptr,a
;       src/main.c:101: } //main()

3
;       src/main.c:98: ID = gpio_pin_val_read(P0_3)<<2 | gpio_pin_val_read(P0_2)<<1 | gpio_pin_val_read(P0_1);
        mov     dpl,#0x03
        lcall   _gpio_pin_val_read
        mov     a,dpl
        add     a,dpl
        add     a,acc
        mov     r7,a
        mov     dpl,#0x02
        push    ar7
        lcall   _gpio_pin_val_read
        mov     r6,dpl
        pop     ar7
        mov     a,r6
        add     a,r6
        orl     ar7,a
        mov     dpl,#0x01
        push    ar7
        lcall   _gpio_pin_val_read
        mov     r6,dpl
        pop     ar7
        mov     dptr,#_ID
        mov     a,r6
        orl     a,r7
        movx    @dptr,a
;       src/main.c:99: } //main()
futurama ★★★★★
() автор топика
Ответ на: комментарий от alysnix
CC  = sdcc
# Program to use for the linker
LK = sdcc

# Flags for above programs when calling them from the command line
DFLAGS = -MM $(INCDIRS) $<
CFLAGS = --model-large --std-c99 $(INCDIRS) -c $< -o "$(OBJDIR)/"
LFLAGS = --model-large --code-loc 0x0000 --code-size 0x4000 --xram-loc 0x0000 --xram-size 0x400 -o $(MAINIHX) $(LIBDIRS)/* $(OBJFILES)
futurama ★★★★★
() автор топика
Последнее исправление: futurama (всего исправлений: 1)
Ответ на: комментарий от Morin

беззнаковый сдвиг…это ж самая примитивная операция для реализации в железе. за один такт должна делаться, просто биты перегоняются в одну сторону, плюс кой чего еще.

alysnix ★★★
()
Ответ на: комментарий от futurama

вообще правильно, канонично, наглядно, это как уже сказали - третий вариант. но правильный компилятор(с наворотами в оптимизации), типа gcc, должен превратить все три варианта в один и тот же асм. это если оптимизации включены, типа -02. но тут компилятор свой и потому вопросы снимаются.

alysnix ★★★
()
Ответ на: комментарий от futurama

Вот твой второй интересно посмотреть в ассемблере. Гляну сейчас.

Разлапистый код получился из-за условных переходов (тут оператор ?)

futurama ★★★★★
() автор топика
Ответ на: комментарий от alysnix

MCU 8051? gcc не умеет

sdcc

Optimization options:
      --nooverlay           Disable overlaying leaf function auto variables
      --nogcse              Disable the GCSE optimisation
      --nolabelopt          Disable label optimisation
      --noinvariant         Disable optimisation of invariants
      --noinduction         Disable loop variable induction
      --noloopreverse       Disable the loop reverse optimisation
      --no-peep             Disable the peephole assembly file optimisation
      --no-reg-params       On some ports, disable passing some parameters in registers
      --peep-asm            Enable peephole optimization on inline assembly
      --peep-return         Enable peephole optimization for return instructions
      --no-peep-return      Disable peephole optimization for return instructions
      --peep-file           <file> use this extra peephole file
      --opt-code-speed      Optimize for code speed rather than size
      --opt-code-size       Optimize for code size rather than speed
      --max-allocs-per-node  Maximum number of register assignments considered at each node of the tree decomposition
      --nolospre            Disable lospre
      --allow-unsafe-read   Allow optimizations to read any memory location anytime
      --nostdlibcall        Disable optimization of calls to standard library

futurama ★★★★★
() автор топика
Последнее исправление: futurama (всего исправлений: 1)
Ответ на: комментарий от futurama

Как я вижу по ассемблеру I и III варианты примерно одинаковые

суммирование более дорогая операция чем OR битов, по самой теории. поскольку суммирование предполагает перенос, а OR - нет. и если любой нетупой компиллятор поймет, что беззнаковое умножение на степень двойки это сдвиг, то суммирование он на OR не заменит. самый правильный и дешевый вариант - 3. потому что он делает ровно то, что ты хочешь сделать.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от futurama

В твоём выводе sdcc есть такая строчка

--opt-code-speed      Optimize for code speed rather than size

А в твоём Makefile такого флага я не вижу.

Попробуй добавить к CFLAGS и посмотреть изменится ли ассемблерный вывод?

fsb4000 ★★★★★
()
Ответ на: комментарий от PPP328

Всё зависит от камня. Бывают случаи когда «+» может быть быстрее. Например когда нет shl/shr на определенное количество бит, есть только на 1 (например 6502 ca65)

это OR можно заменить на суммирование, а не сдвиг.

сдвиг на n разрядов, это подобно беззнаковому умножению/делению на степень двойки. сомнительно что в проце есть быстрое умножение/деление, но нет сдвига на n разрядов. скорее наоборот.

сдвиг на n разрядов технически очень же простой, а вот умножение/деление - в железе сложно.

alysnix ★★★
()
Ответ на: комментарий от alysnix

Дядь, я вам только что рассказал про 6502 камень, у которого ADC (сложение регистра и памяти) - это одна железная инструкция. А Shr/Shl N банально нет. Только делать цикл и долбить ASL/LSR (сдвиг регистра на один бит) N раз.

сомнительно что в проце есть быстрое умножение/деление

Речь про умножение вообще не идет, его там нет. Зачем вам умножение для A << N | B << M ?

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

Дядь, я вам только что рассказал про 6502 камень, у которого ADC (сложение регистра и памяти) - это одна железная инструкция. А Shr/Shl N банально нет. Только делать цикл и долбить ASL/LSR (сдвиг регистра на один бит) N раз.

какое отношение сложение имеет к сдвигу? как можно сдвиг эмулировать сложением?

эта ваша фраза о чем? каким сложением можно эмулировать сдвиг на 6 разрядов например?

Бывают случаи когда «+» может быть быстрее. Например когда нет shl/shr на определенное количество бит, есть только на 1 (например 6502 ca65)

alysnix ★★★
()
Ответ на: комментарий от Morin

и ты точно хорошо понял 3ий вариант, а ведь там двигают на 2 разряда)))

датышо!

ps. если в конкретном камне нет сдвига на более чем разряд, то второй способ может быть быстрей, поскольку в нем только два сдвига, а в третьем - три. но такой конкретный камень не обсуждался.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

мда, спеси поубавим ;)

что такое сдвиг влево и вправо на бит? подсказка, можно выразить как деление или умножение на 2, как выглядит умножение на сумматоре, сюрприз - это сложение

про паттерн я не просто так тоже задал вопрос, простейший это тоже 1 бит, и сюрприз, сдвигать можно 0ом или 1ей

Morin ★★★★
()
Последнее исправление: Morin (всего исправлений: 1)
Ответ на: комментарий от alysnix

какое отношение сложение имеет к сдвигу? как можно сдвиг эмулировать сложением?

эта ваша фраза о чем? каким сложением можно эмулировать сдвиг на 6 разрядов например?

О божечки-кошечки, да прочтите вы наконец моё сообщение.

Ваше утверждение

суммирование более дорогая операция чем OR битов, по самой теории

ложно, потому что я уже назвал вам платформу, где суммирование имеет такую же сложность, что и OR.

PPP328 ★★★★★
()
Ответ на: комментарий от Morin

что такое сдвиг влево и вправо на бит? подсказка, можно выразить как деление или умножение на 2, как выглядит умножение на сумматоре, сюрприз - это сложение

ты как бы намекаешь, что чтобы умножить миллион на миллион… надо миллион раз прибавить миллион к нулю??? спасибо. но так не умножают. гы

alysnix ★★★
()
Ответ на: комментарий от PPP328

ложно, потому что я уже назвал вам платформу, где суммирование имеет такую же сложность, что и OR.

и что за платформа? вы вроде ничто не назвали.

вы не поняли моей фразы. я просто сказал, что OR не требует переноса, и потому, даже теории проще. вне зависимости от платформ. то есть устройство, осуществляющее операцию OR схемотехнически проще, чем осуществляющее полновесное сложение битов с переносом. вы с этим спорите?

alysnix ★★★
()
Ответ на: комментарий от Morin

я как бы намекаю, что тебе надо почитать основы цифровой логики, первые алу кроме сумматора не имели нихрена, от слова совсем

а я как бы намекаю, что умножения на таких алу делались алгоритмически с вычислением поразрядных произведений и их суммированием. а не просто «суммированием».

alysnix ★★★
()
Царь: вызывает антирес ваш питательный процесс: как у вас там пють какаву - с сахарином, али без?
Посол: йес
Царь: вызывает антирес ваш технический прогресс: как у вас там сеють брюкву - с кожурою, али без?
Посол: йес
Царь: вызывает антирес вот ещё какой разрез: как у вас там ходють бабы - в панталонах, али без?
Посол: йес

и оный топик в аналогичном духе.. 🤦‍♂️

aol ★★★★★
()
Последнее исправление: aol (всего исправлений: 1)
Ответ на: комментарий от PPP328

Ну молодец, вот только твоя математическая модель всосала на реальной платформе.

что за модель? вернитесь в топик. вопрос был такой -

Вопрос банальный, но спрошу. ID микроконтроллера задается тремя ногами от 000 до 111 как правильно вдвинуть эти биты в инт?

причем тут асм какого-то конкретного проца с помойки, вопрос ж был про си, и не пойми какого проца.

alysnix ★★★
()
Ответ на: комментарий от alysnix

что за модель?

То есть вы даже собственные сообщения не читаете? Класс. Какой смысл тогда иметь с вами дискуссию.

конкретного проца с помойки

Охлол

PPP328 ★★★★★
()
Последнее исправление: PPP328 (всего исправлений: 1)
Ответ на: комментарий от PPP328

Охлол

судя по lda… это какая-то аккумуляторная хрень с парой еще регистров, архитектуре которой лет стописят с хвостиком. это даже не помойка, а окаменелости. спасибо за ценный код на асме.

alysnix ★★★
()
Ответ на: комментарий от futurama

По-моему, разница между тремя вариантами съедается на фоне использования lcall для доступа к биту GPIO и обрамляющего сохранения и восстановления контекста.

p.s. 3 вариант более читабельный в общем случае, если захардкоженные величины сдвигов будут заменены на макроопределения

qbe
()
Ответ на: комментарий от futurama

ID = gpio_pin_val_read(P0_1) + (gpio_pin_val_read(P0_2) * 2) + (gpio_pin_val_read(P0_3) * 4);

и наоборот, если не предполагается менять местами пины, а религия позволяет обращаться к портам в обход NRF SDK, то можно считывание ID сократить так:

ID = (P0 >> 1) & 0x07;
qbe
()