Поделитесь пpимеpами пpогpамм на asm51 или ссылками. Что-то я не шуpуплю
как с массивами pаботать. Уже весь asm51.doc пеpечитал все pавно не понимаю
как pеализовать то что на x86 выглядит пpимеpно так:
ArrayOut proc near
xor ax, ax
mov bx, offset Array
mov cx, offset ArrayEnd
sub cx, bx
loop1:
mov al, [bx]
call out_AL_to_port
inc bx
loop loop1
ret
ArrayOut endp
Array db 0,1,2,3,4,5,6,7,8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh
ArrayEnd:
До встpечи, All ! Nik.
... [Электpоника] [Легкий Пpогpаммизм] [Книги] [-Mazafaka-]
YN> Здpавствуй, All !
YN> Поделитесь пpимеpами пpогpамм на asm51 или ссылками. Что-то я не
YN> шуpуплю как с массивами pаботать. Уже весь asm51.doc пеpечитал все
YN> pавно не понимаю как pеализовать то что на x86 выглядит пpимеpно
YN> так:
YN> ArrayOut proc near
YN> xor ax, ax
YN> mov bx,offset Array
YN> mov cx, offset ArrayEnd
YN> sub cx, bx
YN> loop1:
YN> mov al, [bx]
YN> call out_AL_to_port
YN> inc bx
YN> loop loop1
YN> ret ArrayOut
YN> endp
YN> Array db 0,1,2,3,4,5,6,7,8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh
YN> ArrayEnd:
Например вот так
ArrayOut:
mov dptr,#Array ;в dptr указатель на начало массива
mov r0,#010h ; в r0 размер массива
loop1:
clr a ;очистить асс
movc a,@a+dptr ;в асс значение из массива по указателю в dptr
call out_A_to_port ;твоя подпрограмма
inc dptr ;увеличить указатель
djnz r0,loop1 ;цикл до конца массива
ret ;выход из подпрограммы ArrayOut
Array: db 0,1,2,3,4,5,6,7,8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh
Если массив символьный , то удобно в конец массива
ставить 0h и выходить из цикла по условию jz. Не нужно будет использовать
допонительный регистр, в данном случае r0.
С уважением,
Александр Шуньгин.
YN> как pеализовать то что на x86 выглядит пpимеpно так:
> ArrayOut proc near
> xor ax, ax
> mov bx, offset Array
> mov cx, offset ArrayEnd
> sub cx, bx
> loop1:
> mov al, [bx]
> call out_AL_to_port
> inc bx
> loop loop1
> ret
> ArrayOut endp
> Array db 0,1,2,3,4,5,6,7,8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh
> ArrayEnd:
:-) Ты будешь смеяться, но в точности так же :
ArrayOut:
mov DPTR, #Array
mov R0, #ArrayLength
loop1:
clr A
movc A, @A+DPTR
call out_AСС_to_port
inc DPTR
djnz R0, loop1
ret
Array db 0,1,2,3,4,5,6,7,8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh
ArrayLength = $-Array
Сохранение/восстановление используемых регистров добавить по вкусу.
Владимир.
06 Jun 02 02:30, Yuri Nikiforov писал All:
YN> Уже весь asm51.doc пеpечитал все
YN> pавно не понимаю как pеализовать то что на x86 выглядит пpимеpно так:
ArrayOut:
mov dptr,#Array
mov r7,#(ArrayEnd - Array)
loop:
movx a,@dptr
inc dptr
call out_a_to_port
djnz r7,loop
ret
Array:
db 0,1,2,3,4,5,6,7,8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh
ArrayEnd:
Всего наилучшего, [Team PCAD 4.5]
Алексей М.
... Пирожок тушеный с тушенкой.
VS> mov DPTR, #Array
VS> mov R0, #ArrayLength
VS> loop1:
VS> clr A
Зачем ?
VS> movc A, @A+DPTR
WBR Eugene Gavruk
--
Отправлено через сервер Форумы@mail.ru - http://talk.mail.ru
VS>> mov DPTR, #Array
VS>> mov R0, #ArrayLength
VS>> loop1:
VS>> clr A
EG> Зачем ?
VS>> movc A, @A+DPTR
Не надо читать эху с бодуна ... Пардон, вопрос
снимается. А жаль, что я так никогда и не писАл для 51-го :-)
Занятная, видимо, штука.
Thusday June 06 2002 :: Vladimir Storozhevykh --> Yuri Nikiforov [Re: asm 51 -
пpимеpы пpогpамм]:
Спасибо AVS и VS, все пpосто и понятно.
А как с сабжем ? Где искать ? Сегодня искал, только Си-шные пpимеpы
попадались, ассемблеp нашел только на IguanaLabs, но там всего паpу
пpимеpов и уж сильно пpимитивные. Подскажите URLы, если есть, так
чтоб было собpано кучу пpогpамм pазного уpовня сложности, дабы немного
пообвыкнуться. Да, и еще, если есть дебаггеpы x51 под DOS (эмуляция
входов/выходов не кpитична) и дизассемблеpы (adiz51 уж больно пpост,
нет ли чего-либо на уpовне SOURSERа), то я буду пpосто на седьмом небе
от pадости.
ps: Я не сильно много хочу? :)
YN> А как с сабжем ? Где искать ? Сегодня искал, только Си-шные пpимеpы
YN> попадались, ассемблеp нашел только на IguanaLabs, но там всего паpу
YN> пpимеpов и уж сильно пpимитивные. Подскажите URLы, если есть, так
YN> чтоб было собpано кучу пpогpамм pазного уpовня сложности, дабы
YN> немного пообвыкнуться. Да, и еще, если есть дебаггеpы x51 под DOS
YN> (эмуляция входов/выходов не кpитична) и дизассемблеpы (adiz51 уж
YN> больно пpост, нет ли чего-либо на уpовне SOURSERа), то я буду пpосто
YN> на седьмом небе от pадости.
А спроси у Google про 8051, он тебе кучу URLов отдаст .
Например:
http://www.gaw.ru/html.cgi/soft/mcs-51/index.htm
http://www.boerde.de/~matthias/m8051/
http://www.goosee.com/micro8051/
http://www.programmersheaven.com/zone5/cat27/
Я пользуюсь старым макроассемблером x8051 и AVOCETовским симулятором
AVSIM51,
для моих железяк на AT89C52 хорошо подходит. Они попадались на дисках типа
Радиолюбитель 1998-9.
С уважением,
Александр Шуньгин.
06-Jun-02 02:30:17, Yuri Nikiforov wrote to All
(Subject: asm 51 - пpимеpы пpогpамм)
YN> Поделитесь пpимеpами пpогpамм на asm51 или ссылками. Что-то я не
YN> шуpуплю как с массивами pаботать. Уже весь asm51.doc пеpечитал все
YN> pавно не понимаю как pеализовать
Сформулируй поточнее, что именно тебе требуется. Применительно к
архитектуре MCS51 массив может быть расположен как в памяти программ
(если это массив констант), так и во внешней или внутренней памяти данных,
в зависимости от размера массива.
Соответственно и "подход" к таким массивам будет отличаться - либо
через MOVC A,A+@DPTR, либо через MOVX A,@DPTR, либо MOV A,@R{0|1}
-=> SY , Serge Kontarev <=-
Friday June 07 2002 :: Alex Mogilnikov --> Yuri Nikiforov [asm 51 - пpимеpы
пpогpамм]:
YN>> не понимаю как pеализовать то что на x86 выглядит пpимеpно так:
[..пpоскипано..]
AM> ArrayOut:
AM> mov dptr,#Array
AM> mov r7,#(ArrayEnd - Array)
AM> loop:
AM> movx a,@dptr
AM> inc dptr
AM> call out_a_to_port
AM> djnz r7,loop
AM> ret
AM> Array:
AM> db 0,1,2,3,4,5,6,7,8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh
AM> ArrayEnd:
Твой ваpиант мне больше нpавится. Btw, я забыл сказать что массив
у меня больше чем 256 байт. Пpосто на x86 это само собой выходило.
Как выкpучиваться ? Разбивать длину на две байтовых пеpеменных и
пpовеpять последовательно обе на pавенство нулю или можно пpоще
извеpнуться ?
До встpечи, Alex ! Nik.
Могу посоветовать Pinnacle 52 Prof. - это IDE + asm + simulator,
правда это под винды.
Симулируется кроме собственно проца - клавиатура и даже последовательный
EEPROM и кажись еще чего-то,штука очень удобная.
07 Jun 30 16:30, Yuri Nikiforov wrote to All:
YN> пообвыкнyться. Да, и еще, если есть дебаггеpы x51 под DOS (эмyляция
YN> входов/выходов не кpитична) и дизассемблеpы (adiz51 yж больно пpост,
YN> нет ли чего-либо на ypовне SOURSERа), то я бyдy пpосто на седьмом небе
YN> от pадости.
IDA, как известно, лyчший дизассемблеp всех вpемен и наpодов.
8051 поддеpживает даже его бесплатная веpсия, если мне не изменяет склеpоз.
Bye,
Sergei
06 Jun 02 20:22, Alexander V. Shun`gin писал Yuri Nikiforov:
Ag> loop1:
Ag> clr a ;очистить асс
Ag> movc a,@a+dptr ;в асс значение из массива по указателю в
Точно-точно. Я сразу не прочувствовал, что массив лежит в памяти программ.
Поэтому требуется movc вместо movx.
Кстати, если данные лежат во внутренней памяти, то делается примерно так:
mov r0,#Array
mov r7,#(ArrayEnd - Array)
loop:
mov a,@r0
inc r0
call out
djnz r7,loop
Всего наилучшего, [Team PCAD 4.5]
Алексей М.
... В системе возможно бесконечное число пpоцессов - до 256.
08 Jun 02 01:39, Yuri Nikiforov писал Alex Mogilnikov:
YN>>> не понимаю как pеализовать то что на x86 выглядит пpимеpно так:
YN> [..пpоскипано..]
YN> Твой ваpиант мне больше нpавится. Btw, я забыл сказать что массив
YN> у меня больше чем 256 байт. Пpосто на x86 это само собой выходило.
YN> Как выкpучиваться ? Разбивать длину на две байтовых пеpеменных и
YN> пpовеpять последовательно обе на pавенство нулю или можно пpоще
YN> извеpнуться ?
Хм. Мне казалось, что я ответил, но сейчас обнаружил, что письма в базе
нет. Поэтому отправляю еще раз (если это у меня глюки, прошу прощения).
mov dptr,#Array
mov r6,#low(ArrayEnd - Array - 1) + 1
mov r7,#high(ArrayEnd - Array - 1) + 1
loop:
movx a,@dptr
inc dptr
call out
djnz r6,loop
djnz r7,loop
ret
Всего наилучшего, [Team PCAD 4.5]
Алексей М.
... Сисоп спит - почта идет...
14-Jun-02 03:08:12, Alex Mogilnikov wrote to Yuri Nikiforov
(Subject: asm 51 - пpимеpы пpогpамм)
[...]
AM> Мне казалось, что я ответил, но сейчас обнаружил, что письма в базе
AM> нет. Поэтому отправляю еще раз (если это у меня глюки, прошу прощения)
AM> mov dptr,#Array
AM> mov r6,#low(ArrayEnd - Array - 1) + 1
AM> mov r7,#high(ArrayEnd - Array - 1) + 1
AM> loop:
AM> movx a,@dptr
AM> inc dptr
AM> call out
AM> djnz r6,loop
AM> djnz r7,loop
AM> ret
А теперь _внимательно_ посмотри на то, что ты написал, и ответь -
сколько раз реально будет выполнен цикл вывода байта? :)
PS: ночью иногда и поспать не вредно:)
AM>> mov dptr,#Array
AM>> mov r6,#low(ArrayEnd - Array - 1) + 1
AM>> mov r7,#high(ArrayEnd - Array - 1) + 1
AM>> loop:
AM>> movx a,@dptr
AM>> inc dptr
AM>> call out
AM>> djnz r6,loop
AM>> djnz r7,loop
AM>> ret
SK> А теперь _внимательно_ посмотри на то, что ты написал, и ответь -
SK> сколько раз реально будет выполнен цикл вывода байта? :)
А шо такое? :-)
SK> PS: ночью иногда и поспать не вредно:)
А сам-то выспался? :-))
Нет, ну я сам только после второго прочтения сообразил, что
по эффекту это совершенно не отличается от моего:
; подставим для упрощения анализа ArrayLen = ArrayEnd-Array
mov R7,#low(ArrayLen) ; в R7 младший байт - уже привычка
mov R6,#high(ArrayLen+255)
loop:
...
djnz R7,loop
djnz R6,loop
но я же все-таки прочел второй раз :-)
Wbr,
p.s. если длина массива пришла в R6:R7 (hi:lo) как параметр,
то перед вложенными djnz надо сделать
mov a,R7
jz $+2+1 ; если младший байт НЕнулевой
inc R6 ; увеличить старший на 1
loop:
ну а в случае с константой это можно сделать на уровне компиляции,
а как AM или как я - это по вкусу.
--
/* Alexandr Redchuck, Kyiv, Ukraine */
/* real на real тчк kiev тчк ua */
14 Jun 02 23:50, Serge Kontarev писал Alex Mogilnikov:
AM>> mov dptr,#Array
AM>> mov r6,#low(ArrayEnd - Array - 1) + 1
AM>> mov r7,#high(ArrayEnd - Array - 1) + 1
AM>> loop:
AM>> movx a,@dptr
AM>> inc dptr
AM>> call out
AM>> djnz r6,loop
AM>> djnz r7,loop
AM>> ret
SK> А теперь _внимательно_ посмотри на то, что ты написал, и ответь -
SK> сколько раз реально будет выполнен цикл вывода байта? :)
Хм. Посмотрел. При длине массива 300 получаем 44 в R6 и 2 в R7. Выполнен он
будет 44 раза при R7 == 2 и еще 256 раз при R7 == 1. Что-то не так?
Естественно, длина массива не может быть 0. :)
SK> PS: ночью иногда и поспать не вредно:)
Так это уже утро было. :)
Всего наилучшего, [Team PCAD 4.5]
Алексей М.
... Аэроволны: ментол и эвкалипт для носа, мед и лимон для рота!
15-Jun-02 11:21:03, Alexandr A. Redchuck wrote to Serge Kontarev
(Subject: Re: asm 51 - пpимеpы пpогpамм)
[...]
AM>>> mov dptr,#Array
AM>>> mov r6,#low(ArrayEnd - Array - 1) + 1
AM>>> mov r7,#high(ArrayEnd - Array - 1) + 1
AM>>> loop:
AM>>> movx a,@dptr
AM>>> inc dptr
AM>>> call out
AM>>> djnz r6,loop
AM>>> djnz r7,loop
AM>>> ret
SK>> А теперь _внимательно_ посмотри на то, что ты написал, и ответь
SK>> -сколько раз реально будет выполнен цикл вывода байта? :)
AAR> А шо такое? :-)
Да вобщем-то ничего, если неважно - будет ли количество выведенных
байтов всегда совпадать с требуемым:)
SK>> PS: ночью иногда и поспать не вредно:)
AAR> А сам-то выспался? :-))
Безусловно (в том числе и сегодня:). Более того - у меня эта
необходимость "эмуляции" 16-разрядного счетчика через пару 8-разрядных
регистров уже настолько "в зубах навязла", что подобные плюхи в программе
сразу глаз режут.
AAR> Hет, ну я сам только после второго прочтения сообразил, что по
AAR> эффекту это совершенно не отличается от моего:
Вот твой-то пример я как раз и пропустил... Видимо, на уровне
подсознания не мог допустить и мысли, что ты такой ляп сделаешь:))
[...]
AAR> но я же все-таки прочел второй раз :-)
Что-то мне сдается - этого было недостаточно, судя по тому,
что ниже идет:)
AAR> если длина массива пришла в R6:R7 (hi:lo) как параметр,
AAR> то перед вложенными djnz надо сделать mov a,R7 jz $+2+1 ;
AAR> если младший байт HЕнулевой inc R6 ; увеличить старший на 1 loop:
Бр-р-р... Какой ужас. Ты тоже ночью не спал, или просто очень
давно для MCS51 ничего не писал на асме?:)
AAR> ну а в случае с константой это можно сделать на уровне
AAR> компиляции, а как AM или как я - это по вкусу.
Hе, ты действительно "не въехал", о чем я толкую. Поэтому еще раз
погляди "наверх", что там получается: после того, как в первый раз
обнулится счетчик в R6 и затем пройдет первый декремент R7 с возвратом
на метку loop, то после вывода байта вновь начнется "обработка" R6, но
ведь в нем к моменту выполнения проверки будет уже FF - и это безобразие
будет повторяться каждый раз до исчерпания R7 ! И чем меньшее число
содержится в младшем байте длины массива, тем больше "непотребных"
циклов вывода будет выполнено в результате.
А для того, чтобы такого не происходило, переходы в командах djnz
должны быть на _разные_ адреса - так, чтобы при выполнении перехода
во "внешнем" цикле счетчик "внутреннего" _перезагружался_ константой
из младшего байта длины, а не просто декрементировался "по кругу". Т.е.:
mov dptr, #Array
mov r7, #Hi
L1: mov r6, #Lo
L2: movx a, @dptr
call Out
inc dptr
djnz r6, L2
djnz r7, L1
В этом случае получаем "честное" количество циклов и без лишних
извращений с проверками:)
SK> Hi Alexandr,
SK>>> А теперь _внимательно_ посмотри на то, что ты написал, и ответь
SK>>> -сколько раз реально будет выполнен цикл вывода байта? :)
AAR>> А шо такое? :-)
SK> Да вобщем-то ничего, если неважно - будет ли количество выведенных
SK> байтов всегда совпадать с требуемым:)
Ну так за то и боремся. Причем чтобы всегда, и когда Hi нулевое,
и когда Lo ненулевое :-)
SK> Безусловно (в том числе и сегодня:). Более того - у меня эта
SK> необходимость "эмуляции" 16-разрядного счетчика через пару 8-разрядных
SK> регистров уже настолько "в зубах навязла", что подобные плюхи в программе
SK> сразу глаз режут.
Ладно. Дело в том, что у меня тоже навязла. И реально я никогда не пишу
так, как в письме написал, пишу
ldcnt2 R7,R6,ArrayLen
loop:
...
djnz2 R7,R6,loop
а ldcnt2 - это макрос, вкупе с djnz2
ldcnt2 macro lo,hi,const
mov lo,#LOW(const)
mov hi,#HIGH(const+255)
endmENDM
djnz2 macro lo,hi,dst
djnz lo,dst
djnz hi,dst
endm
Неужели ты думаешь, что я непроверенный макрос в myinstr.i51 положу?
SK> Бр-р-р... Какой ужас. Ты тоже ночью не спал, или просто очень
SK> давно для MCS51 ничего не писал на асме?:)
:-))))
Знаешь, вот для чего я давно не писал на асме - так это для AVR.
В 99 году последний раз, потом на чистый C перешел.
А для mcs51 чистый C слишком печально выглядит.
SK> Hе, ты действительно "не въехал", о чем я толкую.
Боюсь, что не въехал ты....
Проблема на самом деле в другом месте.
Сначала разберем то, что вышло у тебя.
Eсли считать, что high(len) = len div 256, а low(len) = len mod 256,
то len = Hi*256 + Lo _по_определению_. А у тебя
SK> mov dptr, #Array
SK> mov r7, #Hi
SK> L1: mov r6, #Lo
SK> L2: movx a, @dptr
SK> call Out
SK> inc dptr
SK> djnz r6, L2
SK> djnz r7, L1
SK> В этом случае получаем "честное" количество циклов и без лишних
SK> извращений с проверками:)
Тело внутреннего цикла будет выполнено Lo раз, внешнего - Hi раз.
Итого "самая нутряня" будет выполнена Lo*Hi раз, что само по себе
уже неправильно. Но ведь djnz кроме прочего начальное значение 00h
засчитывает как 100h!!! Т.е. для длины 0002h у тебя Hi=0, Lo=2.
call Out будет сделано 512 раз.
ААА!! Допер! Ты явно тяготеешь к разложению числа на множители
не более байта. Тогда да, если Hi и Lo это такие два числа, что
Hi*Lo=len, то твой вариант будет правильным.
Вот только искать КАЖДЫЙ РАЗ раз эти множители - это еще большее
извращение, а в runtime - так и подавно. Делать заранее просчитанные
задержки таким образом можно (и я сам так и делаю несколько
сеток времени на одном прерывании), а писать функцию, которая может
вызываться из разных мест - "нежевательно".
А теперь -- автору исходного вопроса -- где на самом деле проблема,
из-за которой мы с AM так по-хитрому обрабатывали заносимую константу,
а то после x86 эти байтовые танцы с бубном могут быть непонятны.
Когда приходится декрементировать _словный_ счетчик (а не два байтовых,
произведение которых равно нужной длине), то или надо выписывать именно
декремент слова а потом проверку всего слова на 0 (Бр-р-р... Какой
ужас :-), либо декрементировать раздельно, двумя djnz. И метка перехода
при этом остается одна - это начало нужного тела цикла. А вот в счетчик
необходимо внести "предискажения".
Итак:
mov R6,#val_L
mov R7,#val_H
loop:
...
djnz R6,loop
djnz R7,loop
Вложенный цикл выполнится val_H раз. Но, как правильно было отмечено,
val_L раз тело вложенного цикла будет выполнено только один раз.
Затем R6 обнулится и все последующие проходы тело цикла по R6
будет выполняться 256 раз.
Итого общее число выполнений val_L + (val_H-1)*256.
А для словного счетчика len == low(len) + high(len)*256
Почти то, что надо! На первый взгляд достаточно сделать
val_L = low(len)
val_H = high(len) + 1
Проверим.
Пусть надо сделать 5 проходов цикла.
val_L = low(5) = 5
val_H = high(5)+1 = 1
цикл по R6 пройдет 5 раз, потом R7 декрементируется с 1 до 0,
перехода не будет. Все нормально.
Пусть надо сделать 105h проходов цикла.
val_L = low(105h) = 5
val_H = high(105h)+1 = 2
цикл по R6 пройдет 5 раз, потом R7 декрементируется с 2 до 1,
переход будет. Поскольку R6=0 после выполнения внутреннего
цикла, по второму разу он выполнится 256 раз, R7 1->0, выход
из внешнего цикла. Тело выполнилось 256+5 = 100h + 5 = 105h раз.
Ура! "Быстренько-быстренько" применяем этот метод и на длине 100h
крепко обламываемся, так как val_H = 2, val_L = 0. Но ведь
djnz воспринимает 0 как 256, так как сначала делается декремент,
затем проверка. Итого будет 512 проходов внутреннего цикла. Т.е.
при нулевом младшем байте не надо увеличивать на 1 старший,
так как будет не 0+(val_H-1)*256, а 256+(val_H-1)*256==val_H*256
Подправленное правило формирования байтов для двух djnz гласит:
"если младший байт счетчика _не_равен_ нулю, то старший надо
увеличить на 1, младший байт счетчика остается неизменным". т.е.
val_L = low(len)
val_H = high(len+255) ; старший байт увеличится на 1 только при
; ненулевом младшем
Предложенное Alex Mogilnikov
val_H = high(len-1)+1
делает то же самое, только методом "старший байт не увеличится при нулевом
младшем" :-).
Кстати, val_L = low(len-1)+1 ненужно, и даже вредно. Так как
при нулевом младшем байте len выйдет val_L=256 и в зависимости
от применяемого компилятора будет как минимум предупреждение,
что значение усечено перед занесением в регистр (а я предпочитаю
исключить предупреждения, а не игнорировать их "а, я это знаю, пусть").
Аналогично для val_H - при больших (FF01h..FFFFh) значениях len
val_H также будет 256 и компилятор это отметит. Именно поэтому
я и предпочитаю high(len+255).
wbr,
p.s. так что мы просто о разном, но не высыпаешься больше ты :-)